Sandbox
Create, run, clean up — the basic loop
Sandbox.create(options?)— boots a sandbox.options.nameis a caller-given identity, unique among live sandboxes and held snapshots (409if already taken) — seebyName/getOrCreatebelow to find it again later.options.tags,options.baseUrl,options.authToken,options.vcpuCount,options.memSizeMib(override the daemon’s configured defaults, subject to its ceiling),options.imageId(boots from a registered image instead of the default rootfs — see Image),options.rateLimit({ bandwidthBytesPerSec?, opsPerSec? }, Firecracker’s own token-bucket I/O limiter — unlimited if omitted),options.drives(existing persistent drives to attach, see Drive). A call with nodrives/rateLimitmatching a configured pool’s image/resources transparently resumes a warm snapshot instead of cold-booting — see Pool.sandbox.runCommand(command, args?)— returns{ stdout, stderr, exitCode }.sandbox.readFile(path)— returns file contents asUint8Array.sandbox.writeFile(path, content)—contentis astringorUint8Array.sandbox.chmod(path, mode),sandbox.chown(path, uid, gid),sandbox.mkdir(path, options?)({ parents?: true }),sandbox.rename(from, to),sandbox.copy(from, to),sandbox.symlink(target, linkPath),sandbox.readlink(path),sandbox.truncate(path, size),sandbox.listDir(path)(returns entries with realisDir/isSymlink/size/mode/mtimemetadata) — the full filesystem operation set, all over the same vsock channelrunCommanduses.sandbox.pty(options?)— opens a live, interactive shell session and returns a nativeWebSocket(no added runtime dependency — needs Node.js ≥22 or a browser).options.cols/options.rowssize the terminal once, at open time; no live resize yet. Distinct fromrunCommand’s request/response shape — seekiln sandbox ptyfor the CLI equivalent.sandbox.stop(options?)— stops the sandbox. Default (options.keepomitted ortrue) preserves state as a resumable snapshot, returns{ kept, snapshotId }.{ keep: false }fully destroys instead.
Attaching to an id you already have
Sandbox.attach(id, options?)— wraps an already-existing sandbox id without a network round-trip.
Named sandboxes — find the same environment again later
Sandbox.byName(name, options?)— resolves a name to a live sandbox. Rejects (409) if the name currently belongs to a stopped (snapshotted) sandbox instead — usegetOrCreatefor that.Sandbox.getOrCreate(options)— resolvesoptions.nameto a sandbox in one race-safe call: live as-is, resumed if stopped, created fresh otherwise. Returns{ sandbox, created }.
Listing and filtering
Sandbox.list(options?)— lists sandboxes.options.tagsfilters by exact match on every given key.
Dev-server preview
sandbox.previewUrl(port, options?)— the URL a browser can open to reach a server listening onportinside the sandbox.
Local tunnel
The reverse of preview: expose a service running on this machine to code inside the sandbox.sandbox.tunnel(guestPort, options)—options.localPort(required),options.localHost(default127.0.0.1). Node-only (forwarding to a real local socket needsnode:net, which doesn’t exist in a browser). Returns aTunnelHandlewith.tunnelIdand.close(). See Local tunnel.
Streamed background exec
runCommand waits for the process to exit and returns everything at once — for a long-running command you want to watch live instead, start it in the background and attach a WebSocket to its output:
sandbox.execStream(command, args?)— startscommandin the background, returns a session id immediately.sandbox.attachLogs(sessionId)— returns aWebSocket(requires Node.js >= 22 or a browser’s built-inWebSocket) that replays buffered output then live-tails new output, whether or not the process has already finished.sandbox.listExecStreams()— lists every streamed session tracked against this sandbox, running or finished.- Not carried across
resume()/fork(), and doesn’t survive the daemon restarting — a fresh sandbox (or one just resumed) has no sessions yet.
Snapshot, resume, fork
sandbox.snapshot()— saves full state to disk and stops; returns a snapshot id.Sandbox.resume(snapshotId, options?)— boots from a snapshot, consuming it.Sandbox.fork(snapshotId, options?)— boots from a snapshot without consuming it.409while an earlier fork is still live.Sandbox.listSnapshots(options?)— lists snapshots.options.sourceSandboxIdnarrows to the one taken from that original sandbox id.
Remote storage mounts
sandbox.mount(options)— mounts an S3-compatible bucket atoptions.mountPathviarclone mount.options.endpointis the full URL of the S3-compatible service, never defaulted. Needs the optional FUSE-capable rootfs setup inSELF_HOSTING.md; throwsSandkilnApiErroron a guest-side mount failure. Not carried acrossresume()/fork()— it’s a live guest FUSE process, already captured by Firecracker’s own snapshot.sandbox.listMounts()— lists every remote-storage mount currently active in this sandbox.sandbox.unmount(mountId)— tears down one mount. Best-effort on the guest side — a failedumountis a daemon-log warning, not a failed request.