# Chapter 1 — Two runtimes: host (Pear/Node) vs in-image (`AsyncFunction`) If you only remember one thing from this guide, remember this: **Bare OS runs two different kinds of JavaScript**, and they follow different rules. --- ## The confusion in one sentence You might paste a file into your home directory on the personal Hyperdrive that starts with `import fs from 'node:fs'` and expect it to run like a Node script. **It will not.** That file is loaded as a **string** and executed with the JavaScript **`AsyncFunction`** constructor—not as an ES module. There is no module graph, no `import` resolution, and no automatic `node_modules` on the drive. The **booter** and **seeder** Pear packages, by contrast, are normal **ESM** projects: they use `import`, npm dependencies, and Pear bundling. They run on the **host** and _host_ the environment that evaluates in-image code. When the **`bare-os`** npm module is available on that host, the booter may attach a read-only **`ctx.bareOsHostStats`** snapshot (**`loadavg`**, **`cpus`**, **`networkInterfaces`**, …) and write **`/proc/bare_os/host_os.json`** (**schema 2**, including **`bare-os` 3.9+** and optional **`bare-posix`** fields)—still **not** a general “run Node in the image” escape hatch; see [Chapter 2](02-the-context-object.md). --- ## Mental model: who loads whom ```mermaid flowchart TB subgraph host [Host process Pear or Node] booterPkg[bare-os-booter package] seederPkg[bare-os-seeder package] esm[import and node_modules] end subgraph hyper [Hyperdrives] sys[System drive] pers[Personal drive] end subgraph evalLayer [Evaluated inside booter VM] kernel["start ctx from boot/init.js"] binutil["run ctx argv from bin/*"] userscript["run ctx argv from home script.js"] end booterPkg --> esm booterPkg --> sys booterPkg --> pers booterPkg -->|runKernelFromSource| kernel booterPkg -->|runBinCommand| binutil booterPkg -->|runBinCommand| userscript ``` - **Host** code lives under `packages/bare-os-booter/`, `packages/bare-os-seeder/`, etc. It is **trusted** in the sense that you built or installed it; it opens Corestore, Hyperswarm, Hyperdrive, and constructs `ctx`. - **In-image** code is **bytes on a drive** (`/boot/init.js`, `/bin/cat`, `~/mytool.js`). The booter reads those bytes as UTF-8 strings and passes them to `new AsyncFunction(...)` (see [`kernel-runner.js`](../packages/bare-os-booter/lib/boot/kernel-runner.js)). --- ## In-image execution (the `AsyncFunction` contract) Two entry shapes matter: - **`async function start(ctx)`** — `/boot/init.js` on the **system** drive — `ctx` — `runKernelFromSource` wraps the source and calls `start(ctx)` - **`async function run(ctx, argv)`** (optional for user scripts) — `/bin/*` always; or a `*.js` file resolved from the shell — `ctx`, `argv` (string array) — `runScriptFromSource` runs the file body, then **awaits** `run(ctx, argv)` if defined The booter **injects** `ctx` and `argv`. Kernel **`start`** is required; for shell scripts, top-level statements may stand alone, or you may **define** **`run`** like **`/bin`** utilities. Top-level `import` is invalid in that evaluated string because the engine is not loading an ES module—it is compiling a function body. Shebang lines (`#!/usr/bin/env bare`) are stripped before compile ([`stripShebang`](../packages/bare-os-booter/lib/boot/kernel-runner.js)) so the first token the parser sees is valid JavaScript. --- ## Host execution (Pear / Node packages) When you edit `packages/bare-os-booter/index.js`, you are writing **normal** JavaScript for Node or Bare under Pear: - Use `import Hyperdrive from 'hyperdrive'`. - Add dependencies in `package.json`. - Use async I/O against real host APIs. **Web Encoding globals:** some Bare/Pear builds do **not** define global `TextEncoder` / `TextDecoder`. Booter and in-image code should use **`b4a`** for UTF-8 instead (e.g. `b4a.from(str, 'utf8')`, `b4a.toString(buf, 'utf8')`), matching [`curl-cli.js`](../packages/bare-os-booter/lib/tools/curl-cli.js). Relying on `new TextEncoder()` in booter `lib/*.js` can break at runtime (for example when statting or reading pseudo files under `/proc` or `/sys`). This code **creates** `ctx` and passes it into the kernel. It does **not** run inside the simulated `/bin` environment unless you explicitly call `runBinCommand(ctx, argv)` with the same `ctx` the shell uses. --- ## Trust: system drive vs personal drive - The **system** drive is the **replicated OS image**: `/boot`, `/bin`, `/etc`, `/share`. You should treat its contents as **integrity-checked by replication** from peers you chose to trust (same discovery key / topic as the rest of the project). - The **personal** drive holds `$HOME`, `/.bare`, user files, crontab, etc. It is **writable** by the session. User scripts you write live here by default. A script you place in `~/exploit.js` is **your** code; the booter will still `AsyncFunction`-evaluate it with full `ctx` power. That is convenient and dangerous—see [Chapter 9](09-security-and-trust.md). --- ## Host source policy (Bare-first) Pear-bundled **booter** and **seeder** runtime sources under `packages/bare-os-booter/lib/` and `packages/bare-os-seeder/lib/` must stay resolvable on **Bare** as well as Node: CI runs [`scripts/verify-pear-no-static-node-import.mjs`](../scripts/verify-pear-no-static-node-import.mjs), which rejects **`from 'node:…'`** imports, **`require('node:…')`**, and **`import('node:…')`** in those trees (with path-based exceptions). Use **`#host-fs`**, `**#host-path**`, and `**#host-fs-promises`** from package `imports` instead of bare **`fs`** / **`path`** specifiers. The only deliberate **`node:module`** usage today lives in **`bare-os-boot-manifest-sig.node.js`** (Node default entry for boot manifest verification); the **`bare`** export uses **`bare-os-boot-manifest-sig.bare.js`**. For guest-visible behavior, prefer Holepunch `**bare-*`** modules per [Node → Bare module map](node-to-bare-modules.md). --- ## When to use which runtime - Add a new **`/bin`** command shipped with the OS image — **In-image** pattern: coreutils `src/*.js` + build (Chapter 6) - One-off automation in your home directory — **In-image** script (top-level and/or optional `run`); no `import` (Chapters 4–5) - Change how networking, HDMS, or the REPL works — **Host** booter package (ESM) - Publish or replicate the system image — **Host** seeder package --- ## See also - [Chapter 2 — The context object](02-the-context-object.md) - [Handbook — Booter runtime](../handbook/04-the-booter-runtime.md) - [Handbook — Kernel and binaries](../handbook/06-kernel-and-binaries.md) --- [← Developer guide home](README.md) · [Context object →](02-the-context-object.md)