Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.microsandbox.dev/llms.txt

Use this file to discover all available pages before exploring further.

See Overview for configuration examples and Lifecycle for state management. The TypeScript SDK uses a builder-only entry point. Start every new sandbox from Sandbox.builder(name) and chain configuration calls before terminating with .create() or .createDetached().
import { Sandbox } from "microsandbox";

await using sandbox = await Sandbox.builder("demo")
  .image("alpine")
  .cpus(1)
  .memory(512)
  .create();

Static methods


Sandbox.builder()

static builder(name: string): SandboxBuilder
Begin building a new sandbox. Configure it with chainable setters, then call .create() or .createDetached() to boot it. Parameters
NameTypeDescription
namestringSandbox name
Returns
TypeDescription
SandboxBuilderFluent builder

Sandbox.get()

static get(name: string): Promise<SandboxHandle>
Get a handle to an existing sandbox (running or stopped). The handle provides status, configuration, and lifecycle control. Parameters
NameTypeDescription
namestringSandbox name
Returns
TypeDescription
SandboxHandleHandle with status and lifecycle control

Sandbox.list()

static list(): Promise<SandboxHandle[]>
List all sandboxes (running, stopped, and crashed). Handles returned from list() are read-only — call Sandbox.get(name) to get a live handle for lifecycle calls. Returns
TypeDescription
SandboxHandle[]All sandboxes (read-only handles)

Sandbox.remove()

static remove(name: string): Promise<void>
Delete a stopped sandbox and all its state from disk. Fails if the sandbox is still running. Parameters
NameTypeDescription
namestringSandbox name

Sandbox.start()

static start(name: string): Promise<Sandbox>
Restart a previously stopped sandbox. The VM reboots using the persisted configuration. Parameters
NameTypeDescription
namestringName of a stopped sandbox
Returns
TypeDescription
SandboxRunning sandbox

Sandbox.startDetached()

static startDetached(name: string): Promise<Sandbox>
Restart a stopped sandbox in detached mode. Parameters
NameTypeDescription
namestringName of a stopped sandbox
Returns
TypeDescription
SandboxRunning sandbox

Instance properties


name

readonly name: string
Sandbox name.

config

readonly config: Readonly<SandboxConfig>
The frozen configuration the sandbox was built with.

ownsLifecycle

readonly ownsLifecycle: boolean
Whether this handle owns the sandbox lifecycle. true in attached mode (the auto-disposer will stop the sandbox), false in detached mode.

Instance methods


detach()

detach(): Promise<void>
Release the handle without stopping the sandbox. Reconnect later with Sandbox.get().

drain()

drain(): Promise<void>
Start a graceful drain. Existing commands run to completion, new exec calls are rejected.

fs()

fs(): SandboxFs
Get a filesystem handle for reading and writing files inside the running sandbox. See Filesystem for the full API. Returns
TypeDescription
SandboxFsFilesystem handle

kill()

kill(): Promise<void>
Force-terminate the sandbox immediately. No graceful shutdown.

metrics()

metrics(): Promise<SandboxMetrics>
Get a point-in-time snapshot of the sandbox’s resource usage. Returns
TypeDescription
SandboxMetricsCPU, memory, disk, network metrics

metricsStream()

metricsStream(intervalMs: number): Promise<MetricsStream>
Stream resource metrics at a regular interval. The returned stream supports both recv() and for await...of. Parameters
NameTypeDescription
intervalMsnumberMilliseconds between metric snapshots
Returns
TypeDescription
MetricsStreamAsync stream of metrics

logs()

logs(opts?: LogReadOptions): Promise<LogEntry[]>
Read captured output from the sandbox’s exec.log. Backed by an on-disk JSON Lines file the runtime writes via the relay tap. Works on running and stopped sandboxes alike — there is no protocol traffic. The same method is available on SandboxHandle for callers that don’t want to start the sandbox first. The default sources are "stdout", "stderr", and "output" (PTY-merged). Pass "system" to also include synthetic lifecycle markers and runtime/kernel diagnostic lines.
import { Sandbox } from "microsandbox";

const handle = await Sandbox.get("web");

// Default — all user-program output, regardless of pipe/pty mode
const entries = await handle.logs();

for (const e of entries) {
  const source =
    e.source === "stdout" ? "OUT" :
    e.source === "stderr" ? "ERR" :
    e.source === "output" ? "PTY" :
    "SYS";

  console.log(
    `[${e.timestamp.toISOString()}] ${source} ${e.sessionId}: ${e.text().trimEnd()}`
  );
}

// Filtered: last 50 entries from the past hour, including system lines
const recent = await handle.logs({
  tail: 50,
  since: new Date(Date.now() - 60 * 60 * 1000),
  sources: ["stdout", "stderr", "output", "system"],
});
Parameters
NameTypeDescription
optsLogReadOptions ?Filters: tail, since, until, sources. Omit for the default user-program sources.
Returns
TypeDescription
Promise<LogEntry[]>Matching entries in chronological order

