Use as a library
@nimbus-sh/core is the OS without the Worker: the durable SQLite
filesystem, the shell with 60+ Unix commands, and the WASI runtime layer.
It has no Cloudflare dependency. You hand it a SQLite and get back .fs
and .exec.
In bun or node
Section titled “In bun or node”import { Database } from 'bun:sqlite';import { NimbusWorkspace } from '@nimbus-sh/core/workspace';
const db = new Database('workspace.sqlite');const sql = { exec(q, ...p) { const st = db.query(q); if (st.columnNames.length === 0) { db.run(q, ...p); return []; } return st.all(...p); },};const transactions = { storage: { transactionSync: (cb) => db.transaction(cb)() } };
const ws = await NimbusWorkspace.create({ sql, transactions, generation: 1 });
await ws.fs.writeFile('/home/user/hello.txt', 'hi\n');await ws.exec('cat /home/user/hello.txt | wc -c'); // { stdout: '3\n', exitCode: 0 }node:sqlite works the same way. The workspace behaves as a tenant in a
database you own. It creates and touches only its own tables, and
destroy() drops those tables without calling deleteAll().
transactionSync must be a real transaction. An implementation that only
calls the callback turns every atomic write into a torn one.
In your own Durable Object
Section titled “In your own Durable Object”The same class runs over ctx.storage.sql. The host must supply a
generation that never repeats across instances. Pids derive from it, so
a repeated generation gives a dead process live write authority. Persist a
counter and bump it once per instance. A constant or Date.now() does not
work:
import { DurableObject } from 'cloudflare:workers';import { NimbusWorkspace } from '@nimbus-sh/core/workspace';
export class Workspace extends DurableObject { private ws?: Promise<NimbusWorkspace>;
private workspace(): Promise<NimbusWorkspace> { this.ws ??= (async () => { const generation = ((await this.ctx.storage.get<number>('generation')) ?? 0) + 1; await this.ctx.storage.put('generation', generation); return NimbusWorkspace.create({ sql: this.ctx.storage.sql, transactions: this.ctx, generation, }); })(); return this.ws; }
async exec(command: string) { return (await this.workspace()).exec(command); }}Cold starts, hibernation wakes, and resets all re-instantiate the class.
The counter bumps once per instance, and the code uses the bumped value
only after the put resolves.
Runtime packages
Section titled “Runtime packages”The wasm runtimes are separate npm packages, so a filesystem-only embedder never downloads a Python interpreter:
npm install @nimbus-sh/runtime-bash @nimbus-sh/runtime-cpythonimport bash from '@nimbus-sh/runtime-bash';import cpython from '@nimbus-sh/runtime-cpython';import { localFacetHost } from '@nimbus-sh/core';
const ws = await NimbusWorkspace.create({ sql, transactions, generation: 1, facets: localFacetHost(), runtimes: [bash, cpython],});
await ws.exec('bash -c "echo $((6*7))"'); // GNU bash 5.2, real BusyBox childrenawait ws.exec('python -c "print(6*7)"'); // CPython 3.13 with the real stdlib@nimbus-sh/runtime-ruby (Ruby 3.3) and @nimbus-sh/runtime-clang
(clang → wasm32-wasi) work the same way. Every package carries the same
manifests and sha256-verified blobs the hosted product serves from R2.
localFacetHost() covers bun and node only. On workerd the CSP forbids
request-time WebAssembly.instantiate. Wasm rides the Worker Loader
module map instead, which is the machinery in @nimbus-sh/worker and
@nimbus-sh/fabric. The shell, the coreutils, and the filesystem do not
need it.
The Durable Object machinery
Section titled “The Durable Object machinery”@nimbus-sh/fabric is the Cloudflare half as a standalone library, for
building your own thing on Durable Objects rather than embedding Nimbus.
It holds the resident-process fabric, warm Worker Loader pools, the
multi-reason alarm multiplexer, instance-reset detection, the durable
launch journal, and byte-accounted turn pacing. Its
README
has the measured platform limits: DO storage, CPU, facet, and RPC ceilings.
For the full hosted product shape (sessions, terminal, ports, auth), use
create-nimbus-app instead of composing these by hand.