userland.rundocs70Try the demo
Reference

CLI and raw JS API

Run RISC-V Linux binaries from the command line with test/run.mjs in the nano repository, or drive the low-level NanoVM class that the SDK wraps (reachable as nano.raw).

The command-line runner

test/run.mjs loads wasm/nano.wasm into Node.js, loads one ELF and runs it, printing the guest's output and diagnostics (instruction count, block-cache statistics) to stderr. It is a development tool for the emulator, not a product CLI.

bash
node test/run.mjs [elf] [--load local:/guest/path]… [--trace] [--stdin] [--tty] [--verbose] [--cmd <applet> args…]
Flag / env
Effect
elf
the ELF to run (default test/hello.elf), e.g. runners/riscv/images/busybox
--cmd <program> args…
replace argv (everything after --cmd); for BusyBox the first word is the applet
--load local:/guest
copy a local text file into the guest filesystem (repeatable)
--trace
count syscalls (needs a build with the trace feature: make build-minimal or make build-trace)
--stdin
feed the host's stdin to the guest, then EOF
--tty
enable the in-VM tty line discipline
--verbose / -v
instruction-level diagnostics
NANOVM_WASM
path of the wasm to load (default wasm/nano.wasm)
NANOVM_RAM_MB
memory size (default 2000 − wasmMB − 20)
bash
$ node test/run.mjs runners/riscv/images/busybox --cmd echo "Hello from RISC-V"
Hello from RISC-V
Exit code 0  (~100000 insns)

$ node test/run.mjs runners/riscv/images/node --cmd node -e "console.log(process.arch, process.version)"
riscv64 v25.4.0
Exit code 0  (~501600000 insns)

Output above is from a run of nano v0.2.1 on an Apple M3 Max (Node.js 24.11.1); stderr lines other than the exit line are omitted. runners/riscv/images/ holds the BusyBox (1,149,392 bytes) and Node.js ELFs via Git LFS.

The raw NanoVM API

runners/riscv/host/nanovm.mjs is the browser wrapper around the WebAssembly module: it owns the shared memory, the in-memory filesystem, the virtual server and the run loop. The SDK vendors it and exposes the instance as nano.raw. Prefer the SDK: it adds types, safe defaults, the VM lock and the higher-level modes. Wrap direct raw runs in nano.withVmLock().

OptionTypeDefaultDescription
NanoVM.create({ wasm, ramMB, busyboxUrl, nodeUrl })Promise<NanoVM>ramMB 512Instantiate the module with a shared memory of ramMB.
run(command, { onStdout, maxSteps })Promise<ExecResult>maxSteps 2e6Run a BusyBox command line (whitespace-split).
node(...args, opts)Promise<ExecResult>—Run the Node.js ELF.
addFile(path, content, mode?)void—Create a file (parents created).
readFileString(path) / listDir(path)string | null / DirEntry[] | null—Read a file / list a directory.
makeDir / removePath / renamePath / cwd()—Direct MemFS operations.
loadTarGz(bytes)Promise<void>—Unpack an archive.
writeStdin / setInteractiveStdin / closeStdin / cancelRun—Standard input and cancellation.
setNetwork({ corsProxyUrl, disabled })void—Configure the outbound network device (see Networking).
snapshot() / restoreAndRun(snap, script, opts)—Snapshot primitives used by NodeRuntime.
instructionCount()number—Guest instructions retired so far.
virtualServer.injectConnection(port, request)Promise<Uint8Array>—Inject one HTTP request (see Virtual server).
SDK · JavaScript

nano.raw: the NanoVM instance

Direct filesystem calls and the instruction counter. The counter shows how much guest code a shell pipeline executes.

javascript
const raw = nano.raw;
raw.addFile("/work/raw.txt", "via raw\n");
print(raw.readFileString("/work/raw.txt").trim(), JSON.stringify(raw.listDir("/work").map((e) => e.name)));
const before = raw.instructionCount();
const r = await nano.withVmLock(() => raw.run("echo counted"));
print(r.stdout.trim(), "| guest instructions:", raw.instructionCount() - before > 0);
loading…
Expected output
via raw [".keep","raw.txt"]
counted | guest instructions: true

Prefer the SDK for apps

For a tour of the emulator itself see RISC-V emulator. Everything above is reachable through @userland-run/nano-sdk with types: createNano, Running commands, Filesystem. The raw class has no compatibility guarantees between releases.