Files
bare-operating-system/developer-guide/12-bare-modules-and-pear-ecosystem.md
T
snxraven 68a564b93e
Release rolling / release (push) Failing after 3m16s
Update Docs
2026-08-18 18:20:22 -04:00

12 KiB
Raw Blame History

Chapter 12 — Bare modules, ctx.bare, and the Pear ecosystem

This chapter ties together Holepunch bare-* packages, the Pear host runtime, and how Bare OS exposes a curated subset to in-image scripts.


Tiers of access (image, Pear embed, host, mirror)

  1. /lib/bare (system image, primary)bare-os-bare-libs builds one IIFE per manifest row into kernel/lib/bare/bundles/ (mirrored on the seeded Hyperdrive). It also copies bare-module-manifest.json into kernel/lib/bare/. manifest.json lists successful bundles; stale **bundles/*.js** files are pruned on each successful build. At boot, drive bundles run first (unless BARE_OS_BARE_DRIVE_BUNDLES=0).

  2. Pear booter (bare-module-manifest.data.mjs) — The stock booter package ships packages/bare-os-booter/lib/ctx/bare-module-manifest.json (normative JSON, edited or synced from the catalog) and a generated sibling bare-module-manifest.data.mjs that export default the same object. Under pear run, import.meta.url is pear://…; bare-fs cannot open pear: URLs passed as URL instances because normalization uses bare-url.fileURLToPath ( file: only). Therefore loadBareModuleManifest() reads the embedded .data.mjs on Pear so the manifest stays in the traced module graph. On file: dev checkouts it prefers the JSON on disk (live edits) and falls back to the embedded copy if the file is missing. Regenerate .data.mjs with npm run sync:bare-manifest or node scripts/generate-bare-module-manifest-data.mjs; CI runs npm run verify:manifest-data.

  3. ctx.bare (host fallback) — Unless BARE_OS_BARE_HOST_IMPORTS=0, the booter then **import()**s manifest packages still missing after drive merge. Under pear run (booter import.meta.url is pear:), bundle: true rows are skipped for host import() (keys come from **/lib/bare/bundles/*** only; avoids bare-module **MODULE_NOT_FOUND / referrer** errors for npm names like holesail). Under file: dev trees, bundle: true may still be host-imported when the drive bundle did not fill the key. Remaining host imports cover native or Bare-only packages that could not be bundled, or when the image is older than the manifest. Set **BARE_OS_BARE_HOST_IMPORTS=0** for a fully image-local ctx.bare (no Pear host node_modules participation). Disable all ctx.bare with BARE_OS_BARE_MODULES=0. For narrow harnesses, session env may set BARE_OS_BARE_HOST_SKIP_CTX_KEYS (comma-separated ctxKey list to skip) or BARE_OS_BARE_HOST_ONLY_CTX_KEYS (allowlist — only those keys are host-imported). Manifest rows may include optional tier (core vs extended) and risk (low, medium, high) for distributor policy; the build honors tier via BARE_OS_BUNDLE_TIER.

Boot cold path / stdlib budget: the stock booter measures drive merge + host import() resolution for ctx.bare and sets BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS before the guest starts. Operators may set BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB to log boot-perf.json / stderr warnings when resolution exceeds the budget; combine with BARE_OS_BUNDLE_TIER=core (or a smaller manifest) to shrink cold I/O. Use node scripts/kernel-microbench.mjs for regression-shaped timings (not a literal Pear cold boot).

  1. The full mirror (discoverability) — A local checkout of Holepunch repos (for example holepunchto_repos under your Pear tooling tree) lists on the order of 150+ repositories whose names start with bare-. Many are native addons, platform-specific (mobile, GUI, FFmpeg, …), or developer tools. The manifest can list them for ctx.bare, but only rows that bundle cleanly become real drive IIFEs; the rest rely on host import or stubs until you trim the manifest.

Maintenance workflow

  • Holepunch catalog (maximal npm set) — From the repo root:

    npm run gen:bare-catalog
    npm run sync:bare-manifest
    npm install
    

    This refreshes docs/bare-holepunch-catalog.json (every holepunchto/bare-* repo plus npm latest, minus scripts/bare-catalog-overrides.json), then merges published packages into bare-module-manifest.json and replaces booter optionalDependencies from that catalog (anything not includedInBooter is dropped). sync:bare-manifest rewrites entries only and preserves the curated top-level pearEntries array (pear-build, pear-bundle, pear-ref, bare-bundle-compile, bare-bundle-evaluate). packages/bare-os-bare-libs/build.mjs resolves package.json #imports with host platform / bare conditions so new Holepunch modules (Bluetooth, native UI, …) bundle without a Node-only default. CI runs npm run gen:bare-catalog:check so the committed catalogs entries (and source) stay in sync with live npm/GitHub.

    scripts/bare-ctx-import-overrides.json adjusts a few packages for ctx.bare / esbuild: namespace exports (export: *), bare-node-runtime/global as a side-effect entry, etc. Edit this when npm packages have no default export or need a subpath.

  • Add or remove a ctx.bare entry by hand — Edit the manifest and booter dependencies / optionalDependencies as needed. The bundle field in the manifest is legacy metadata; bare-os-bare-libs attempts every row. Prefer the catalog + sync path for **bare-*** rows so ctxKey and semver ranges stay consistent.

  • Refresh /lib/bare on the image — From the repo root:

    npm run build -w bare-os-bare-libs
    

    Optional BARE_OS_BUNDLE_TIER=core builds only manifest rows with "tier": "core" (default tier when omitted). Use all or unset for the full catalog.

    Then re-run the seeder so kernel/lib/bare/ is copied into the Hyperdrive (the seeder invokes this build automatically when running from a file: URL). Check manifest.jsonbundleStats after a build for how many IIFEs succeeded vs stub-only.

  • Node vs Pear/Bare — On Node, buildBareCtxObjectFromHost skips manifest rows with nativeHint: true so optional Bare-native packages are not **import()**d (avoids stray failures and unhandled rejections from addons). On Pear/Bare, the full manifest is loaded in parallel.

  • Pear — Continue to use node scripts/ensure-pear-node-modules.mjs packages/bare-os-booter before pear run so hoisted node_modules resolve like npm (see PEAR-RUN.md). After any manifest or catalog edit, run npm run sync:bare-manifest before pear stage so bare-module-manifest.data.mjs matches the JSON.

  • Local Holepunch clone inventory — After editing the manifest or before a release, run npm run audit:holepunch-clones to refresh docs/audit/holepunch-clone-sync-report.json against BARE_OS_HOLEPUNCH_CLONES_ROOT. To fail CI when selected clones lag origin/main, list their directory names in docs/audit/holepunch-drift-repos.json and set BARE_OS_HOLEPUNCH_DRIFT_CHECK=1 (see scripts/README.md).

  • mirror-drive (Holepunch) audit — The stock VFS union and /mirror/* overlays remain the supported read-mostly composition path. The upstream mirror-drive package is a candidate for a future env-gated fast path (read-only layering); treat any integration as parity-tested against union semantics and document fallback when the package is absent. See BARE_OS_VFS_UNION_PREFIXES in the environment appendix and ctx.bareOsEmitMirrorDriveHint above.


Runtime caps

ctx.bareOsRuntimeCaps.features includes bareCtxModules, bareDriveBundles, and bareHostImportsForCtx so kernels can see whether host fallbacks are enabled.


Pear IPC channel registry

ctx.bareOsPearIpcEmit(channel, payload) is a host bridge for pear-ipc-style messaging. Well-known channel strings are listed in packages/bare-os-booter/lib/tools/bare-os-pear-ipc-registry.js and mirrored as JSON under /proc/bare_os/pear_ipc.json (and the flat /proc/bare_os_pear_ipc_registry alias) so operators and kernels share one vocabulary for reload, mirror, and telemetry hints.

ctx.bareOsPearIpcRequest(channel, payload, { timeoutMs? }) correlates bareOsIpcReqId on payload and awaits process.emit('bare-os:pear-ipc-response', { bareOsIpcReqId, result?, error? }) on Node-style hosts. Use for request/response pairs alongside bareOsPearIpcEmit.

Mirror-drive hints: ctx.bareOsEmitMirrorDriveHint({ label?, key? }) emits bare-os:mirror-drive-hint for Holepunch-style snapshot workflows (see kernel extensions).

Blind-peer style hint: ctx.bareOsEmitBlindPeerHint(payload) forwards a capped JSON object on Pear IPC as bare_os_blind_peer_hint (topic/key material stays opaque strings; the guest does not verify blind-relay crypto).

Host-only eval probe: ctx.bareOsHostCapability('bundleEvaluate') is true when the host advertises **BARE_OS_HOST_BUNDLE_EVALUATE=1**, documenting an optional cross-worker / bare-bundle-evaluate path. Actual evaluation still happens outside the guest VFS trust boundary.

Discord bots (ctx.bare.discordJS) — The booter vendors bare-discord-js (official discord.js 14) and attaches it as ctx.bare.discordJS. Guest scripts have no import/require. Full how-to (Portal, .env, intents, slash catalog, initd, packing): Chapter 21 — Discord bots. Disable with BARE_OS_DISCORD=0.

bare-fetch content encodings (Capability word 6 doc alignment) — When the host fetch implementation is Holepunch bare-fetch 3, Content-Encoding negotiation may include br and zstd in addition to gzip depending on platform support. Responses may expose type and Headers.getSetCookie() (forwarded by in-guest web_fetch). In-image scripts should not assume a fixed encoding list; treat Accept-Encoding as host-defined. SPDX license identifiers on catalog rows (when present) are metadata for distributors, not a runtime guarantee inside the guest.


New: ctx.pear surface and /bin/pear (2026)

A parallel ctx.pear surface exposes Pear-level development tooling to in-image scripts.

  • Populated from pearEntries in bare-module-manifest.json (pear-build, pear-bundle, pear-ref, bare-bundle-compile, …).
  • Static host imports under pear:// via bare-os-ctx-pear-host.js (see HDMS manager pattern — no dynamic import("pkg") from guest bundles).
  • /bin/pear: help, info, list, init, stage, release, seed (build/bundle alias stage).

Guest workflow (no host Pear CLI required for release):

pear init && pear stage && pear release . && pear seed .
appstore install my-app pear://0.<length>.<key> --yes
appstore launch my-app

Full operator guide: docs/guides/guest-pear-and-appstore-workflow.md.

Design and audit: docs/design/ctx-pear-surface-and-bare-audit-plan.md, docs/audit/ctx-bare-audit-notes.md.


See also


← Kernel + Pear cookbook · Modules and import →