# Runtime and languages



Pear applications are JavaScript programs. The runtime under them is **[Bare](/bare/explanation/bare-runtime)**, a small embeddable JavaScript runtime that strips the assumptions Node.js carries about being a server. This page explains why the language story looks the way it does, how non-JavaScript code joins in, and what the recommended app shape is when you want one codebase to run on desktop, mobile, and terminal.

<Callout type="info">
  For where Bare sits relative to Pear, see [How the stack fits together](/p2p/explanation/how-the-stack-fits-together).
</Callout>

## Why JavaScript [#why-javascript]

Two pragmatic reasons:

1. **Web heritage.** The peer-to-peer libraries Pear is built on ([Hypercore](/p2p/reference/building-blocks/hypercore), [Hyperdrive](/p2p/reference/building-blocks/hyperdrive), [Hyperswarm](/p2p/reference/building-blocks/hyperswarm)) are mature JavaScript modules with millions of downloads. Reusing them on the desktop and on mobile through a single language eliminates a translation layer.

2. **Bare keeps it small.** Bare ships without Node's standard library opinions—no `fs.read` on a URL, no built-in `http` module, no Worker baggage. That makes it cheap to embed in mobile apps, desktop shells, and constrained terminal environments alike. The Pear runtime adds the bits applications actually need on top.

If you're coming from Node.js, the surface looks similar but isn't identical—see [Bare modules](/bare/reference/bare/modules) for the exact set of standard libraries available, and the [Node.js compatibility](/bare/reference/bare/modules#nodejs-compatibility) section for a builtin-by-builtin mapping to the corresponding `bare-*` modules. The [`bare-node`](https://github.com/holepunchto/bare-node) shim maps many Node.js builtins onto their Bare equivalents, easing the port.

## Other languages [#other-languages]

For languages that compile to JavaScript (TypeScript being the obvious one) the path is straightforward: compile to JS, then point the application's [`main` field or HTML `<script>` entrypoint](/pear/reference/pear/configuration#packagejson) at the compiled output.

For code that JavaScript can't naturally express—tight cryptography loops, codec work, hardware access—Bare loads native addons written in C, C++, Rust, or any language with a C-compatible ABI. See [Native addons](/bare/explanation/native-addons) for how to write one, and how to build prebuilt binaries for every platform you ship to.

## One codebase, many platforms: the Pear-end pattern [#one-codebase-many-platforms-the-pear-end-pattern]

The recommendation for cross-platform Pear apps is to split the code into two halves:

* **Pear-end**—the peer-to-peer logic, business rules, and storage. Runs in a Bare worker.
* **UI**—the platform-specific presentation. Talks to the Pear-end over an inter-process communication (IPC) stream.

Because the Pear-end never imports DOM APIs and never assumes a particular UI framework, it's portable across desktop (Electron), mobile (React Native via Bare iOS / Bare Android), and terminal. Only the UI half changes per platform—it gets a fresh implementation each time, but it's also the cheap half: layout, not logic. On mobile the worklet and the typed seam between the two halves are what carry this split—see [One core, many platforms](/bare/explanation/bare-on-native).

This split is what powers Keet's identical experience across phones, laptops, and terminals: one Pear-end, three UIs.

**[Pear OTA](/pear/reference/pear/runtime)** (the `pear-runtime` library) is what wires the two halves together: the UI host embeds it to spawn the Pear-end as a Bare worker, manage peer-to-peer storage, and apply over-the-air updates. It targets desktop; on mobile the same role is filled by [`pear-mobile`](https://www.npmjs.com/package/pear-mobile), the embeddable Pear runtime for mobile applications. If you have an app on the removed global `pear run` API, see [Migrate from pear run to Pear OTA](/pear/how-to/operate-an-app/migration).

## Workers carry the Pear-end [#workers-carry-the-pear-end]

In a desktop Pear app the Pear-end runs as a [Bare](/bare/reference/bare/modules) worker spawned by the Electron main process. The worker owns the swarm identity, the [Corestore](/p2p/reference/helpers/corestore), and every peer-to-peer protocol the app implements; the renderer reaches it through a single IPC duplex stream. The same shape applies on terminal, where the `pear` CLI is the host that spawns the worker. Mobile has no separate host process—the view starts the Pear-end worklet directly; see [Pear mobile application architecture](/pear/explanation/pear-mobile-architecture#where-this-differs-from-desktop) for why.

See [Workers](/pear/explanation/workers) for the pattern in full—what crosses the IPC boundary, why native addons live on the worker side, and how `Bare.argv` lines up with `process.argv`.

## See also [#see-also]

* [How the stack fits together](/p2p/explanation/how-the-stack-fits-together)—the full layering, from native C foundations up to apps.
* [Inside Bare](/bare/explanation/bare-runtime)—what the runtime adds, its lifecycle, and why it's minimal.
* [One core, many platforms](/bare/explanation/bare-on-native)—running the Pear-end in a worklet behind a typed RPC seam.
* [Workers](/pear/explanation/workers)—the host-and-worker split this page calls the "Pear-end."
* [`pear-runtime` reference](/pear/reference/pear/runtime)—the JavaScript API exposed inside a running Pear app.
* [Bare modules](/bare/reference/bare/modules)—the standard library available to both halves of a Pear app.
* [Storage and distribution](/pear/explanation/storage-and-distribution)—what's running underneath both halves.