removePersisted()

removePersisted(): Promise<void>
Remove the sandbox and all its persisted state from disk.

stop()

stop(): Promise<void>
Gracefully shut down the sandbox.

stopAndWait()

stopAndWait(): Promise<ExitStatus>
Stop the sandbox and wait for the exit status. Returns
TypeDescription
ExitStatusExit code and success flag

wait()

wait(): Promise<ExitStatus>
Block until the sandbox exits on its own. Returns
TypeDescription
ExitStatusExit code and success flag

[Symbol.asyncDispose]()

[Symbol.asyncDispose](): Promise<void>
Implements AsyncDisposable so the sandbox can be used with await using. When the binding goes out of scope, the sandbox is stopped (best-effort) — but only if ownsLifecycle is true.

PatchBuilder

Fluent builder for the ordered list of pre-boot rootfs patches. Used in SandboxBuilder.patch(p => p...). Each method appends one operation; calls are chainable. By default a method that targets a path already present in the image errors at boot; pass { replace: true } on the operation to allow overwriting. mkdir and remove are idempotent. See Patches for conceptual context.

append()

append(path: string, content: string): this
Append content to an existing file at path. If the file lives in a lower image layer, it’s copied up first. Parameters
NameTypeDescription
pathstringAbsolute path inside the guest
contentstringText to append

copyDir()

copyDir(src: string, dst: string, opts?: { replace?: boolean }): this
Recursively copy a host directory at src into the guest rootfs at dst. Parameters
NameTypeDescription
srcstringHost source directory
dststringAbsolute destination path inside the guest
opts.replacebooleanWhen true, overwrite an existing path at dst

copyFile()

copyFile(
  src: string,
  dst: string,
  opts?: { mode?: number; replace?: boolean },
): this
Copy a single host file at src into the guest rootfs at dst. Parameters
NameTypeDescription
srcstringHost source file
dststringAbsolute destination path inside the guest
opts.modenumberFile mode, e.g. 0o644. Omit to keep the source mode
opts.replacebooleanWhen true, overwrite an existing path at dst

file()

file(
  path: string,
  content: Buffer,
  opts?: { mode?: number; replace?: boolean },
): this
Write raw bytes at path. Parameters
NameTypeDescription
pathstringAbsolute path inside the guest
contentBufferRaw byte content
opts.modenumberFile mode, e.g. 0o644
opts.replacebooleanWhen true, overwrite an existing path

mkdir()

mkdir(path: string, opts?: { mode?: number }): this
Create a directory at path. Idempotent: a no-op if the directory already exists. Parameters
NameTypeDescription
pathstringAbsolute path inside the guest
opts.modenumberDirectory mode, e.g. 0o755

remove()

remove(path: string): this
Delete a file or directory at path. Idempotent: a no-op if the path doesn’t exist. Parameters
NameTypeDescription
pathstringAbsolute path inside the guest

symlink(target: string, link: string, opts?: { replace?: boolean }): this
Create a symlink at link pointing to target. Parameters
NameTypeDescription
targetstringWhat the symlink points to (literal symlink target text)
linkstringAbsolute path of the symlink itself
opts.replacebooleanWhen true, overwrite an existing path at link

text()

text(
  path: string,
  content: string,
  opts?: { mode?: number; replace?: boolean },
): this
Write UTF-8 text content at path. Parameters
NameTypeDescription
pathstringAbsolute path inside the guest
contentstringText content
opts.modenumberFile mode, e.g. 0o644
opts.replacebooleanWhen true, overwrite an existing path

Types

SandboxBuilder

