Files
2026-04-25 23:02:07 -04:00

8.5 KiB

name, version, description, tags, requires
name version description tags requires
bare-os-super-developer 1.0.0 Write Bare OS scripts and small apps using ctx — VFS, execLine, hooks, caps, and safe patterns (no Node in /bin/agent loop).
bare-os
ctx
scripts
vfs
kernel
developer
read_file
read_proc_file
run_js_script

bare-os-super-developer — Scripts, apps, and ctx

When to use

Use this skill when you (or the user) need to author or debug Bare OS JavaScript that runs inside the guest (kernel init, /bin/* utilities, kernel.ext.d, user .mjs run via run_js_script**, or Pear/booter-hosted scripts). It complements repo docs: treat **developer-guide/02-the-context-object.md** and **packages/bare-os-booter/lib/bare-os-ctx.d.ts as the canonical deep dives; this file is the fast mental model.

Core model

  1. Entrypoints — Kernel: async function start(ctx) in /boot/init.js (or your image). Commands: async function run(ctx, argv)** where **argv[0] is the invoked name (e.g. agent). You must set ctx.exitCode (number) before returning on failure paths.
  2. ctx is not Node — There is no full process**, no **require('node:fs')**. The booter assembles **ctx** as the narrow syscall surface: **vfs**, **env**, **execLine**, **runBinCommand**, optional **httpFetch**, **bare, identity helpers, diagnostics, etc. See the mermaid overview in Chapter 2 of the developer guide.
  3. /bin/agent is special — The agent bundle uses run_js_script** for guest JS and a frozen tool surface; do not assume **node** exists. For general in-guest scripting, prefer **ctx.vfs** + **ctx.execLine** / **ctx.runBinCommand** and optional **ctx.bare.* modules when enabled.

Writing scripts (run(ctx, argv))

  • Argvargv is a string array; argv[0] is how you were invoked (symlink name matters for multi-call binaries).
  • Stdout — Prefer ctx.console.log** / **ctx.console.error** (session-aware). For binary or captured stdout, **ctx.bareOsBinWrite may exist when the shell captures pipeline output.
  • Shell a subprocessawait ctx.execLine('some shell line', { signal, timeoutMs })** returns a string (see booter **raceWithAbortAndTimeout**). Heavy work: **await ctx.runBinCommand(['/bin/grep', …], opts) for same resolution as the interactive shell.
  • Filesystemawait ctx.vfs.readFile(path)****Uint8Array**; **await ctx.vfs.writeFile(path, buf, opts?)**. Decode with **ctx.b4a.toString(buf)** or **TextDecoder**. Always use absolute paths under **/home**, **/tmp**, **/mnt**, **/bin, etc., per policy.
  • Environmentctx.env** is mutable shell state (also **ctx.vfs.env**). After **execLine**, **ctx.env.BARE_OS_EXIT_STATUS reflects last exit code when the booter sets it.
  • Exit — Set ctx.exitCode = 1** (or other code) on error; **0** on success. **ctx.requestBooterExit(code)** ends the whole session from builtins like **exit.

Building “apps” (long-lived behaviour)

Think in layers the stock OS already uses:

Layer Mechanism Notes
Init **bareOsRegisterBootStepHook**, initd units Boot-order DAG (stock: **bare-os-www** before **bare-holesail** so **bare-www-*** reaches loopback HTTP; **bare-openssh** + login stack ensure **bare-ssh-*** in **~/.holesail/state.json**); pair **registerKernelShutdownHook** / initd disposers for teardown.
Virtual files **bareOsRegisterVirtualFile(name, reader, opts?)** Serves **/run/bare-os/virtual/<name>**; gated by runtime caps.
IPC **ctx.bareOsIpc** when present **push/take**, JSON helpers, fanout, duplex bridge — bounded; audit when **BARE_OS_IPC_AUDIT=1**.
Kernel extensions bareOsRegisterKernelExtensionRecord**, **bareOsRunImageScript** under **/lib/bare-os/extensions/ Trusted image paths only.
Sandboxed user JS **bareOsSandboxRunScript(source, argv?, opts?)** Restricted **ctx**; disable with **BARE_OS_SANDBOX_SCRIPT=0**.
Pear / host **bareOsPearIpcEmit**, **bareOsPearIpcRequest**, mirror/export hints Host must cooperate; return **{ ok, hint }** patterns.

Before touching sensitive ctx** methods in hardened images, call **ctx.bareOsIsCtxMethodAllowed?.(name)** when boot policy **BARE_OS_BOOT_POLICY_ALLOWED_CTX_METHODS is set.

ctx field map (cheat sheet)

Always read live truth for capability bits: read_proc_file** on **/proc/bare_os/features** and **/proc/bare_os/capabilities.json** — do not infer from man pages alone (see **bare-os-kernel-proc skill).

Files, drives, process

  • ctx.vfs****readFile**, **writeFile**, **mkdir**, **readdir**, **stat/lstat**, **chmod**, … Path routing: system vs personal Hyperdrive; **ctx.drive** vs **ctx.personalDrive for advanced use.
  • ctx.env**, **ctx.drive**, **ctx.personalDrive**, **ctx.disk — Session identity and mounts.
  • ctx.execLine**, **ctx.runBinCommand — Shell and /bin execution with shared policy (timeouts, abort).

Bytes, console, session

  • ctx.b4a — Buffer/string helpers for Hyperdrive payloads.
  • ctx.console**, **ctx.readLine**, **ctx.writeScreen** — REPL session ( **readLine may be Fish-backed when enabled).
  • ctx.exitCode**, **ctx.requestBooterExit**, **ctx.registerKernelShutdownHook

Bare OS introspection & policy

  • ctx.bareOsCtxApiVersion**, **ctx.bareOsRuntimeCaps (frozen)
  • ctx.bareOsAdvertisedKernelCapabilityWords**, **ctx.bareOsSeedKernelCapabilityWords****>>> 0 when testing bits.
  • ctx.bareOsGetResourceStatus**, **ctx.bareOsReadProcMetricsLive**, **ctx.bareOsReadBareTopSnapshot
  • ctx.bareOsRegisterVirtualFile**, **ctx.bareOsInvalidateVirtualFile**, **ctx.bareOsUpdateVirtualFileMeta
  • ctx.bareOsEmitIpcAudit**, **ctx.bareOsEvaluatePeerAdmission**, **ctx.bareOsEmitMirrorDriveHint

Optional / host-dependent

  • ctx.httpFetch** — Same allow/deny policy as **curl** / **wget**; every host for **web_fetch must be allowlisted.
  • ctx.bare** — Frozen map of vendored modules (**b4a**, **protomux**, …) when **BARE_OS_BARE_MODULES allows.
  • ctx.bareOsHostStats**, **ctx.bareOsChat***, **ctx.bareOsPearIpc* — Present only when wired by the booter/host.

For the full list and semantics, open developer-guide/02-the-context-object.md** in the repo (or **read_file on a mounted checkout).

Minimal script template (guest)

/**
 * @param {Record<string, unknown>} ctx
 * @param {string[]} argv
 */
export async function run(ctx, argv) {
  const argv0 = argv[0] || 'script'
  const vfs = ctx.vfs
  if (!vfs?.readFile) {
    ctx.console.error(argv0 + ': no vfs')
    ctx.exitCode = 1
    return
  }
  try {
    const buf = await vfs.readFile('/proc/bare_os/features.json')
    const t =
      ctx.b4a && typeof ctx.b4a.toString === 'function'
        ? ctx.b4a.toString(buf)
        : new TextDecoder().decode(buf)
    ctx.console.log(t.slice(0, 500))
  } catch (e) {
    ctx.console.error(argv0 + ': ' + (e && e.message ? e.message : String(e)))
    ctx.exitCode = 1
  }
}

Save under /home/.../my-tool.mjs** and run by absolute path (or register under **/bin** on the image). Do not rely on **node in the guest.

Agent-specific note

When helping inside /bin/agent, the model uses tools (read_file, run_js_script, …) backed by the same personal/system VFS as the rest of the guest. run_js_script** writes a temp **.mjs** under **~/.agent/** and executes it like a **/bin** script — the script body should use the same **ctx** patterns above when the harness passes **ctx.

Checklist before shipping

  1. read_proc_file** / **get_system_info — confirm needed features and caps exist this session.
  2. Paths — absolute, no .. escape from allowed roots.
  3. Timeouts — pass AbortSignal** / **timeoutMs** to **execLine** / **readLine for network or slow FS.
  4. Teardown — unregister hooks, clear intervals, dispose IPC fanout subscribers.
  5. Secrets — never log ~/.agent/config.json** or keys; redact in **MEMORY.md.

Output format (when this skill was used)

  • What you read — which ctx** fields or **/proc files grounded the answer.
  • Plan — file paths, entrypoint (run vs start), and exit semantics.
  • Risks — policy gates, missing caps, host-only APIs.