# Deploy your application



This is the operator reference for the desktop release flow. The conceptual picture lives in [Release pipeline](/pear/explanation/deployment-releasing-apps-p2p); the type-along path is in [Ship your app](/p2p/getting-started/build-a-peer-to-peer-chat/ship) and [Deploy over-the-air updates](/p2p/getting-started/build-a-peer-to-peer-chat/update). Use this page when you need exact commands for the eight **Foundational Steps**.

<Callout type="info">
  Building a React Native or Expo app? Steps 3 and 4 below (make distributables, build the deployment directory) work differently on mobile—see [Deploy your mobile application](/pear/how-to/operate-an-app/manual-deployment/mobile) for the mobile "Build the OTA payload" equivalent. Steps 0, 1, 2, 5, 6, and 7 are identical on both platforms.
</Callout>

<Callout type="info">
  For the simplest publish/update workflow, let CI stage for you. [Publish with GitHub Actions](/pear/how-to/operate-an-app/github-actions/publish-with-github-actions) turns shipping a new version into a `git push`. This page is the full-control path when you need release lines, provision, and multisig.
</Callout>

Each step is independent—you can stop at any point if your project is still in proof-of-concept. The first three (`touch`, `upgrade link`, `version`) are setup; the next four (`make`, `pear build`, `stage`, `provision`) are the **release cycle** you repeat for every shipment; the final step (`multisig`) gates production.

## 0. Touch and seed [#0-touch-and-seed]

Mint a new `pear://` link backed by a fresh [Hypercore](/p2p/reference/building-blocks/hypercore):

```sh skip="release-flow"
pear touch
# pear://qxenz5wmspmryjc13m9yzsqj1conqotn8fb4ocbufwtz9mtbqq5o
```

Announce the link on the swarm:

```sh skip="release-flow"
pear seed pear://qxenz5wmspmryjc13m9yzsqj1conqotn8fb4ocbufwtz9mtbqq5o
```