Fluent configuration builder returned by Sandbox.builder(name). Every setter returns the same builder so calls can be chained.
MethodDescription
image(src)OCI image ("alpine"), local rootfs path, or a RootfsSource. Required.
cpus(n)Virtual CPUs
memory(mib)Guest memory in MiB
logLevel(level)Override log verbosity
quietLogs()Suppress log output
workdir(path)Default working directory for commands
shell(shell)Shell binary used by sandbox.shell(...)
entrypoint(iter)Override the image’s stored ENTRYPOINT. Consulted by msb exec / msb run (CLI command resolution), not by sandbox.exec / sandbox.shell — those pass cmd literally
init(cmd, args?)Hand off PID 1 to cmd (absolute path or "auto") after agentd setup. See Custom init system
initWith(cmd, i => ...)Like init but with a closure-builder for argv and env (.arg, .args, .env, .envs)
hostname(name)Guest hostname
user(user)Default guest user
pullPolicy(policy)Image pull behavior
libkrunfwPath(path)Override the bundled libkrunfw shared library
env(key, value)Add a single env var
envs(record | iter)Add many env vars
script(name, content)Mount a script at /.msb/scripts/<name>
scripts(record | iter)Mount many scripts
replace()Replace any existing sandbox with the same name (10s SIGTERM grace, then SIGKILL)
replaceWithGrace(graceMs)Same as replace() with a custom SIGTERM grace in milliseconds. 0 skips SIGTERM. Implies replace()
maxDuration(secs)Maximum sandbox lifetime
idleTimeout(secs)Stop the sandbox after this many idle seconds
volume(guestPath, m => ...)Mount a volume — see Volumes
patch(p => ...)Modify the rootfs before boot — see Snapshots
addPatch(patch)Append a pre-built Patch
registry(r => r.auth(...).insecure().caCertsPath(...))Configure the OCI registry
port(host, guest)Publish a TCP port
portUdp(host, guest)Publish a UDP port
disableNetwork()Disable networking entirely
network(n => ...)Configure DNS / TLS / policy / secrets — see Networking
secret(s => ...)Add a secret via SecretBuilder
secretEnv(envVar, value, allowedHost)Auto-placeholder shorthand. Generates $MSB_<ENV_VAR>.
build(): Promise<SandboxConfig>Materialize without booting
create(): Promise<Sandbox>Build and boot in attached mode
createDetached(): Promise<Sandbox>Build and boot in detached mode
createWithPullProgress(): Promise<PullProgressCreate>Build and boot in attached mode while streaming image pull progress
createDetachedWithPullProgress(): Promise<PullProgressCreate>Build and boot in detached mode while streaming image pull progress

LogLevel

Sandbox process log verbosity.
ValueDescription
'debug'Debug and higher
'error'Errors only
'info'Info and higher
'trace'Most verbose - all diagnostic output
'warn'Warnings and errors only

LogEntry

A class wrapping one captured log entry. Returned by logs().
Property / MethodTypeDescription
timestampDateWall-clock capture time on the host
sourceLogSourceWhere the chunk came from
sessionIdnumber | nullRelay-monotonic session id; null for "system" entries
dataUint8ArrayThe chunk’s bytes (UTF-8 lossy decoded by default)
text()stringConvenience: UTF-8 decode of data (lossy — invalid bytes are replaced)

LogReadOptions

Filters passed to logs(). All fields optional. Omit the argument entirely for the default sources (stdout + stderr + output).
FieldTypeDescription
tailnumber?Show only the last N entries after other filters apply
sinceDate?Inclusive lower bound on entry timestamp
untilDate?Exclusive upper bound on entry timestamp
sourcesLogSource[]?Sources to include. Omit = ["stdout", "stderr", "output"]. Add "system" to merge runtime/kernel diagnostics.

LogSource

Tag indicating where a captured log entry came from. String literal type:
type LogSource = "stdout" | "stderr" | "output" | "system";
ValueDescription
"stdout"Captured from a session’s stdout (pipe mode — streams stayed separated)
"stderr"Captured from a session’s stderr (pipe mode)
"output"Captured from a session running in PTY mode. PTY allocation merges stdout and stderr at the kernel level inside the guest, so they arrive as a single stream — tagged "output" rather than mislabelled as "stdout".
"system"Synthetic entry: lifecycle markers in exec.log plus runtime/kernel diagnostic lines merged in at read time when "system" is requested.

MetricsStream

Async stream for receiving periodic metrics snapshots.
MethodReturnsDescription
[Symbol.asyncIterator]AsyncIterator<SandboxMetrics>Use with for await...of
recv()Promise<SandboxMetrics | null>Receive next snapshot. Returns null when the stream ends.
[Symbol.asyncDispose]()Promise<void>Stop iterating; safe to use with await using.

PullPolicy

Controls when the SDK fetches an OCI image from the registry.
ValueDescription
'always'Pull the image every time, even if cached locally
'if-missing'Pull only if the image is not already cached. This is the default.
'never'Never pull; fail if the image is not cached locally

PullProgress

Image pull and materialize progress event emitted by PullProgressCreate. A discriminated union. Narrow on kind to access variant-specific fields:
const creation = await Sandbox.builder("demo")
  .image("alpine")
  .createWithPullProgress();

for await (const ev of creation) {
  if (ev.kind === "layerDownloadProgress") {
    console.log(`${ev.layerIndex}: ${ev.downloadedBytes}/${ev.totalBytes}`);
  }
}

