> ## 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.

# Sandbox

> TypeScript SDK - Sandbox API reference

See [Overview](/sandboxes/overview) for configuration examples and [Lifecycle](/sandboxes/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()`. Use `.detached(true)` before `.create()` for detached/background mode. Sandbox names must be non-empty and no longer than 128 UTF-8 bytes.

```typescript theme={null}
import { Sandbox } from "microsandbox";

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

## Static methods

***

#### Sandbox.builder()

```typescript theme={null}
static builder(name: string): SandboxBuilder
```

Begin building a new sandbox. Configure it with chainable setters, then call `.create()` to boot it.

**Parameters**

| Name | Type     | Description                         |
| ---- | -------- | ----------------------------------- |
| name | `string` | Sandbox name, up to 128 UTF-8 bytes |

**Returns**

| Type                                | Description    |
| ----------------------------------- | -------------- |
| [`SandboxBuilder`](#sandboxbuilder) | Fluent builder |

#### Sandbox.get()

```typescript theme={null}
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**

| Name | Type     | Description                         |
| ---- | -------- | ----------------------------------- |
| name | `string` | Sandbox name, up to 128 UTF-8 bytes |

**Returns**

| Type                              | Description                              |
| --------------------------------- | ---------------------------------------- |
| [`SandboxHandle`](#sandboxhandle) | Handle with status and lifecycle control |

***

#### Sandbox.list()

```typescript theme={null}
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**

| Type                                | Description                       |
| ----------------------------------- | --------------------------------- |
| [`SandboxHandle[]`](#sandboxhandle) | All sandboxes (read-only handles) |

***

#### Sandbox.remove()

```typescript theme={null}
static remove(name: string): Promise<void>
```

Delete a stopped sandbox and all its state from disk. Fails if the sandbox is still running.

**Parameters**

| Name | Type     | Description                         |
| ---- | -------- | ----------------------------------- |
| name | `string` | Sandbox name, up to 128 UTF-8 bytes |

***

#### Sandbox.start()

```typescript theme={null}
static start(name: string): Promise<Sandbox>
```

Restart a previously stopped sandbox. The VM reboots using the persisted configuration.

**Parameters**

| Name | Type     | Description                                      |
| ---- | -------- | ------------------------------------------------ |
| name | `string` | Name of a stopped sandbox, up to 128 UTF-8 bytes |

**Returns**

| Type                           | Description     |
| ------------------------------ | --------------- |
| [`Sandbox`](#instance-methods) | Running sandbox |

***

#### Sandbox.startDetached()

```typescript theme={null}
static startDetached(name: string): Promise<Sandbox>
```

Restart a stopped sandbox in detached mode.

**Parameters**

| Name | Type     | Description                                      |
| ---- | -------- | ------------------------------------------------ |
| name | `string` | Name of a stopped sandbox, up to 128 UTF-8 bytes |

**Returns**

| Type                           | Description     |
| ------------------------------ | --------------- |
| [`Sandbox`](#instance-methods) | Running sandbox |

***

## Instance properties

***

#### name

```typescript theme={null}
readonly name: string
```

Sandbox name. Names are limited to 128 UTF-8 bytes.

***

#### ownsLifecycle

```typescript theme={null}
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()

```typescript theme={null}
detach(): Promise<void>
```

Release the handle without stopping the sandbox. Reconnect later with [`Sandbox.get()`](#sandboxget).

***

#### requestDrain()

```typescript theme={null}
requestDrain(): Promise<void>
```

Request a graceful drain and return once the request is sent. Existing commands run to completion, but new `exec` calls are rejected. Use [`waitUntilStopped()`](#waituntilstopped) when the caller needs stopped-state observation.

***

#### fs()

```typescript theme={null}
fs(): SandboxFsOps
```

Get a filesystem handle for reading and writing files inside the running sandbox. See [Filesystem](/sdk/typescript/filesystem) for API details.

**Returns**

| Type                                         | Description       |
| -------------------------------------------- | ----------------- |
| [`SandboxFsOps`](/sdk/typescript/filesystem) | Filesystem handle |

***

#### kill()

```typescript theme={null}
kill(): Promise<void>
```

Force-terminate the sandbox and wait until stopped state is observed. No graceful shutdown. Pending writes that the workload hasn't `fsync`'d may be lost — same durability semantics as a sudden power loss on a physical machine. Use [`stop()`](#stop) for graceful shutdown that gives the workload a chance to flush.

***

#### metrics()

```typescript theme={null}
metrics(): Promise<SandboxMetrics>
```

Get a point-in-time snapshot of the sandbox's resource usage.

**Returns**

| Type                                | Description                        |
| ----------------------------------- | ---------------------------------- |
| [`SandboxMetrics`](#sandboxmetrics) | CPU, memory, disk, network metrics |

***

#### config()

```typescript theme={null}
config(): Promise<SandboxConfig>
```

Get the configuration the sandbox was built with.

***

#### metricsStream()

```typescript theme={null}
metricsStream(intervalMs: number): Promise<MetricsStream>
```

Stream resource metrics at a regular interval. The returned stream supports both `recv()` and `for await...of`.

**Parameters**

| Name       | Type     | Description                           |
| ---------- | -------- | ------------------------------------- |
| intervalMs | `number` | Milliseconds between metric snapshots |

**Returns**

| Type                              | Description             |
| --------------------------------- | ----------------------- |
| [`MetricsStream`](#metricsstream) | Async stream of metrics |

***

#### logs()

```typescript theme={null}
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`](#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.

```typescript theme={null}
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**

| Name | Type                                    | Description                                                                              |
| ---- | --------------------------------------- | ---------------------------------------------------------------------------------------- |
| opts | [`LogReadOptions`](#logreadoptions) `?` | Filters: `tail`, `since`, `until`, `sources`. Omit for the default user-program sources. |

**Returns**

| Type                                   | Description                             |
| -------------------------------------- | --------------------------------------- |
| `Promise<`[`LogEntry`](#logentry)`[]>` | Matching entries in chronological order |

***

#### remove()

```typescript theme={null}
remove(): Promise<void>
```

Remove the sandbox and all its persisted state from disk.

***

#### stop()

```typescript theme={null}
stop(): Promise<void>
```

Gracefully shut down the sandbox and wait until stopped state is observed. Lets the sandbox finish writing any pending data to disk before it exits, so files written inside the sandbox aren't lost across a later restart. Waits up to 10\_000 ms for a clean exit; if the sandbox is still running after that, it is force-killed.

***

#### stopWithTimeout()

```typescript theme={null}
stopWithTimeout(timeoutMs: number): Promise<void>
```

Gracefully shut down the sandbox with an explicit observation timeout before force-kill escalation.

***

#### requestStop()

```typescript theme={null}
requestStop(): Promise<void>
```

Request graceful shutdown and return once the request is sent.

***

#### requestKill()

```typescript theme={null}
requestKill(): Promise<void>
```

Request force termination and return once the signal is sent.

***

#### killWithTimeout()

```typescript theme={null}
killWithTimeout(timeoutMs: number): Promise<void>
```

Force-terminate the sandbox and wait up to `timeoutMs` for stopped-state observation.

***

#### waitUntilStopped()

```typescript theme={null}
waitUntilStopped(): Promise<SandboxStopResult>
```

Block until the sandbox is observed in a terminal non-running state, without triggering a stop or kill request.

**Returns**

| Type                                      | Description                                     |
| ----------------------------------------- | ----------------------------------------------- |
| [`SandboxStopResult`](#sandboxstopresult) | Terminal status and optional observed exit code |

***

#### \[Symbol.asyncDispose]\()

```typescript theme={null}
[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](/sandboxes/customize#patches) for conceptual context.

***

#### append()

```typescript theme={null}
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**

| Name    | Type     | Description                    |
| ------- | -------- | ------------------------------ |
| path    | `string` | Absolute path inside the guest |
| content | `string` | Text to append                 |

***

#### copyDir()

```typescript theme={null}
copyDir(src: string, dst: string, opts?: { replace?: boolean }): this
```

Recursively copy a host directory at `src` into the guest rootfs at `dst`.

**Parameters**

| Name         | Type      | Description                                      |
| ------------ | --------- | ------------------------------------------------ |
| src          | `string`  | Host source directory                            |
| dst          | `string`  | Absolute destination path inside the guest       |
| opts.replace | `boolean` | When `true`, overwrite an existing path at `dst` |

***

#### copyFile()

```typescript theme={null}
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**

| Name         | Type      | Description                                           |
| ------------ | --------- | ----------------------------------------------------- |
| src          | `string`  | Host source file                                      |
| dst          | `string`  | Absolute destination path inside the guest            |
| opts.mode    | `number`  | File mode, e.g. `0o644`. Omit to keep the source mode |
| opts.replace | `boolean` | When `true`, overwrite an existing path at `dst`      |

***

#### file()

```typescript theme={null}
file(
  path: string,
  content: Buffer,
  opts?: { mode?: number; replace?: boolean },
): this
```

Write raw bytes at `path`.

**Parameters**

| Name         | Type      | Description                             |
| ------------ | --------- | --------------------------------------- |
| path         | `string`  | Absolute path inside the guest          |
| content      | `Buffer`  | Raw byte content                        |
| opts.mode    | `number`  | File mode, e.g. `0o644`                 |
| opts.replace | `boolean` | When `true`, overwrite an existing path |

***

#### mkdir()

```typescript theme={null}
mkdir(path: string, opts?: { mode?: number }): this
```

Create a directory at `path`. Idempotent: a no-op if the directory already exists.

**Parameters**

| Name      | Type     | Description                    |
| --------- | -------- | ------------------------------ |
| path      | `string` | Absolute path inside the guest |
| opts.mode | `number` | Directory mode, e.g. `0o755`   |

***

#### remove()

```typescript theme={null}
remove(path: string): this
```

Delete a file or directory at `path`. Idempotent: a no-op if the path doesn't exist.

**Parameters**

| Name | Type     | Description                    |
| ---- | -------- | ------------------------------ |
| path | `string` | Absolute path inside the guest |

***

#### symlink()

```typescript theme={null}
symlink(target: string, link: string, opts?: { replace?: boolean }): this
```

Create a symlink at `link` pointing to `target`.

**Parameters**

| Name         | Type      | Description                                              |
| ------------ | --------- | -------------------------------------------------------- |
| target       | `string`  | What the symlink points to (literal symlink target text) |
| link         | `string`  | Absolute path of the symlink itself                      |
| opts.replace | `boolean` | When `true`, overwrite an existing path at `link`        |

***

#### text()

```typescript theme={null}
text(
  path: string,
  content: string,
  opts?: { mode?: number; replace?: boolean },
): this
```

Write UTF-8 text content at `path`.

**Parameters**

| Name         | Type      | Description                             |
| ------------ | --------- | --------------------------------------- |
| path         | `string`  | Absolute path inside the guest          |
| content      | `string`  | Text content                            |
| opts.mode    | `number`  | File mode, e.g. `0o644`                 |
| opts.replace | `boolean` | When `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.

| Method                                                   | Description                                                                                                                                                                    |
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `image(src)`                                             | OCI image (`"alpine"`) or local rootfs/disk path. **Required.**                                                                                                                |
| `imageWith(i => i.oci("alpine").upperSize(8192))`        | Configure explicit OCI upper size or disk-image details                                                                                                                        |
| `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(...)`                                                                                                                                      |
| `security(profile)`                                      | In-guest security profile (`"default"` or `"restricted"`)                                                                                                                      |
| `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](/sandboxes/customize#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)                                                                                              |
| `replaceWithTimeout(timeoutMs)`                          | Same as `replace()` with a custom SIGTERM timeout 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](/sdk/typescript/volumes)                                                                                                                        |
| `patch(p => ...)`                                        | Modify the rootfs before boot — see [Snapshots](/sdk/typescript/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](/sdk/typescript/networking)                                                                                          |
| `secret(s => ...)`                                       | Add a secret via [`SecretBuilder`](/sdk/typescript/secrets#secretbuilder)                                                                                                      |
| `secretEnv(envVar, value, allowedHost)`                  | Auto-placeholder shorthand. Generates `$MSB_<env_var>`.                                                                                                                        |
| `detached(enabled)`                                      | Create in detached/background mode when `true`                                                                                                                                 |
| `build(): Promise<SandboxConfig>`                        | Materialize without booting. Consumes the builder                                                                                                                              |
| `create(): Promise<Sandbox>`                             | Build and boot                                                                                                                                                                 |
| `createWithPullProgress(): Promise<PullProgressCreate>`  | Build and boot while streaming image pull progress                                                                                                                             |

### LogLevel

Sandbox process log verbosity.

| Value     | Description                          |
| --------- | ------------------------------------ |
| `'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()`](#logs).

| Property / Method | Type                      | Description                                                              |
| ----------------- | ------------------------- | ------------------------------------------------------------------------ |
| timestamp         | `Date`                    | Wall-clock capture time on the host                                      |
| source            | [`LogSource`](#logsource) | Where the chunk came from                                                |
| sessionId         | `number \| null`          | Relay-monotonic session id; `null` for `"system"` entries                |
| data              | `Uint8Array`              | The chunk's bytes (UTF-8 lossy decoded by default)                       |
| `text()`          | `string`                  | Convenience: UTF-8 decode of `data` (lossy — invalid bytes are replaced) |

### LogReadOptions

Filters passed to [`logs()`](#logs). All fields optional. Omit the argument entirely for the default sources (`stdout` + `stderr` + `output`).

| Field   | Type                           | Description                                                                                                      |
| ------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| tail    | `number?`                      | Show only the last N entries after other filters apply                                                           |
| since   | `Date?`                        | Inclusive lower bound on entry timestamp                                                                         |
| until   | `Date?`                        | Exclusive upper bound on entry timestamp                                                                         |
| sources | [`LogSource`](#logsource)`[]?` | 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:

```typescript theme={null}
type LogSource = "stdout" | "stderr" | "output" | "system";
```

| Value      | Description                                                                                                                                                                                                             |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"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.

| Method                    | Returns                                                  | Description                                                 |
| ------------------------- | -------------------------------------------------------- | ----------------------------------------------------------- |
| `[Symbol.asyncIterator]`  | `AsyncIterator<`[`SandboxMetrics`](#sandboxmetrics)`>`   | Use with `for await...of`                                   |
| `recv()`                  | `Promise<`[`SandboxMetrics`](#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.

| Value          | Description                                                        |
| -------------- | ------------------------------------------------------------------ |
| `'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`](#pullprogresscreate). A discriminated union. Narrow on `kind` to access variant-specific fields:

```typescript theme={null}
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` value                 | Additional 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()`. Yields [`PullProgress`](#pullprogress) events as the image is resolved, downloaded, and materialized. Call `awaitSandbox()` after iteration to obtain the live sandbox.

| Method                  | Returns                                              | Description                                                                                                                       |
| ----------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| \[Symbol.asyncIterator] | `AsyncGenerator<`[`PullProgress`](#pullprogress)`>`  | Use with `for await...of`                                                                                                         |
| progress.recv()         | `Promise<`[`PullProgress`](#pullprogress)` \| null>` | Receive next event. Returns `null` when the stream ends.                                                                          |
| awaitSandbox()          | `Promise<`[`Sandbox`](#instance-methods)`>`          | Resolve the underlying creation task and return the running sandbox. Single-shot: a second call throws an already-consumed error. |

### SandboxConfig

Configuration object produced by `SandboxBuilder.build()` and returned by `sandbox.config()`. You generally should not construct this by hand; use the builder.

| Field                | Type                               | Description                                                                                                |
| -------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| name                 | `string`                           | Sandbox name, up to 128 UTF-8 bytes                                                                        |
| image                | `RootfsSource`                     | OCI / bind / disk discriminated union                                                                      |
| cpus                 | `number \| null`                   | Virtual CPUs                                                                                               |
| memoryMib            | `number \| null`                   | Guest memory in MiB                                                                                        |
| logLevel             | `LogLevel \| null`                 | Log verbosity                                                                                              |
| quietLogs            | `boolean`                          | Suppress log output                                                                                        |
| workdir              | `string \| null`                   | Default working directory                                                                                  |
| shell                | `string \| null`                   | Shell binary                                                                                               |
| securityProfile      | `"default" \| "restricted"`        | In-guest security profile                                                                                  |
| entrypoint           | `string[] \| null`                 | Override image entrypoint                                                                                  |
| cmd                  | `string[] \| null`                 | Override image cmd                                                                                         |
| hostname             | `string \| null`                   | Guest hostname                                                                                             |
| user                 | `string \| null`                   | Default guest user                                                                                         |
| libkrunfwPath        | `string \| null`                   | Custom libkrunfw path                                                                                      |
| env                  | `Array<readonly [string, string]>` | Environment variables                                                                                      |
| scripts              | `Array<readonly [string, string]>` | Named scripts                                                                                              |
| mounts               | `VolumeMount[]`                    | Volume mounts                                                                                              |
| patches              | `Patch[]`                          | Rootfs modifications applied before boot                                                                   |
| pullPolicy           | `PullPolicy \| null`               | Image pull behavior                                                                                        |
| replace              | `boolean`                          | Replace existing sandbox with same name                                                                    |
| replaceWithTimeoutMs | `number`                           | Milliseconds to wait after `SIGTERM` before escalating to `SIGKILL` (default `10000`; `0` skips `SIGTERM`) |
| maxDurationSecs      | `number \| null`                   | Maximum sandbox lifetime                                                                                   |
| idleTimeoutSecs      | `number \| null`                   | Stop after idle time                                                                                       |
| portsTcp             | `Array<readonly [number, number]>` | TCP host→guest mappings                                                                                    |
| portsUdp             | `Array<readonly [number, number]>` | UDP host→guest mappings                                                                                    |
| registry             | `RegistryConfig \| null`           | Registry connection settings                                                                               |
| network              | `NetworkConfig \| null`            | Network configuration                                                                                      |
| disableNetwork       | `boolean`                          | Disable networking entirely                                                                                |
| secrets              | `SecretEntry[]`                    | Secret entries (top-level)                                                                                 |

### SandboxHandle

A lightweight handle to an existing sandbox (running or stopped). Obtained via [`Sandbox.get()`](#sandboxget) or [`Sandbox.list()`](#sandboxlist).

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 / Method             | Type                                                   | Description                                                                                                     |
| ----------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| name                          | `string`                                               | Sandbox name, up to 128 UTF-8 bytes                                                                             |
| status                        | [`SandboxStatus`](#sandboxstatus)                      | Current status                                                                                                  |
| configJson                    | `string`                                               | Raw JSON configuration                                                                                          |
| createdAt                     | `Date \| null`                                         | Creation timestamp                                                                                              |
| updatedAt                     | `Date \| null`                                         | Last update timestamp                                                                                           |
| metrics()                     | `Promise<`[`SandboxMetrics`](#sandboxmetrics)`>`       | Point-in-time resource metrics                                                                                  |
| logs()                        | `Promise<`[`LogEntry`](#logentry)`[]>`                 | Read captured `exec.log` (works without starting)                                                               |
| start()                       | `Promise<`[`Sandbox`](#instance-methods)`>`            | Start in attached mode                                                                                          |
| startDetached()               | `Promise<`[`Sandbox`](#instance-methods)`>`            | Start in detached mode                                                                                          |
| connect()                     | `Promise<`[`Sandbox`](#instance-methods)`>`            | Connect to a running sandbox without taking ownership. Returns an error if it doesn't respond within 10\_000 ms |
| connectWithTimeout(timeoutMs) | `Promise<`[`Sandbox`](#instance-methods)`>`            | Same as `connect()` with an explicit timeout in milliseconds                                                    |
| stop()                        | `Promise<void>`                                        | Gracefully shut down. Waits up to 10\_000 ms for pending writes to flush, then force-kills                      |
| stopWithTimeout(timeoutMs)    | `Promise<void>`                                        | Same as `stop()` with an explicit timeout in milliseconds; `0` force-kills immediately                          |
| requestStop()                 | `Promise<void>`                                        | Request graceful shutdown without waiting                                                                       |
| kill()                        | `Promise<void>`                                        | Force terminate and wait until stopped state is observed                                                        |
| killWithTimeout(timeoutMs)    | `Promise<void>`                                        | Same as `kill()` with an explicit observation timeout                                                           |
| requestKill()                 | `Promise<void>`                                        | Request force termination without waiting                                                                       |
| requestDrain()                | `Promise<void>`                                        | Request graceful drain without waiting                                                                          |
| waitUntilStopped()            | `Promise<`[`SandboxStopResult`](#sandboxstopresult)`>` | Block until the sandbox reaches terminal state                                                                  |
| remove()                      | `Promise<void>`                                        | Delete sandbox and state                                                                                        |

### SandboxStopResult

Observed terminal sandbox state returned by [`waitUntilStopped()`](#waituntilstopped).

| Field    | Type                              | Description                            |
| -------- | --------------------------------- | -------------------------------------- |
| status   | [`SandboxStatus`](#sandboxstatus) | Terminal status that was observed      |
| exitCode | `number \| null`                  | Process exit code when it is available |

### SandboxMetrics

Point-in-time resource usage snapshot.

| Field            | Type     | Description                                      |
| ---------------- | -------- | ------------------------------------------------ |
| cpuPercent       | `number` | CPU usage as a percentage                        |
| diskReadBytes    | `number` | Total bytes read from disk since boot            |
| diskWriteBytes   | `number` | Total bytes written to disk since boot           |
| memoryBytes      | `number` | Current memory usage in bytes                    |
| memoryLimitBytes | `number` | Memory limit in bytes                            |
| netRxBytes       | `number` | Total bytes received over the network since boot |
| netTxBytes       | `number` | Total bytes sent over the network since boot     |
| timestamp        | `Date`   | When this measurement was taken                  |
| uptimeMs         | `number` | Time since the sandbox was created (ms)          |

### SandboxStatus

| Value        | Description                    |
| ------------ | ------------------------------ |
| `'crashed'`  | VM exited unexpectedly         |
| `'draining'` | Graceful shutdown in progress  |
| `'running'`  | Guest agent is ready           |
| `'stopped'`  | VM shut down; can be restarted |