Run `pear seed` on at least one always-online machine so peers can fetch updates while developer laptops are asleep. On every other machine that should reseed, run the same command—additional seeders raise availability and shorten the [first-connection latency](/pear/how-to/operate-an-app/manual-deployment/troubleshoot-desktop-releases#seeder-came-online-after-the-client).

## 1. Set the upgrade link [#1-set-the-upgrade-link]

Every shipped build polls a `pear://` link from its `package.json` `upgrade` field. Set it once per [release line](/pear/explanation/deployment-releasing-apps-p2p#release-lines):

```sh skip="release-flow"
npm pkg set upgrade=pear://qxenz5wmspmryjc13m9yzsqj1conqotn8fb4ocbufwtz9mtbqq5o
```

Or edit `package.json` directly:

```json skip="release-flow"
{
  "version": "1.0.0",
  "upgrade": "pear://qxenz5wmspmryjc13m9yzsqj1conqotn8fb4ocbufwtz9mtbqq5o"
}
```

For production, set `upgrade` to the **multisig** link (see [Set up multisig](/pear/how-to/operate-an-app/multisig/set-up-multisig)). For internal preview, set it to the **provision** link ([step 6](#6-provision)). For developer-team builds, set it to a **stage** link ([step 5](#5-stage)). The link decides which release line a binary follows.

## 2. Version [#2-version]

[`pear-runtime`](/pear/reference/pear/runtime) only swaps the application drive if the new build advertises a higher version:

```sh skip="release-flow"
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease]
```

`npm version` rewrites `package.json` and creates a `vX.Y.Z` git tag. If this is the first release, leave `version` at `1.0.0` and skip to step 3.

## 3. Make distributables [#3-make-distributables]

Run `npm run make` on each OS you ship (macOS, Linux, Windows, or CI workers per platform):

```sh skip="release-flow"
npm run make   # .app + .dmg on macOS; .AppImage on Linux; .msix on Windows
```

The full coverage—entitlements, code signing, notarization, MSIX publisher matching, signing certificates—is in [Build desktop distributables](/pear/how-to/operate-an-app/build-and-package/build-desktop-distributables).

The `package.json` checklist before a make:

* `author` populated
* `license` populated
* `description` populated
* `name` set per brand
* `productName` set per brand
* `build/icon.icns` (macOS), `build/icon.ico` (Windows), `build/icon.png` (Linux) are per brand

## 4. Build the deployment directory [#4-build-the-deployment-directory]

`pear build` assembles per-OS makes into the multi-architecture **deployment directory** layout `pear stage` expects. It is part of the `pear` CLI, so there is nothing extra to install—run it as `pear build` (or `npx pear build`).

The expected layout:

```text skip="layout-illustration"
pear-chat-1.0.1/
├─ package.json
└─ by-arch/
   └─ <platform-arch>/
      └─ app/
```

Run `pear build` from **outside** the application folder (see [stage size increases](/pear/how-to/operate-an-app/manual-deployment/troubleshoot-desktop-releases#pear-stage-shows-huge-size-growth)). Pass each make's output via `--<platform-arch>-app` and pick a `--target` name:

```sh skip="release-flow"
pear build \
  --package=./pear-chat/package.json \
  --darwin-arm64-app ./pear-chat/out/PearChat-darwin-arm64/PearChat.app \
  --darwin-x64-app   ./pear-chat/out/PearChat-darwin-x64/PearChat.app \
  --linux-arm64-app  ./pear-chat/out/PearChat-linux-arm64/PearChat.AppImage \
  --linux-x64-app    ./pear-chat/out/PearChat-linux-x64/PearChat.AppImage \
  --win32-x64-app    ./pear-chat/out/PearChat-win32-x64/PearChat.msix \
  --target pear-chat-1.0.1
```

If you omit `--target`, the deployment directory is named `<name>-<version>` from `package.json`. Each make produces a single platform-arch on its own machine—transfer the build outputs to the build machine first, then assemble.

## 5. Stage [#5-stage]

`pear stage <upgrade-link> <deployment-directory>` syncs the directory into the [Hypercore](/p2p/reference/building-blocks/hypercore) behind the link.

Always dry-run first and read the file-by-file diff:

```sh skip="release-flow"
pear stage --dry-run pear://qxenz5wmspmryjc13m9yzsqj1conqotn8fb4ocbufwtz9mtbqq5o ./pear-chat-1.0.1
```

Look for:

* Files you expect to ship
* No surprise additions (`.DS_Store`, editor swap files, secrets, deployment directories nested inside the app)
* Sensible byte counts

Run the real stage:

```sh skip="release-flow"
pear stage pear://qxenz5wmspmryjc13m9yzsqj1conqotn8fb4ocbufwtz9mtbqq5o ./pear-chat-1.0.1
```

The output should match the dry-run diff line for line. If anything differs, abort and investigate before continuing.

### Stage checklist [#stage-checklist]

* Always dry-run first.
* Check the dry-run output diff.
* Compare the live stage output to the dry-run output diff.

### Confirm stage updates [#confirm-stage-updates]

Open the app on a second machine. The seeding process from step 0 should show peers joining as instances connect. To verify the update flow:

1. Change a file.
2. `npm version patch`.
3. `npm run make`.
4. `pear build`.
5. `pear stage`.

If `upgrade` points to the stage link, every connected instance should fire the `updated` event from [`pear.updater`](/pear/reference/pear/runtime) (and, in the template, surface an "Update ready" button).

## 6. Provision [#6-provision]

`pear stage` is append-only—every file you ever staged stays in the core history. `pear provision` resyncs from a stage link onto a target link while compacting deletions, producing a leaner drive for prerelease distribution.

The signature is:

```sh skip="release-flow"
pear provision <versioned-source-link> <target-link> <versioned-production-link>
```

A **versioned link** has the form `pear://<fork>.<length>.<key>`. Copy it from the most recent `pear stage` output—the link printed under the `^Latest:` line at the end (the versioned link at the top of the output shows the drive *before* that stage).

The target link is a fresh `pear://` from step 0. While bootstrapping, set the third argument (the versioned production link) to `pear://0.0.<target-key>`; after a multisig drive exists, use `pear://<fork>.<length>.<multisig-key>` instead.

Dry-run first:

```sh skip="release-flow"
pear provision --dry-run \
  pear://0.1079.qxenz5wmspmryjc13m9yzsqj1conqotn8fb4ocbufwtz9mtbqq5o \
  pear://q9sopzoqgas9usoiq7uzkkwngm5pzj4zo3n4esjwwbmw6offis8o \
  pear://0.0.q9sopzoqgas9usoiq7uzkkwngm5pzj4zo3n4esjwwbmw6offis8o
```

Read the diff and run for real:

```sh skip="release-flow"
pear provision \
  pear://0.1079.qxenz5wmspmryjc13m9yzsqj1conqotn8fb4ocbufwtz9mtbqq5o \
  pear://q9sopzoqgas9usoiq7uzkkwngm5pzj4zo3n4esjwwbmw6offis8o \
  pear://0.0.q9sopzoqgas9usoiq7uzkkwngm5pzj4zo3n4esjwwbmw6offis8o
```

### Switching builds to provision [#switching-builds-to-provision]

Update `package.json`:

* `upgrade` → the provision link (step 1)
* `version` → bumped (step 2)

Make, `pear build`, and stage again. Then provision a second time so the source link points at the provision target:

```sh skip="release-flow"
pear provision pear://0.1080.qxenz5wmspmryjc13m9yzsqj1conqotn8fb4ocbufwtz9mtbqq5o pear://q9sopzoqgas9usoiq7uzkkwngm5pzj4zo3n4esjwwbmw6offis8o pear://0.0.q9sopzoqgas9usoiq7uzkkwngm5pzj4zo3n4esjwwbmw6offis8o
```

### Provision checklist [#provision-checklist]

* Always dry-run first.
* Check the dry-run output diff before provisioning.

## 7. Multisig [#7-multisig]

Production releases are gated by a **multisig** drive—a [Hypercore](/p2p/reference/building-blocks/hypercore) whose write access is controlled by a quorum of signing keys instead of one machine's private key. This is what removes the single point of failure from a typical desktop release flow, and unlike stage and provision drives, a multisig drive is **not** machine-bound.

Multisig has a one-time setup and a repeatable per-release flow, each covered in its own guide:

* [Set up multisig](/pear/how-to/operate-an-app/multisig/set-up-multisig)—generate signing keys, configure `pear.json`, compute the multisig link, and point `upgrade` at it. Do this once.
* [Sign with multisig](/pear/how-to/operate-an-app/multisig/sign-with-multisig)—prepare a request, collect a quorum of signatures, verify, and commit the production drive. Repeat for every release.
* [Troubleshoot multisig](/pear/how-to/operate-an-app/multisig/troubleshoot-multisig)—refused requests, interrupted commits, `INCOMPATIBLE_SOURCE_AND_TARGET`, and recovering lost write access.

## 8. Store submissions (optional) [#8-store-submissions-optional]

Beyond peer-to-peer distribution, the Linux distributables from [step 3](#3-make-distributables) can also be packaged for platform application stores—**Flathub** (Flatpak) and the **Snap Store**. Store installs complement the flow above: an app installed from a store still updates over the air through the same staged and multisig-gated releases.

See [Submit to app stores](/pear/how-to/operate-an-app/build-and-package/submit-to-app-stores) for the manifest preparation, local testing, submission, and release-automation steps of both flows.

## Disabling updates [#disabling-updates]

Pass `--no-updates` per run to skip the OTA check (matches `hello-pear-electron`'s default `npm start` script):

```sh skip="release-flow"
npm start -- --no-updates
```

To disable updates for every run of a build, construct the runtime with `updates: false` (see [`pear-runtime`](/pear/reference/pear/runtime#disabling-updates)):

```js skip="snippet-illustration"
const PearRuntime = require('pear-runtime')
const { version, upgrade, name } = require('../package.json')
const pear = new PearRuntime({
  dir,
  version,
  upgrade,
  name,
  updates: false
  // ... other options
})
```

This is useful for kiosk binaries or air-gapped distributions where OTA must be off.

## Release lines and multiple stage drives [#release-lines-and-multiple-stage-drives]

A typical project keeps several stage drives in parallel—`development`, `staging`, `rc`, plus any number of custom lines for experiments or hotfixes. Each line has its own `pear://` link from step 0 and its own seeded reseeders.

Production has exactly one chain: `rc` → provision (`prerelease`) → multisig (`production`). The `rc` build's `upgrade` field points at the multisig link, so `rc` builds do not receive OTA updates—every `rc` iteration requires a new installer. The [Release pipeline](/pear/explanation/deployment-releasing-apps-p2p#release-lines) explanation has the conceptual picture.

To bootstrap a new release line:

1. Run step 0 to mint and seed a new link.
2. Run step 1 in a build dedicated to that line.
3. Skip step 2—the line starts at the current `version`.
4. Run steps 3 and 4 to produce a build.
5. The build is now pointed at the new line; share it with whoever should follow that line.

## See also [#see-also]

* [Set up multisig](/pear/how-to/operate-an-app/multisig/set-up-multisig)—one-time signing-key, config, and link setup for the production gate.
* [Sign with multisig](/pear/how-to/operate-an-app/multisig/sign-with-multisig)—the per-release prepare → sign → verify → commit flow.
* [Troubleshoot multisig](/pear/how-to/operate-an-app/multisig/troubleshoot-multisig)—refused requests, interrupted commits, and recovering lost write access.
* [Publish with GitHub Actions](/pear/how-to/operate-an-app/github-actions/publish-with-github-actions)—the simplest publish/update workflow, staging from CI on every push.
* [Release pipeline](/pear/explanation/deployment-releasing-apps-p2p)—conceptual diagrams for stage, provision, multisig, and release lines.
* [Build desktop distributables](/pear/how-to/operate-an-app/build-and-package/build-desktop-distributables)—per-OS makes, signing, notarization, and MSIX publisher details.
* [Submit to app stores](/pear/how-to/operate-an-app/build-and-package/submit-to-app-stores)—Flathub and Snap Store packaging on top of the Linux distributables.
* [Desktop release npm scripts](/pear/reference/ci-and-release/desktop-release-npm-scripts)—the `package.json` scripts that drive this flow.
* [Publish a changelog for your app](/pear/how-to/operate-an-app/publish-a-changelog)—ship a `CHANGELOG.md` so users read release notes with `pear changelog`.
* [Troubleshoot desktop releases](/pear/how-to/operate-an-app/manual-deployment/troubleshoot-desktop-releases)—OTA, seeding, deployment-folder, and lost write-access pitfalls.
* [Release pipeline glossary](/pear/explanation/deployment-releasing-apps-p2p#glossary)—terminology.
* [`pear-ci` GitHub Action reference](/pear/reference/ci-and-release/pear-ci-action)—inputs, outputs, and the CLI behind CI publishing.
* [`pear-runtime` reference](/pear/reference/pear/runtime)—the runtime that drives OTA on the client.
* [Storage and distribution](/pear/explanation/storage-and-distribution)—how releases reach users.
