SDK overview
@userland-run/nano-sdk is the supported way to embed NanoVM: a typed, ESM-only package with no runtime dependencies that boots the VM and exposes files, processes, a shell engine, server previews, a JavaScript sandbox, a worker transport, a signed app catalog and a terminal UI.
npm install @userland-run/nano-sdk
These docs describe SDK 0.2.10, the version the live samples run on, and the runtime it vendors (nano v0.2.1, Node.js v25.4.0). Recent additions: typed worker catalog wrappers (0.2.7), host-engine server previews and terminal dispose() (0.2.8), a nodert CommonJS fix (0.2.9) and the agent tools subpath (0.2.10). The SDK is licensed MPL-2.0 OR LicenseRef-UEL; the vendored runtime is AGPL-3.0-only OR LicenseRef-UEL.
Entry points
@userland-run/nano-sdkcreateNano, Nano, Vfs, Shell, NodeRuntime, serve, worker, catalog, createHeadless, provision@userland-run/nano-sdk/terminal<nano-terminal>, createTerminal); a separate bundle so headless apps never download it@userland-run/nano-sdk/worker@userland-run/nano-sdk/agent@userland-run/nano-sdk/service-workernano-sw.js: cross-origin isolation and preview routing (Requirements)Boot a VM
import { createNano } from "@userland-run/nano-sdk";
const nano = await createNano({
image: { wasm: "/nano/console.wasm" }, // emulator + BusyBox
ramMB: 512,
engines: { node: "host" }, // node() on the browser's JS engine
scripting: { wasm: "/nano/boa.wasm" }, // optional: the JS sandbox
});Every option is documented with a runnable sample on Configuration. The samples on these pages use the instance this page boots, available as nano.
A tour in six lines
Files, a BusyBox command, a shell pipeline and Node.js, all against one virtual filesystem.
nano.fs.writeFile("/work/nums.txt", "3\n1\n2\n");
print((await nano.run("cat /work/nums.txt")).stdout.split("\n").join(" ").trim());
print((await nano.shExec("sort -n /work/nums.txt | tr '\\n' ' '")).stdout.trim());
const r = await nano.node(["-e", "const n = require('fs').readFileSync('/work/nums.txt', 'utf8').trim().split('\\n').map(Number); console.log('sum', n.reduce((a, b) => a + b))"]);
print(r.stdout.trim());
print(nano.fs.list("/work").map((e) => e.name).join(", "));3 1 2 1 2 3 sum 6 .keep, nums.txt
What the SDK gives you
Behavior to know
- VM operations are serialized. One VM runs one thing at a time;
run,shExec, VMnode, filesystem mutations and snapshots queue in FIFO order. See Running commands. - A server holds the VM. While a
startServer()launch runs, other VM calls reject immediately until you stop it. See Serve mode. - Output is combined.
stdoutin every result holds stdout and stderr interleaved as the guest wrote them. - Main thread by default.
createNano()runs the VM on the calling thread; long runs block the UI. Use the worker transport for interactive apps.
Finished apps built on the SDK are in the examples gallery; product-level tours are under features.