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)"]);   // node

Options 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