# Storage and distribution



Pear stores everything—the runtime itself, every installed application, and each application's persistent data—under a single per-OS directory. New versions of an application reach users through the same peer-to-peer swarm that distributes data inside the application; there is no central server. This page explains the on-disk layout and the distribution model, and the trade-offs that motivate both.

## On-disk layout [#on-disk-layout]

The top-level directory depends on the operating system:

| OS      | Pear directory                       |
| ------- | ------------------------------------ |
| macOS   | `~/Library/Application Support/pear` |
| Linux   | `~/.config/pear`                     |
| Windows | `%USERPROFILE%\AppData\Roaming\pear` |

Inside that directory:

* **`current`**—a symlink to the Pear platform binary that's currently active. The platform itself is delivered the same way an application is: by the swarm. Updating Pear means re-pointing this symlink.
* **`corestores/`**—every installed application, stored as a [Corestore](/p2p/reference/helpers/corestore) of [Hyperdrives](/p2p/reference/building-blocks/hyperdrive). One corestore per application; one Hyperdrive per logical bundle (binaries plus assets).
* **`app-storage/`**—application-private persistent data, keyed by the application's `dkey` (derived from its `pear://` link). This is where chat history, drafts, settings, and user content live. Each subdirectory is its own corestore again, scoped to one application.

In a running application, the path you'd write to is exposed as [`Pear.config.storage`](/pear/reference/pear/api#pearconfig-object); the platform root is [`Pear.config.pearDir`](/pear/reference/pear/api#pearconfig-object).

