Little documentation
Guides and APIRuntime

just-bash Runtime

Why the first local Little Harness runtime can build on just-bash.

Little Harness: published on npm as little-harness@0.2.0-alpha.0 (2026-10-05). Sections labeled UNRELEASED describe source-only changes. Release status

just-bash is a TypeScript virtual bash environment with an in-memory filesystem. It is a strong first substrate for Little Harness because agents naturally benefit from file and shell workflows.

The alpha runtime uses just-bash for:

  • virtual filesystems
  • mountable filesystems
  • copy-on-write overlays
  • standard shell commands
  • text and data tools such as rg, jq, sqlite3, and xan
  • optional Python and JavaScript execution
  • network disabled by default
  • Runtime Tool Bridge exposure for configured Little Harness tools inside js-exec

Runtime Shape

Little Harness session
-> just-bash Bash instance
   -> /session
   -> /artifacts
   -> .agents/skills
   -> /persistent
   -> configured tools via Runtime Tool Bridge

This gives the runtime a familiar command surface and per-session file isolation without requiring Docker, microVMs, or cloud sandboxes in the happy path.

Where It Runs

The same just-bash runtime can run in two places, chosen by localHost({ sandbox }):

  • In a child process (subprocessSandbox()) — the default for any turn that can run Python or JavaScript or reach the network, under the default "auto" mode.
  • In the host process (justBashSandbox()) — under "auto" only when runtime.python and runtime.javascript are both false and network is off, or always with "in-process".

See Execution Environments.

Runtime Tool Bridge

When JavaScript is enabled, the default just-bash runtime exposes configured tools inside js-exec as tools.<name>(args).

js-exec -c 'const result = await tools.queryCustomers({ plan: "enterprise" }); console.log(result.path ?? JSON.stringify(result))'

This is the default path for complex, batched, or programmatically assembled tool inputs. The model can still call the same tools directly through the provider; the bridge simply gives it a scriptable route when emitting many large tool-call JSON payloads would be brittle or token-heavy.

Bridge calls use the same configured tool definitions, execution context, spooling policy, abort signal, traces, and durability replay as ordinary tool calls. Trace and durable events use caller: "runtime" and scope replay by the parent bash tool call id so repeated identical bridge calls in different bash commands do not collide.

The bridge is available only when bash is model-visible and JavaScript is enabled. It is not advertised when runtime.bash === false, runtime.javascript === false, runtime.toolBridge === false, or per-call activeTools / prepareStep settings hide bash.

createHarness({
  host: localHost(),
  model,
  tools,
  runtime: { toolBridge: false },
});

Security Boundary

just-bash is Tier-0: a compatibility layer for trusted tool patterns, not an isolation boundary. Commands never touch the real filesystem, processes, or sockets, but the containment is a library's parser and virtual filesystem, not the OS. js-exec and Python execute guest code inside whichever process hosts just-bash, which is why the default "auto" mode moves code-running turns into the subprocess sandbox (empty environment, SIGKILL watchdog, and just-bash's defense-in-depth layer, on only there — see defenseInDepthForAdapter). Neither placement confines native code; see Isolation And Security.

Whatever the sandbox, these still run in the host app's trust boundary:

  • tool handlers
  • storage callbacks
  • export callbacks
  • custom runtime hooks

Little Harness should treat those as explicit capabilities and make their side effects visible in trace events.

Beyond Tier-0

just-bash has no git, containers, compilers, or package managers. A command that needs one can be escalated to a real sandbox you provide with tieredSandbox({ nextTier }), which classifies each script before it runs; see Execution Tiers. Containers, microVMs, or hosted execution pools plug in as that nextTier (or as the whole sandbox) through the same HarnessSandboxFactory port — the developer-facing harness config does not change.

On this page