SDK
Running commands
Four ways to run a process inside the VM — from raw BusyBox argv to a full sh script — plus streamed output and interactive stdin.
The four entry points
Method
Use it for
nano.run("echo hi")
raw BusyBox — whitespace-split argv, no shell parsing
nano.exec(["echo", "a b"])
safe argv via sh — single-quoted, no shell operators
nano.shExec("a | b > c")
a full sh line/script — pipes, redirects, operators
nano.node(["-e", "…"])
the real Node ELF with an explicit argv array
javascript
await nano.run("echo hello world");
await nano.exec(["echo", "a b", "c"]); // argv-safe
await nano.shExec("sort -rn data.txt | head -5"); // shell features
await nano.node(["-e", "console.log(2 + 2)"]); // nodeOptions and result
Every call accepts ExecOptions and resolves to an ExecResult.
ExecOptions
Effect
onData(chunk)
callback for streamed output as it is produced
maxSteps
instruction budget (default 2,000,000 for BusyBox, 2e9 for Node)
ExecResult
Meaning
exitCode
process exit status
stdout
combined stdout + stderr as text
cancelled
true if the run was cancelled
javascript
const res = await nano.run("find /usr -name \"*.so\"", {
onData: (chunk) => term.write(chunk),
maxSteps: 10_000_000,
});
console.log(res.exitCode);Instruction budget
maxSteps caps how long a run may execute. BusyBox commands finish well under the default; Node's cold V8 boot needs the larger budget, which node() sets for you. Raise it for heavy work, or lower it to bound untrusted code.
Interactive stdin
For REPL-style or interactive programs, switch on interactive stdin and feed input as it arrives.
javascript
nano.setInteractiveStdin(true);
nano.writeStdin("hello\n");
nano.closeStdin();Interactive TTY stdin is still maturing — line-oriented dispatch is solid; full raw-mode programs (vi, top) are a work in progress.
Cancel & clean up
javascript
nano.cancel(); // halt the current run nano.destroy(); // free the VM's memory