const sandbox = await creation.awaitSandbox();
kind valueAdditional fields
'resolving'reference: string
'resolved'reference: string, manifestDigest: string, layerCount: number, totalDownloadBytes?: number
'layerDownloadProgress'layerIndex: number, digest: string, downloadedBytes: number, totalBytes?: number
'layerDownloadComplete'layerIndex: number, digest: string, downloadedBytes: number
'layerDownloadVerifying'layerIndex: number, digest: string
'layerMaterializeStarted'layerIndex: number, diffId: string
'layerMaterializeProgress'layerIndex: number, bytesRead: number, totalBytes: number
'layerMaterializeWriting'layerIndex: number
'layerMaterializeComplete'layerIndex: number, diffId: string
'stitchMergingTrees'layerCount: number
'stitchWritingFsmeta'(none)
'stitchWritingVmdk'(none)
'stitchComplete'(none)
'complete'reference: string, layerCount: number
totalDownloadBytes and totalBytes on the 'resolved' / 'layerDownloadProgress' variants may be absent if the manifest omits sizes.

PullProgressCreate

Async iterable creation handle returned by Sandbox.builder(name).createWithPullProgress() and Sandbox.builder(name).createDetachedWithPullProgress(). Yields PullProgress events as the image is resolved, downloaded, and materialized. Call awaitSandbox() after iteration to obtain the live sandbox.
MethodReturnsDescription
[Symbol.asyncIterator]AsyncGenerator<PullProgress>Use with for await...of
progress.recv()Promise<PullProgress | null>Receive next event. Returns null when the stream ends.
awaitSandbox()Promise<Sandbox>Resolve the underlying creation task and return the running sandbox. Single-shot: a second call throws an already-consumed error.

SandboxConfig

Frozen configuration object — produced by SandboxBuilder.build() and exposed as the config property on a Sandbox. You generally should not construct this by hand; use the builder.
FieldTypeDescription
namestringSandbox name
imageRootfsSourceOCI / bind / disk discriminated union
cpusnumber | nullVirtual CPUs
memoryMibnumber | nullGuest memory in MiB
logLevelLogLevel | nullLog verbosity
quietLogsbooleanSuppress log output
workdirstring | nullDefault working directory
shellstring | nullShell binary
entrypointstring[] | nullOverride image entrypoint
cmdstring[] | nullOverride image cmd
hostnamestring | nullGuest hostname
userstring | nullDefault guest user
libkrunfwPathstring | nullCustom libkrunfw path
envArray<readonly [string, string]>Environment variables
scriptsArray<readonly [string, string]>Named scripts
mountsVolumeMount[]Volume mounts
patchesPatch[]Rootfs modifications applied before boot
pullPolicyPullPolicy | nullImage pull behavior
replacebooleanReplace existing sandbox with same name
replaceWithGraceMsnumberMilliseconds to wait after SIGTERM before escalating to SIGKILL (default 10000; 0 skips SIGTERM)
maxDurationSecsnumber | nullMaximum sandbox lifetime
idleTimeoutSecsnumber | nullStop after idle time
portsTcpArray<readonly [number, number]>TCP host→guest mappings
portsUdpArray<readonly [number, number]>UDP host→guest mappings
registryRegistryConfig | nullRegistry connection settings
networkNetworkConfig | nullNetwork configuration
disableNetworkbooleanDisable networking entirely
secretsSecretEntry[]Secret entries (top-level)

SandboxHandle

A lightweight handle to an existing sandbox (running or stopped). Obtained via Sandbox.get() or Sandbox.list(). Handles from Sandbox.get(name) are live — they expose lifecycle methods (start, stop, kill, connect, etc). Handles in the array returned by Sandbox.list() are read-only: calling lifecycle methods on them throws. Use Sandbox.get(name) to upgrade to a live handle.
Property / MethodTypeDescription
namestringSandbox name
statusSandboxStatusCurrent status
configJsonstringRaw JSON configuration
createdAtDate | nullCreation timestamp
updatedAtDate | nullLast update timestamp
metrics()Promise<SandboxMetrics>Point-in-time resource metrics
logs()Promise<LogEntry[]>Read captured exec.log (works without starting)
start()Promise<Sandbox>Start in attached mode
startDetached()Promise<Sandbox>Start in detached mode
connect()Promise<Sandbox>Connect to a running sandbox without taking ownership
stop()Promise<void>Graceful shutdown
kill()Promise<void>Force terminate
remove()Promise<void>Delete sandbox and state

SandboxMetrics

Point-in-time resource usage snapshot.
FieldTypeDescription
cpuPercentnumberCPU usage as a percentage
diskReadBytesnumberTotal bytes read from disk since boot
diskWriteBytesnumberTotal bytes written to disk since boot
memoryBytesnumberCurrent memory usage in bytes
memoryLimitBytesnumberMemory limit in bytes
netRxBytesnumberTotal bytes received over the network since boot
netTxBytesnumberTotal bytes sent over the network since boot
timestampDateWhen this measurement was taken
uptimeMsnumberTime since the sandbox was created (ms)

SandboxStatus

ValueDescription
'crashed'VM exited unexpectedly
'draining'Graceful shutdown in progress
'running'Guest agent is ready
'stopped'VM shut down; can be restarted