API Reference
For which node:* modules are shimmed and to what degree, see the
module status table on the Compatibility page.
VfsBus (@bolojs/fs)
Section titled “VfsBus (@bolojs/fs)”Single-owner observable virtual filesystem backed by memfs (hot layer) and OPFS (cold layer). The hot layer is authoritative; OPFS is a best-effort persistence cache that degrades silently. Files not accessed for 5 minutes are evicted from the hot layer (cold layer keeps a copy).
import { VfsBus } from '@bolojs/fs';const vfs = new VfsBus();Methods
Section titled “Methods”| Method | Signature | Description |
|---|---|---|
writeFile |
(path, content: string | Uint8Array) => Promise<void> |
Write or overwrite a file. Creates parent dirs automatically. |
readFile |
(path) => Promise<string | Uint8Array> |
Read a file. Falls through to OPFS cold layer if not in hot layer. |
exists |
(path) => boolean |
Synchronous hot-layer existence check. |
mkdir |
(path, opts?) => void |
Create directory (synchronous, hot layer only). |
rm |
(path, opts?) => void |
Remove file or directory (synchronous, hot layer only). |
readdir |
(path) => string[] |
List directory entries (synchronous). |
on |
(event, handler) => void |
Subscribe to filesystem events (see below). |
watch |
(glob, handler) => void |
Watch paths matching a glob pattern. |
snapshot |
() => object |
Export the full hot-layer state as a plain object. |
restore |
(snap) => void |
Restore state from a snapshot() export. |
use |
(middleware) => void |
Add a middleware function that runs before writes. |
Events
Section titled “Events”vfs.on('write', ({ path }) => { /* file written */ });vfs.on('delete', ({ path }) => { /* file removed */ });vfs.on('rename', ({ path }) => { /* file renamed */ });Internal surfaces
Section titled “Internal surfaces”vfs.vol: the underlying memfs Volume (use for low-level operations).
vfs.hot: memfs fs interface (sync methods available: readFileSync, writeFileSync, etc.).
ShellService (bolojs)
Section titled “ShellService (bolojs)”Routes shell commands to the appropriate execution tier.
import { ShellService } from 'bolojs';
const shell = new ShellService({ vfs, packageManager, runtimeWorker, sandbox });Constructor
Section titled “Constructor”interface ShellServiceDeps { vfs: VfsBus; packageManager: PackageManager; runtimeWorker: RuntimeWorker; swSandbox?: SWSandbox; // optional: enables `npm run dev` sandbox?: SandboxBackend; // optional: enables `agent run <script>` events?: ContainerEvents; workdir?: string;}execute(command, output?)
Section titled “execute(command, output?)”const result = await shell.execute(command, { stdout: (data: string) => void, // called incrementally as output arrives stderr: (data: string) => void,});// result: { stdout: string, stderr: string, exitCode: number }Supported commands
Section titled “Supported commands”| Command | Tier | Notes |
|---|---|---|
npm install [packages] |
PackageManager | Installs into VFS /node_modules |
npm run dev |
ContainerAdapter | Requires sandbox dep; starts BrowserViteServer |
runtime run <file> |
V8 Web Worker | Reads file from VFS, runs in RuntimeWorker |
agent run <file> |
SandboxBackend |
Reads file from VFS, runs via whatever sandbox dep is configured |
Unknown commands return exit code 127.
SandboxBackend / IframeSandbox (bolojs)
Section titled “SandboxBackend / IframeSandbox (bolojs)”Untrusted-code execution is pluggable behind a small interface:
interface SandboxRunResult { result?: string; error?: string;}
interface SandboxBackend { run(code: string): Promise<SandboxRunResult>; dispose(): void;}The default implementation is IframeSandbox: a cross-origin, opaque-origin iframe
(browser-native isolation, no WASM runtime to load):
import { IframeSandbox } from 'bolojs';const sandbox = new IframeSandbox();const { result, error } = await sandbox.run('2 + 2');// result: '4', error: undefinedfs.readFileSync(path) is available read-only inside the sandbox; write operations
(writeFileSync, mkdirSync, rmSync) throw immediately.
For hard, C-level memory/CPU/stack caps (not just origin isolation), implement
SandboxBackend with the QuickJS-based SandboxPool from the separate
quickjs-sandbox package and
pass it as sandbox: it’s opt-in and not a dependency of bolojs.
RuntimeWorker (bolojs)
Section titled “RuntimeWorker (bolojs)”Trusted code execution tier. Runs scripts in a dedicated Web Worker.
import { RuntimeWorker } from 'bolojs';const worker = new RuntimeWorker(vfs, sandbox);Constructor
Section titled “Constructor”new RuntimeWorker(vfs: VfsBus, sandbox: SWSandbox)runScript(code, opts?)
Section titled “runScript(code, opts?)”worker.onStdout = (data) => console.log(data);worker.onStderr = (data) => console.error(data);worker.onExit = (code) => console.log('exit', code);
await worker.runScript(code, { filename: '/index.js', args: [] });A watchdog terminates the Worker if no heartbeat is received for >10 seconds.
SWSandbox (@bolojs/sandbox)
Section titled “SWSandbox (@bolojs/sandbox)”ServiceWorker-based network proxy that intercepts requests to a virtual origin.
import { SWSandbox } from '@bolojs/sandbox';const sandbox = await SWSandbox.create({ origin: 'https://sandbox.local/', swPath: '/sw.js' });SWSandbox.create(opts)
Section titled “SWSandbox.create(opts)”Registers the service worker at swPath and waits for it to activate. Requires HTTPS
(or localhost). Throws if ServiceWorker API is unavailable.
onFetch(handler)
Section titled “onFetch(handler)”sandbox.onFetch(async (req) => { if (new URL(req.url).origin === 'https://sandbox.local/') { return viteServer.onFetch(new URL(req.url).pathname, req); } return new Response('Not found', { status: 404 });});setPolicyRegistry(registry)
Section titled “setPolicyRegistry(registry)”Attach a Map<string, unknown> of sandbox policies. Used by @bolojs/sandbox-policy.
Extending bolo
Section titled “Extending bolo”Something you need isn’t supported yet? Check the live compatibility dashboard first, then extend through one of these seams instead of forking.
Bundler tools (@bolojs/registry)
Section titled “Bundler tools (@bolojs/registry)”registerWasmTool() registers additional native-binary-to-WASM tools (formatters, linters, other
transpilers) behind the same lazy-load dispatcher bolo uses for its own bundler:
import { registerWasmTool, resolveWasmTool } from '@bolojs/registry';
registerWasmTool('my-tool', async () => { const mod = await import('my-wasm-tool'); return { async run(args, stdin) { const result = await mod.compile(args.join(' ')); return { stdout: result.output, stderr: result.errors, exitCode: 0 }; }, };});
const tool = await resolveWasmTool('my-tool');Unregistered commands fall through to ShellService.
Runtime shims (@bolojs/node-runtime-shims)
Section titled “Runtime shims (@bolojs/node-runtime-shims)”Some Node.js features need capabilities the browser can’t provide natively. Instead of
blocking these forever, createLiveShimRegistry exposes backend hooks:
| Feature | Default | Extension point |
|---|---|---|
| TCP/IP | HTTP-only (SW proxy) | netBackend: (deps) => nodeNetNamespace |
| UDP | Not supported | dgramBackend: (deps) => { createSocket } |
| TLS | Not supported | tlsBackend: (deps) => nodeTlsNamespace |
Native .node addons |
Not supported | nativeAddonLoader: (path, vfs) => moduleSync |
| Worker threads | Stub (isMainThread=true) |
workerThreadsBackend: (deps) => workerThreadsNamespace |
import { createLiveShimRegistry } from '@bolojs/node-runtime-shims';
const registry = createLiveShimRegistry({ vfs, sandbox, dgramBackend: ({ vfs }) => ({ createSocket: (type, onMessage) => new WebTransportDgramSocket(onMessage), }),});Each deps object passed to a backend factory is { vfs, sandbox }.
window.__browserbox (demo contract)
Section titled “window.__browserbox (demo contract)”The demo app exposes a global API for e2e tests and embedding scripts.
// Check readinessif (window.__browserbox_ready) { // Install packages await window.__browserbox.install(['react', 'react-dom']);
// Write a file into the VFS await window.__browserbox.vfs.writeFile('/src/App.jsx', '<h1>Hello</h1>');
// Load a URL in the preview iframe window.__browserbox.preview.loadUrl('https://sandbox.local/');}This is the demo shell’s external API, not a published library export.