A practical consequence of this layout: you can't browse the on-disk files with Finder or a file manager and expect to see the application's actual content. Everything is encoded inside hyperdrives. To read what an installed application actually distributed, use [`pear dump`](/pear/reference/pear/cli#pear-dump-flags-link-dir)—it materializes the hyperdrive's contents back into ordinary files.

### Application storage in development vs production [#application-storage-in-development-vs-production]

The directories above are the **platform**'s storage. An **application** embedded in [Electron](/p2p/getting-started/build-a-peer-to-peer-chat/reshape-into-a-production-app)—the `dir` field passed to `new PearRuntime({ dir, ... })`—lives in a different per-OS location, and it differs between development and packaged builds:

| OS      | Packaged                                      | Development (no packaged app) |
| ------- | --------------------------------------------- | ----------------------------- |
| macOS   | `~/Library/Application Support/<productName>` | `<tmpdir>/pear/<productName>` |
| Linux   | `~/.config/<productName>`                     | `<tmpdir>/pear/<productName>` |
| Windows | `%USERPROFILE%\AppData\Local\<productName>`   | `<tmpdir>/pear/<productName>` |

The convention comes from the getting-started [pear-chat `getStorageDir()` helper](/p2p/getting-started/build-a-peer-to-peer-chat/reshape-into-a-production-app): when `app.isPackaged` is `false`, the dir falls back to `os.tmpdir()`; otherwise it picks the OS-appropriate user-data folder. (In the [`hello-pear-electron`](https://github.com/holepunchto/hello-pear-electron/blob/main/electron/main.js) template the same logic lives in `getWorker()`, which passes `dir` to the Bare worker that constructs the runtime.) The Pear runtime exposes that dir as `pear.storage`, which the worker passes to [Corestore](/p2p/reference/helpers/corestore) as `storage`.

On Windows the docs and examples deliberately use `AppData\Local` (machine-local), not the `AppData\Roaming` the upstream template defaults to: a [Corestore](/p2p/reference/helpers/corestore) holds a per-device peer keypair and can grow large, so it should stay machine-bound rather than sync across roaming profiles.

<Callout type="info">
  Mobile has no dev/production split like the table above—[`pear-mobile`](/pear/reference/pear/mobile#options) resolves `dir` to the OS-sandboxed app-data directory (iOS Application Support, Android `files`) unconditionally, because a mobile app sandbox doesn't expose anywhere else to write. See [Pear mobile application architecture](/pear/explanation/pear-mobile-architecture#storage).
</Callout>

### Running multiple application instances [#running-multiple-application-instances]

Because [Corestore](/p2p/reference/helpers/corestore) takes an exclusive file-system lock on its directory, two copies of the same packaged app cannot share `dir`. To run a second local instance you point it at a separate folder with the `--storage` flag (recognised by every Pear-shaped Electron app that wires `paparam` like the template):

```bash
# development
npm start -- --storage /tmp/custom/storage

# packaged macOS
open -n PearChat.app --args --storage /tmp/custom/storage

# packaged Linux
./PearChat.AppImage --storage /tmp/custom/storage

# packaged Windows
.\PearChat.exe --storage C:\tmp\custom\storage
```

A second `--storage` instance behaves exactly like an instance running on another machine: a separate [Corestore](/p2p/reference/helpers/corestore), a separate [Hyperswarm](/p2p/reference/building-blocks/hyperswarm) presence, the same `pear://` link. This is the simplest way to test peer-to-peer flows locally without involving a second device.

<Callout type="info">
  There's no mobile equivalent—there's no `--storage` flag or second app instance to launch on one device. Test multi-peer mobile flows with a second physical device or simulator instead, each with its own OS-sandboxed storage by construction.
</Callout>

## How distribution works [#how-distribution-works]

A Pear application's `pear://<key>` link is a stable identifier the swarm can route on. When you publish a new version with `pear stage` and announce it with `pear seed`, you're appending to the application's [Hyperdrive](/p2p/reference/building-blocks/hyperdrive)—peers tracking that drive pick up the new version while they're connected to the swarm, replicating only the blocks they actually need rather than the whole drive.

The swarm replicates lazily: a peer that runs your app becomes a source for it. Once you have a few users running an application, distribution scales without any central infrastructure on your end. The original author can go offline and the application keeps spreading, as long as at least one peer with a copy is reachable.

The `pear seed <link>` command keeps a peer online and announcing as a source for a given link. It's not strictly required—any peer running the app contributes—but it's the recommended way to guarantee availability for a release. A handful of seeders is usually enough; very popular apps reach the long-tail-availability sweet spot quickly.

The same model applies to the Pear platform itself: there's no Pear download server, only a swarm.

### Installing applications [#installing-applications]

For a long time the way to launch a Pear application was `pear run pear://<key>`—the runtime fetched the bundle from the swarm and ran it in place.

That runtime capability has been unbundled from the CLI: `pear run` was **removed in Pear v3** in favour of the embeddable **[Pear OTA](/pear/reference/pear/runtime)** (`pear-runtime`) library, so any JavaScript project can carry peer-to-peer over-the-air updates without depending on the CLI. The CLI's remaining focus is deployment and, now, installation. The full rationale is in [Pear Evolution](https://pears.com/news/pear-evolution/).

Installing replaces "run from a link" with a first-class on-disk install. [`pear install pear://<key>`](/pear/reference/pear/cli#pear-install) pulls an application built with [`pear build`](/pear/how-to/operate-an-app/manual-deployment/deployment#4-build-the-deployment-directory) from the swarm and sets it up locally, the same way the platform binary arrives—there is still no download server, only peers. The command works for both applications and standalone binaries.

```bash
# install an application peer-to-peer
pear install pear://<key>
```

<Callout type="info">
  `pear install` ships with the Pear v3 CLI, provided by the standalone [`pear-install`](https://www.npmjs.com/package/pear-install) module—which also works directly via `npx pear-install pear://<key>` on machines without Pear.
</Callout>

The same mechanism bootstraps Pear itself. As of v3 the CLI is a standalone binary that updates over the swarm through **[Pear OTA](/pear/reference/pear/runtime)** (`pear-runtime`), so `npx pear-install` installs `pear`—collapsing the install path for the platform and for the apps it distributes into one model. A mobile counterpart, [`pear-mobile`](https://www.npmjs.com/package/pear-mobile), carries the same over-the-air update story to iOS and Android.

Because installed applications already live as [Corestores](/p2p/reference/helpers/corestore) of [Hyperdrives](/p2p/reference/building-blocks/hyperdrive) under the platform directory (see [On-disk layout](#on-disk-layout)), an install is just another entry in that tree, and updates flow through the same lazy swarm replication described above.

### When seeding is not enough [#when-seeding-is-not-enough]

Self-seeding with `pear seed` only covers cores you hold locally and requires an always-on process per application. Private rooms, direct-message threads, and offline authors create gaps where no participant seeds the data a new peer needs.

<Callout type="info">
  [Blind peering](/p2p/explanation/blind-peering) describes third-party replicators that cache cores without reading them, as one way to close that gap.
</Callout>

## Why this shape [#why-this-shape]

* **No infrastructure.** The author of an application doesn't run servers, doesn't pay for bandwidth, doesn't have a single point of failure. The cost of serving the app is amortized across users.
* **Versioning is built in.** Each [Hyperdrive](/p2p/reference/building-blocks/hyperdrive) is backed by an append-only [Hypercore](/p2p/reference/building-blocks/hypercore) log, so an application's history is preserved automatically and rollbacks are routine—even though the drive itself still supports deletes and updates on top of that log.
* **Same primitives for code and data.** Application storage and the application itself are both corestores, which means the same replication, encryption, and update mechanics apply to both.

## See also [#see-also]

* [Pear desktop application architecture](/pear/explanation/pear-desktop-architecture)—how a typical Electron app maps `dir`, workers, and OTA into that layout.
* [Release pipeline](/pear/explanation/deployment-releasing-apps-p2p)—stage, provision, multisig, and release lines for shipping desktop builds.
* [Manage installed applications](/pear/how-to/manage-installed-applications)—listing and dropping local application storage.
* [Deploy your application](/pear/how-to/operate-an-app/manual-deployment/deployment)—staging and seeding new releases.
* [Hypercore](/p2p/reference/building-blocks/hypercore)—the append-only log every other primitive composes.
* [Hyperdrive](/p2p/reference/building-blocks/hyperdrive)—file-system layer used for application bundles and assets.
* [Corestore](/p2p/reference/helpers/corestore)—the storage manager whose on-disk format backs every installed application and app-storage directory.
