---
title: Sandbox
description: Rust SDK - Sandbox API reference
---

Create and control a microVM sandbox: boot it from an image, run commands, stream logs and metrics, then shut it down. See [Overview](/sandboxes/overview) for configuration examples and [Lifecycle](/sandboxes/lifecycle) for state management.

<div className="msb-glance">

  <p className="msb-gl"><span className="msb-dot static"></span>Static<span className="msb-ct">6</span></p>
  <a className="msb-row" href="#sandboxbuilder"><span className="msb-rn">Sandbox::builder()</span><span className="msb-rg">configure a new sandbox</span></a>
  <a className="msb-row" href="#sandboxget"><span className="msb-rn">Sandbox::get()</span><span className="msb-rg">handle to an existing one</span></a>
  <a className="msb-row" href="#sandboxlist"><span className="msb-rn">Sandbox::list()</span><span className="msb-rg">all sandboxes</span></a>
  <a className="msb-row" href="#sandboxstart"><span className="msb-rn">Sandbox::start()</span><span className="msb-rg">restart a stopped one</span></a>
  <a className="msb-row" href="#sandboxstart_detached"><span className="msb-rn">Sandbox::start_detached()</span><span className="msb-rg">restart detached</span></a>
  <a className="msb-row" href="#sandboxremove"><span className="msb-rn">Sandbox::remove()</span><span className="msb-rg">delete a stopped one</span></a>

  <p className="msb-gl"><span className="msb-dot instance"></span>Instance<span className="msb-ct">16</span></p>
  <a className="msb-row" href="/sdk/rust/execution"><span className="msb-rn">sb.exec()</span><span className="msb-rg">run a command</span></a>
  <a className="msb-row" href="/sdk/rust/execution"><span className="msb-rn">sb.shell()</span><span className="msb-rg">interactive shell</span></a>
  <a className="msb-row" href="#sb-fs"><span className="msb-rn">sb.fs()</span><span className="msb-rg">read / write files</span></a>
  <a className="msb-row" href="#sb-logs"><span className="msb-rn">sb.logs()</span><span className="msb-rg">captured output</span></a>
  <a className="msb-row" href="#sb-metrics"><span className="msb-rn">sb.metrics()</span><span className="msb-rg">resource snapshot</span></a>
  <a className="msb-row" href="#sb-metrics_stream"><span className="msb-rn">sb.metrics_stream()</span><span className="msb-rg">stream metrics</span></a>
  <a className="msb-row" href="#sb-stop"><span className="msb-rn">sb.stop()</span><span className="msb-rg">graceful shutdown</span></a>
  <a className="msb-row" href="#sb-kill"><span className="msb-rn">sb.kill()</span><span className="msb-rg">force terminate</span></a>
  <a className="msb-row" href="#sb-drain"><span className="msb-rn">sb.drain()</span><span className="msb-rg">graceful drain</span></a>
  <a className="msb-row" href="#sb-detach"><span className="msb-rn">sb.detach()</span><span className="msb-rg">release, keep running</span></a>
  <a className="msb-row" href="#sb-wait"><span className="msb-rn">sb.wait()</span><span className="msb-rg">block until it exits</span></a>
  <a className="msb-row" href="#sb-stop_and_wait"><span className="msb-rn">sb.stop_and_wait()</span><span className="msb-rg">stop, then await exit</span></a>
  <a className="msb-row" href="#sb-config"><span className="msb-rn">sb.config()</span><span className="msb-rg">full configuration</span></a>
  <a className="msb-row" href="#sb-name"><span className="msb-rn">sb.name()</span><span className="msb-rg">sandbox name</span></a>
  <a className="msb-row" href="#sb-owns_lifecycle"><span className="msb-rn">sb.owns_lifecycle()</span><span className="msb-rg">attached vs detached</span></a>
  <a className="msb-row" href="#sb-remove_persisted"><span className="msb-rn">sb.remove_persisted()</span><span className="msb-rg">delete persisted state</span></a>

  <p className="msb-gl"><span className="msb-dot builder"></span>Builder · SandboxBuilder<span className="msb-ct">32</span></p>
  <div className="msb-chiprow">
    <a className="msb-chip" href="#image">.image()</a>
    <a className="msb-chip" href="#memory">.memory()</a>
    <a className="msb-chip" href="#cpus">.cpus()</a>
    <a className="msb-chip" href="#port">.port()</a>
    <a className="msb-chip" href="#volume">.volume()</a>
    <a className="msb-chip" href="#env">.env()</a>
    <a className="msb-chip" href="#secret">.secret()</a>
    <a className="msb-chip" href="#network">.network()</a>
    <a className="msb-chip" href="#init">.init()</a>
    <a className="msb-chip" href="#patch">.patch()</a>
    <a className="msb-chip" href="#create">.create()</a>
    <a className="msb-chip" href="#build">.build()</a>
    <a className="msb-more" href="#build">+ 20 more in the Builder section</a>
  </div>

  <p className="msb-gl"><span className="msb-dot type"></span>Types</p>
  <div className="msb-chiprow">
    <a className="msb-typepill" href="#sandboxconfig">SandboxConfig</a>
    <a className="msb-typepill" href="#sandboxhandle">SandboxHandle</a>
    <a className="msb-typepill" href="#sandboxmetrics">SandboxMetrics</a>
    <a className="msb-typepill" href="#sandboxstatus">SandboxStatus</a>
    <a className="msb-typepill" href="#logentry">LogEntry</a>
    <a className="msb-typepill" href="#logoptions">LogOptions</a>
    <a className="msb-typepill" href="#logsource">LogSource</a>
    <a className="msb-typepill" href="#loglevel">LogLevel</a>
    <a className="msb-typepill" href="#pullpolicy">PullPolicy</a>
    <a className="msb-typepill" href="#registryauth">RegistryAuth</a>
    <a className="msb-typepill" href="/sdk/rust/execution#exitstatus">ExitStatus</a>
    <a className="msb-typepill" href="#patchbuilder">PatchBuilder</a>
  </div>

</div>

<p className="msb-label" id="typical-flow">Typical flow</p>

```rust
use microsandbox::Sandbox;

let sb = Sandbox::builder("api")             // 1. configure
    .image("python")
    .memory(1024)
    .create()                                // 2. boot the microVM
    .await?;

let out = sb.exec("python", ["-V"]).await?;  // 3. run
println!("{}", out.stdout()?);

sb.stop().await?;                            // 4. shut down
```

## Static methods

---

#### <span className="msb-recv">Sandbox::</span><span className="msb-hn">builder()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span></div>

```rust
fn builder(name: impl Into<String>) -> SandboxBuilder
```

Create a builder for configuring a new sandbox. The builder lets you set the image, resources, volumes, networking, secrets, and other options before booting the VM. Sandbox names must be non-empty and no longer than 128 UTF-8 bytes. See [`SandboxBuilder`](#sandboxbuilder) for all available options.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Sandbox name - must be unique and no longer than 128 UTF-8 bytes.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sandboxbuilder">SandboxBuilder</a></div>
    <div className="msb-param-desc">Builder for configuring the sandbox.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let sb = Sandbox::builder("api")
    .image("python")
    .create()
    .await?;
```

</Accordion>

---

#### <span className="msb-recv">Sandbox::</span><span className="msb-hn">get()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn get(name: &str) -> MicrosandboxResult<SandboxHandle>
```

Get a handle to an existing sandbox (running or stopped). The handle provides status, configuration, and lifecycle control without requiring a full connection to the guest agent.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sandboxhandle">SandboxHandle</a></div>
    <div className="msb-param-desc">Handle with status and lifecycle control.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let handle = Sandbox::get("api").await?;
println!("{:?}", handle.status());
```

</Accordion>

---

#### <span className="msb-recv">Sandbox::</span><span className="msb-hn">list()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn list() -> MicrosandboxResult<Vec<SandboxHandle>>
```

List all sandboxes (running, stopped, and crashed).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sandboxhandle">Vec&lt;SandboxHandle&gt;</a></div>
    <div className="msb-param-desc">All sandbox handles.</div>
  </div>
</div>

<Accordion title="Example">

```rust
for h in Sandbox::list().await? {
    println!("{} — {:?}", h.name(), h.status());
}
```

</Accordion>

---

#### <span className="msb-recv">Sandbox::</span><span className="msb-hn">remove()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn remove(name: &str) -> MicrosandboxResult<()>
```

Delete a stopped sandbox and all its state from disk (configuration, logs, runtime directory). Fails if the sandbox is still running - stop it first.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
</div>

<Accordion title="Example">

```rust
Sandbox::remove("api").await?;
```

</Accordion>

---

#### <span className="msb-recv">Sandbox::</span><span className="msb-hn">start()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn start(name: &str) -> MicrosandboxResult<Sandbox>
```

Restart a previously stopped sandbox. The VM reboots using the persisted configuration. The sandbox enters attached mode - it stops when your process exits.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Name of a stopped sandbox, up to 128 UTF-8 bytes.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Sandbox</a></div>
    <div className="msb-param-desc">Running sandbox.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let sb = Sandbox::start("api").await?;
```

</Accordion>

---

#### <span className="msb-recv">Sandbox::</span><span className="msb-hn">start_detached()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn start_detached(name: &str) -> MicrosandboxResult<Sandbox>
```

Restart a stopped sandbox in detached mode. The sandbox survives after your process exits.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Name of a stopped sandbox, up to 128 UTF-8 bytes.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Sandbox</a></div>
    <div className="msb-param-desc">Running sandbox.</div>
  </div>
</div>

---

## Instance methods

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">config()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn config(&self) -> &SandboxConfig
```

Access the sandbox's full configuration.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sandboxconfig">&amp;SandboxConfig</a></div>
    <div className="msb-param-desc">Sandbox configuration.</div>
  </div>
</div>

<Accordion title="Example">

```rust
println!("{} MiB", sb.config().memory_mib);
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">detach()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn detach(self)
```

Release the handle without stopping the sandbox. The sandbox continues running as a background process. Reconnect later with [`Sandbox::get()`](#sandboxget).

<Accordion title="Example">

```rust
sb.detach().await; // keeps running in the background
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">drain()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn drain(&self) -> MicrosandboxResult<()>
```

Start a graceful drain. Existing commands run to completion, but new `exec` calls are rejected. The sandbox transitions to `Stopped` when all in-flight commands finish. Useful for zero-downtime rotation of worker sandboxes.

<Accordion title="Example">

```rust
sb.drain().await?;
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">fs()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn fs(&self) -> SandboxFs<'_>
```

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

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="/sdk/rust/filesystem">SandboxFs</a></div>
    <div className="msb-param-desc">Filesystem handle.</div>
  </div>
</div>

<Accordion title="Example">

```rust
sb.fs().write("/tmp/hello.txt", "hi").await?;
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">kill()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn kill(&self) -> MicrosandboxResult<()>
```

Force-terminate the sandbox immediately with SIGKILL. No graceful shutdown — use when the sandbox is unresponsive. Pending writes that the workload hasn't `fsync`'d may be lost, same durability semantics as a sudden power loss on a physical machine. Prefer [`stop()`](#sb-stop) for graceful shutdown that gives the workload a chance to flush.

<Accordion title="Example">

```rust
sb.kill().await?; // SIGKILL, no graceful shutdown
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">metrics()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn metrics(&self) -> MicrosandboxResult<SandboxMetrics>
```

Get a point-in-time snapshot of the sandbox's resource usage: CPU, memory, disk I/O, network I/O, optional upper disk usage, and uptime.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sandboxmetrics">SandboxMetrics</a></div>
    <div className="msb-param-desc">Resource metrics.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let m = sb.metrics().await?;
println!("cpu {:.1}% · mem {} MiB", m.cpu_percent, m.memory_bytes / 1_048_576);
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">metrics_stream()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn metrics_stream(&self, interval: Duration) -> impl Stream<Item = MicrosandboxResult<SandboxMetrics>>
```

Stream resource metrics at a regular interval. Returns an async stream that yields a new snapshot every `interval` duration.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>interval</code><span className="msb-type">Duration</span></div>
    <div className="msb-param-desc">Time between metric snapshots.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sandboxmetrics">impl Stream&lt;SandboxMetrics&gt;</a></div>
    <div className="msb-param-desc">Async stream yielding a snapshot each interval.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use futures::StreamExt;

let mut stream = sb.metrics_stream(Duration::from_secs(1));
while let Some(snapshot) = stream.next().await {
    println!("{:.1}%", snapshot?.cpu_percent);
}
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">logs()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn logs(&self, opts: &LogOptions) -> MicrosandboxResult<Vec<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 `LogSource::System` to also include synthetic lifecycle markers and runtime/kernel diagnostic lines. `logs()` is **synchronous** because it's a pure file read.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>opts</code><a className="msb-type" href="#logoptions">&amp;LogOptions</a></div>
    <div className="msb-param-desc">Filters: <code>tail</code>, <code>since</code>, <code>until</code>, <code>sources</code>. <code>LogOptions::default()</code> returns everything for the default sources.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#logentry">Vec&lt;LogEntry&gt;</a></div>
    <div className="msb-param-desc">Matching entries in chronological order.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::sandbox::{LogOptions, LogSource, Sandbox};

let handle = Sandbox::get("web").await?;

// Default — all user-program output, regardless of pipe/pty mode
let entries = handle.logs(&LogOptions::default())?;

for e in entries {
    let source = match e.source {
        LogSource::Stdout => "OUT",
        LogSource::Stderr => "ERR",
        LogSource::Output => "PTY",
        LogSource::System => "SYS",
    };
    println!(
        "[{}] {} {:?}: {}",
        e.timestamp.to_rfc3339(),
        source,
        e.session_id,
        String::from_utf8_lossy(&e.data).trim_end()
    );
}

// Filtered: last 50 entries from the past hour, including system lines
let recent = handle.logs(&LogOptions {
    tail: Some(50),
    since: Some(chrono::Utc::now() - chrono::Duration::hours(1)),
    sources: vec![
        LogSource::Stdout,
        LogSource::Stderr,
        LogSource::Output,
        LogSource::System,
    ],
    ..Default::default()
})?;
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">name()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn name(&self) -> &str
```

Get the sandbox name.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
</div>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">owns_lifecycle()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn owns_lifecycle(&self) -> bool
```

Whether this handle owns the sandbox lifecycle. `true` in attached mode (sandbox stops when your process exits), `false` in detached mode.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">bool</span></div>
    <div className="msb-param-desc"><code>true</code> if attached.</div>
  </div>
</div>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">remove_persisted()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn remove_persisted(&self) -> MicrosandboxResult<()>
```

Remove the sandbox and all its persisted state from disk.

<Accordion title="Example">

```rust
sb.remove_persisted().await?;
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">stop()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn stop(&self) -> MicrosandboxResult<()>
```

Gracefully shut down the sandbox. 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 ten seconds for a clean exit; if the sandbox is still running after that, it is force-killed.

<Accordion title="Example">

```rust
sb.stop().await?;
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">stop_and_wait()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn stop_and_wait(&self) -> MicrosandboxResult<ExitStatus>
```

Stop the sandbox and wait for the exit status.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="/sdk/rust/execution#exitstatus">ExitStatus</a></div>
    <div className="msb-param-desc">Exit code and success flag.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let status = sb.stop_and_wait().await?;
println!("exited: {}", status.success());
```

</Accordion>

---

#### <span className="msb-recv">sb.</span><span className="msb-hn">wait()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn wait(&self) -> MicrosandboxResult<ExitStatus>
```

Block until the sandbox exits on its own (without triggering a stop). Returns the exit status.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="/sdk/rust/execution#exitstatus">ExitStatus</a></div>
    <div className="msb-param-desc">Exit code and success flag.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let status = sb.wait().await?;
```

</Accordion>

---

## SandboxBuilder

Builder for configuring a sandbox before creation. Obtained via [`Sandbox::builder(name)`](#sandboxbuilder). Every setter returns `Self`, so calls chain. Examples are shown on the methods where usage is non-obvious; simple setters are demonstrated by the [Typical flow](#typical-flow) above.

---

#### <span className="msb-recv">.</span><span className="msb-hn">build()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span><span className="msb-tag is-async">async</span></div>

```rust
async fn build(self) -> MicrosandboxResult<SandboxConfig>
```

Materialize the [`SandboxConfig`](#sandboxconfig) without booting the sandbox. Validates the configuration and, if `from_snapshot` was called, opens the snapshot manifest to pin its image reference and upper-layer source. For booting, use [`create`](#create) or [`create_detached`](#create_detached) instead — they call `build` internally.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sandboxconfig">SandboxConfig</a></div>
    <div className="msb-param-desc">Validated, ready-to-boot configuration.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">cpus()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn cpus(self, count: u8) -> Self
```

Set the number of virtual CPUs. This is a limit, not a reservation. Default: `1`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>count</code><span className="msb-type">u8</span></div>
    <div className="msb-param-desc">Number of vCPUs.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">create()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span><span className="msb-tag is-async">async</span></div>

```rust
async fn create(self) -> MicrosandboxResult<Sandbox>
```

Boot the sandbox in attached mode. The sandbox stops when your process exits.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Sandbox</a></div>
    <div className="msb-param-desc">Running sandbox.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">create_detached()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span><span className="msb-tag is-async">async</span></div>

```rust
async fn create_detached(self) -> MicrosandboxResult<Sandbox>
```

Boot the sandbox in detached mode. The sandbox survives after your process exits.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Sandbox</a></div>
    <div className="msb-param-desc">Running sandbox.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let sb = Sandbox::builder("worker")
    .image("python")
    .create_detached()
    .await?;
sb.detach().await;
```

</Accordion>

---

#### <span className="msb-recv">.</span><span className="msb-hn">disable_network()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn disable_network(self) -> Self
```

Fully disable networking. No network interface is created.

---

#### <span className="msb-recv">.</span><span className="msb-hn">entrypoint()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn entrypoint(self, cmd: impl IntoIterator<Item = impl Into<String>>) -> Self
```

Override the OCI image's stored ENTRYPOINT. The value is consulted by command-resolution paths that follow OCI semantics — specifically `msb exec` / `msb run` against this sandbox from the terminal. [`Sandbox::exec`](/sdk/rust/execution) and [`Sandbox::shell`](/sdk/rust/execution) do **not** consult it; they pass `cmd` literally to the guest agent. Use this when configuring a sandbox via the SDK for later CLI attachment.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>cmd</code><span className="msb-type">impl IntoIterator</span></div>
    <div className="msb-param-desc">Entrypoint command and arguments.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">env()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn env(self, key: impl Into<String>, value: impl Into<String>) -> Self
```

Set an environment variable visible to all commands. Can be called multiple times. Per-command env vars (via `exec_with`) are merged on top.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>key</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Variable name.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>value</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Variable value.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">hostname()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn hostname(self, hostname: impl Into<String>) -> Self
```

Set the guest hostname.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>hostname</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Hostname.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">idle_timeout()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn idle_timeout(self, secs: u64) -> Self
```

Auto-drain the sandbox after this many seconds of inactivity (no active exec sessions). Enforced on the host side.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>secs</code><span className="msb-type">u64</span></div>
    <div className="msb-param-desc">Idle timeout in seconds.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">init()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn init(self, cmd: impl Into<PathBuf>) -> Self
```

Hand off PID 1 inside the guest to `cmd` after agentd finishes its boot-time setup. The agent forks; the parent execs the init and becomes PID 1, the agent continues as a child process. See [Custom init system](/sandboxes/customize#custom-init-system) for image picks, shutdown semantics, and tradeoffs.

`cmd` is either an absolute path inside the guest rootfs or the literal `"auto"`. Auto first honors a known init at the start of the image ENTRYPOINT, such as `/init` in s6-overlay images, then falls back to probing `/sbin/init`, `/lib/systemd/systemd`, and `/usr/lib/systemd/systemd` inside the guest. When attached `msb run` uses an image-declared init entrypoint, the remaining ENTRYPOINT plus CMD or trailing command is passed to that init instead of direct-executed through agentd. For init binaries that take argv or extra env (rare), use [`init_with`](#init_with).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>cmd</code><span className="msb-type">impl Into&lt;PathBuf&gt;</span></div>
    <div className="msb-param-desc">Absolute path inside the guest, or <code>"auto"</code>.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let sb = Sandbox::builder("worker")
    .image("jrei/systemd-debian:12")
    .init("auto")
    .create()
    .await?;
```

</Accordion>

---

#### <span className="msb-recv">.</span><span className="msb-hn">init_with()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn init_with(
    self,
    cmd: impl Into<PathBuf>,
    f: impl FnOnce(InitOptionsBuilder) -> InitOptionsBuilder,
) -> Self
```

Like [`init`](#init), but with a closure-builder for argv and env vars. Mirrors `exec_with` in shape. The builder exposes `arg`, `args`, `env`, and `envs`. Calling `init` or `init_with` more than once overwrites — different from `env`, which appends. The init is one-shot pre-boot.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>cmd</code><span className="msb-type">impl Into&lt;PathBuf&gt;</span></div>
    <div className="msb-param-desc">Absolute path to the init binary inside the guest.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><span className="msb-type">FnOnce(InitOptionsBuilder)</span></div>
    <div className="msb-param-desc">Closure populating argv and env.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let sb = Sandbox::builder("worker")
    .image("jrei/systemd-debian:12")
    .init_with("/lib/systemd/systemd", |i| i
        .args(["--unit=multi-user.target"])
        .env("container", "microsandbox"))
    .create()
    .await?;
```

</Accordion>

---

#### <span className="msb-recv">.</span><span className="msb-hn">image()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn image(self, image: impl IntoImage) -> Self
```

Set the root filesystem source. Accepts OCI image names, local directory paths, or disk image paths. The format is auto-detected.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>image</code><span className="msb-type">impl IntoImage</span></div>
    <div className="msb-param-desc">OCI image name, local directory path, or disk image path.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">image_with()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn image_with(self, f: impl FnOnce(ImageBuilder) -> ImageBuilder) -> Self
```

Configure an explicit rootfs source. Use this for OCI-only settings such as the writable overlay upper size, or for disk images when the filesystem type can't be auto-detected.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><span className="msb-type">FnOnce(ImageBuilder)</span></div>
    <div className="msb-param-desc">Configure the rootfs source.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::size::SizeExt;

let sb = Sandbox::builder("worker")
    .image_with(|i| i.oci("python:3.12").upper_size(8.gib()))
    .create()
    .await?;
```

</Accordion>

---

#### <span className="msb-recv">.</span><span className="msb-hn">log_level()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn log_level(self, level: LogLevel) -> Self
```

Override the sandbox process's log verbosity.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>level</code><a className="msb-type" href="#loglevel">LogLevel</a></div>
    <div className="msb-param-desc">Log level.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">max_duration()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn max_duration(self, secs: u64) -> Self
```

Set the maximum sandbox lifetime in seconds. When exceeded, the sandbox is drained and stopped. Enforced on the host side - the guest cannot override it.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>secs</code><span className="msb-type">u64</span></div>
    <div className="msb-param-desc">Maximum lifetime in seconds.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">memory()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn memory(self, size: impl Into<Mebibytes>) -> Self
```

Set the guest memory size. Physical pages are only allocated as the guest touches them, so this is a limit, not an upfront reservation. Default: `512` MiB.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>size</code><span className="msb-type">impl Into&lt;Mebibytes&gt;</span></div>
    <div className="msb-param-desc">Memory in MiB.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">network()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn network(self, f: impl FnOnce(NetworkBuilder) -> NetworkBuilder) -> Self
```

Configure networking. See [Networking](/sdk/rust/networking) for the full builder API.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="/sdk/rust/networking#networkbuilder">NetworkBuilder</a></div>
    <div className="msb-param-desc">Configure the network.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">patch()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn patch(self, f: impl FnOnce(PatchBuilder) -> PatchBuilder) -> Self
```

Modify the rootfs before the VM boots. Patches go into the writable layer - the base image is untouched. See [`PatchBuilder`](#patchbuilder) for the operations.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#patchbuilder">FnOnce(PatchBuilder)</a></div>
    <div className="msb-param-desc">Configure rootfs patches.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">port()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn port(self, host_port: u16, guest_port: u16) -> Self
```

Publish a TCP port from the sandbox to the host. The default host bind address is `127.0.0.1`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>host_port</code><span className="msb-type">u16</span></div>
    <div className="msb-param-desc">Port on the host.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>guest_port</code><span className="msb-type">u16</span></div>
    <div className="msb-param-desc">Port inside the sandbox.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">port_bind()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn port_bind(self, host_bind: IpAddr, host_port: u16, guest_port: u16) -> Self
```

Publish a TCP port on a specific host bind address, such as `0.0.0.0`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>host_bind</code><span className="msb-type">IpAddr</span></div>
    <div className="msb-param-desc">Host bind address.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>host_port</code><span className="msb-type">u16</span></div>
    <div className="msb-param-desc">Port on the host.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>guest_port</code><span className="msb-type">u16</span></div>
    <div className="msb-param-desc">Port inside the sandbox.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">port_udp()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn port_udp(self, host_port: u16, guest_port: u16) -> Self
```

Publish a UDP port. The default host bind address is `127.0.0.1`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>host_port</code><span className="msb-type">u16</span></div>
    <div className="msb-param-desc">Port on the host.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>guest_port</code><span className="msb-type">u16</span></div>
    <div className="msb-param-desc">Port inside the sandbox.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">port_udp_bind()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn port_udp_bind(self, host_bind: IpAddr, host_port: u16, guest_port: u16) -> Self
```

Publish a UDP port on a specific host bind address.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>host_bind</code><span className="msb-type">IpAddr</span></div>
    <div className="msb-param-desc">Host bind address.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>host_port</code><span className="msb-type">u16</span></div>
    <div className="msb-param-desc">Port on the host.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>guest_port</code><span className="msb-type">u16</span></div>
    <div className="msb-param-desc">Port inside the sandbox.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">pull_policy()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn pull_policy(self, policy: PullPolicy) -> Self
```

Control when the OCI image is pulled from the registry.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>policy</code><a className="msb-type" href="#pullpolicy">PullPolicy</a></div>
    <div className="msb-param-desc">Pull behavior.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">registry_auth()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn registry_auth(self, auth: RegistryAuth) -> Self
```

Authenticate to a private container registry.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>auth</code><a className="msb-type" href="#registryauth">RegistryAuth</a></div>
    <div className="msb-param-desc">Registry credentials.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">replace()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn replace(self) -> Self
```

If a sandbox with the same name already exists, stop it, remove it, and create a fresh one. Without this, creation fails on name conflict.

---

#### <span className="msb-recv">.</span><span className="msb-hn">script()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn script(self, name: impl Into<String>, content: impl Into<String>) -> Self
```

Add a named script at `/.msb/scripts/` inside the guest. Scripts are added to `PATH` and can be called by name via `exec()` or `shell()`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Script name (becomes the filename).</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>content</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Script content.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">secret()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn secret(self, f: impl FnOnce(SecretBuilder) -> SecretBuilder) -> Self
```

Add a secret with full configuration. See [Secrets](/sdk/rust/secrets) for the builder API. Automatically enables TLS interception.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="/sdk/rust/secrets#secretbuilder">SecretBuilder</a></div>
    <div className="msb-param-desc">Configure the secret.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">secret_env()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn secret_env(self, env_var: impl Into<String>, value: impl Into<String>, allowed_host: impl Into<String>) -> Self
```

Shorthand for adding a header-injected secret. Equivalent to `.secret(|s| s.env(env_var).value(value).allow_host(allowed_host))`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>env_var</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Environment variable name (non-empty, no <code>=</code> or NUL).</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>value</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Secret value.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>allowed_host</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Allowed destination host.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">shell()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn shell(self, shell: impl Into<String>) -> Self
```

Set the shell used by [`Sandbox::shell()`](/sdk/rust/execution). Default: `/bin/sh`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>shell</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Shell path (e.g. <code>"/bin/bash"</code>).</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">user()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn user(self, user: impl Into<String>) -> Self
```

Set the default guest user for all commands.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>user</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">User name or UID.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">volume()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn volume(self, guest_path: impl Into<String>, f: impl FnOnce(MountBuilder) -> MountBuilder) -> Self
```

Add a volume mount. See [Volumes](/sdk/rust/volumes) for mount types.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>guest_path</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Mount point inside the sandbox.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="/sdk/rust/volumes#mountbuilder">MountBuilder</a></div>
    <div className="msb-param-desc">Configure the mount.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">workdir()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn workdir(self, path: impl Into<String>) -> Self
```

Set the default working directory for all commands.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Absolute path inside the guest.</div>
  </div>
</div>

---

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

---

#### <span className="msb-recv">.</span><span className="msb-hn">append()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn append(self, path: impl Into<String>, content: impl Into<String>) -> Self
```

Append `content` to an existing file at `path`. If the file lives in a lower image layer, it's copied up first.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Absolute path inside the guest.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>content</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Text to append.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">copy_dir()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn copy_dir(self, src: impl Into<PathBuf>, dst: impl Into<String>, replace: bool) -> Self
```

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

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>src</code><span className="msb-type">impl Into&lt;PathBuf&gt;</span></div>
    <div className="msb-param-desc">Host source directory.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>dst</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Absolute destination path inside the guest.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>replace</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">When <code>true</code>, overwrite an existing path at <code>dst</code>.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">copy_file()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn copy_file(
    self,
    src: impl Into<PathBuf>,
    dst: impl Into<String>,
    mode: Option<u32>,
    replace: bool,
) -> Self
```

Copy a single host file at `src` into the guest rootfs at `dst`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>src</code><span className="msb-type">impl Into&lt;PathBuf&gt;</span></div>
    <div className="msb-param-desc">Host source file.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>dst</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Absolute destination path inside the guest.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>mode</code><span className="msb-type">Option&lt;u32&gt;</span></div>
    <div className="msb-param-desc">File mode, e.g. <code>Some(0o644)</code>. <code>None</code> keeps the source mode.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>replace</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">When <code>true</code>, overwrite an existing path at <code>dst</code>.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">file()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn file(
    self,
    path: impl Into<String>,
    content: impl Into<Vec<u8>>,
    mode: Option<u32>,
    replace: bool,
) -> Self
```

Write raw bytes at `path`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Absolute path inside the guest.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>content</code><span className="msb-type">impl Into&lt;Vec&lt;u8&gt;&gt;</span></div>
    <div className="msb-param-desc">Raw byte content.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>mode</code><span className="msb-type">Option&lt;u32&gt;</span></div>
    <div className="msb-param-desc">File mode, e.g. <code>Some(0o644)</code>.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>replace</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">When <code>true</code>, overwrite an existing path.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">mkdir()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn mkdir(self, path: impl Into<String>, mode: Option<u32>) -> Self
```

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

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Absolute path inside the guest.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>mode</code><span className="msb-type">Option&lt;u32&gt;</span></div>
    <div className="msb-param-desc">Directory mode, e.g. <code>Some(0o755)</code>.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">remove()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn remove(self, path: impl Into<String>) -> Self
```

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

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Absolute path inside the guest.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">symlink()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn symlink(self, target: impl Into<String>, link: impl Into<String>, replace: bool) -> Self
```

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

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>target</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">What the symlink points to (literal symlink target text).</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>link</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Absolute path of the symlink itself.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>replace</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">When <code>true</code>, overwrite an existing path at <code>link</code>.</div>
  </div>
</div>

---

#### <span className="msb-recv">.</span><span className="msb-hn">text()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn text(
    self,
    path: impl Into<String>,
    content: impl Into<String>,
    mode: Option<u32>,
    replace: bool,
) -> Self
```

Write UTF-8 text content at `path`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Absolute path inside the guest.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>content</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Text content.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>mode</code><span className="msb-type">Option&lt;u32&gt;</span></div>
    <div className="msb-param-desc">File mode, e.g. <code>Some(0o644)</code>.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>replace</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">When <code>true</code>, overwrite an existing path.</div>
  </div>
</div>

---

## Types

### LogEntry

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Returned by <a href="#sb-logs">logs()</a></p>

A single captured log entry returned by [`logs()`](#sb-logs).

| Field | Type | Description |
|-------|------|-------------|
| timestamp | `DateTime<Utc>` | Wall-clock capture time on the host |
| source | [`LogSource`](#logsource) | Where the chunk came from |
| session_id | `Option<u64>` | Relay-monotonic session id; `None` for `System` entries |
| data | `Bytes` | The chunk's bytes (UTF-8 lossy decoded by default; raw bytes if `--raw` mode was used) |

### LogLevel

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div>

<p className="msb-backref">Used by <a href="#log_level">log_level()</a></p>

Sandbox process log verbosity.

| Value | Description |
|-------|-------------|
| `Error` | Errors only |
| `Warn` | Warnings and errors only |
| `Info` | Info and higher |
| `Debug` | Debug and higher |
| `Trace` | Most verbose - all diagnostic output |

### LogOptions

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Used by <a href="#sb-logs">logs()</a></p>

Filters passed to [`logs()`](#sb-logs). All fields optional. `LogOptions::default()` returns everything for the default sources (`Stdout` + `Stderr` + `Output`).

| Field | Type | Description |
|-------|------|-------------|
| tail | `Option<usize>` | Show only the last N entries after other filters apply |
| since | `Option<DateTime<Utc>>` | Inclusive lower bound on entry timestamp |
| until | `Option<DateTime<Utc>>` | Exclusive upper bound on entry timestamp |
| sources | `Vec<`[`LogSource`](#logsource)`>` | Sources to include. Empty = `[Stdout, Stderr, Output]` (the default user-program sources). Add `System` to merge runtime/kernel diagnostics. |

### LogSource

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div>

<p className="msb-backref">Used by <a href="#logentry">LogEntry.source</a> · <a href="#logoptions">LogOptions.sources</a></p>

Tag indicating where a captured log entry came from.

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

### PullPolicy

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div>

<p className="msb-backref">Used by <a href="#pull_policy">pull_policy()</a></p>

Controls when the SDK fetches an OCI image from the registry.

| Value | Description |
|-------|-------------|
| `Always` | Pull the image every time, even if cached locally |
| `IfMissing` | Pull only if the image is not already cached. This is the default. |
| `Never` | Never pull; fail if the image is not cached locally |

### RegistryAuth

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div>

<p className="msb-backref">Used by <a href="#registry_auth">registry_auth()</a></p>

Credentials for authenticating to a private container registry.

| Variant | Fields | Description |
|---------|--------|-------------|
| `Basic` | - `username: String` <br/> - `password: String` | Username and password authentication |

### SandboxConfig

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Returned by <a href="#sb-config">config()</a> · <a href="#build">build()</a></p>

The full configuration of a sandbox. Obtained via [`config()`](#sb-config) or built via [`SandboxBuilder`](#sandboxbuilder). Contains all settings used to create the sandbox.

| Field | Type | Description |
|-------|------|-------------|
| cpus | `u8` | Number of virtual CPUs |
| env | `Vec<(String, String)>` | Environment variables |
| idle_timeout_secs | `Option<u64>` | Idle timeout |
| image | `RootfsSource` | Root filesystem source (OCI, bind, or disk image) |
| max_duration_secs | `Option<u64>` | Maximum lifetime |
| memory_mib | `u32` | Guest memory in MiB |
| name | `String` | Sandbox name, up to 128 UTF-8 bytes |
| patches | `Vec<Patch>` | Rootfs patches |
| scripts | `Vec<(String, String)>` | Named scripts |
| shell | `Option<String>` | Shell for `shell()` calls |
| volumes | `Vec<VolumeMount>` | Volume mounts |
| workdir | `Option<String>` | Default working directory |

### SandboxHandle

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Returned by <a href="#sandboxget">Sandbox::get()</a> · <a href="#sandboxlist">Sandbox::list()</a></p>

A lightweight handle to an existing sandbox (running or stopped). Obtained via [`Sandbox::get()`](#sandboxget) or [`Sandbox::list()`](#sandboxlist). Provides status, configuration, and lifecycle control **without** an active connection to the guest agent. You cannot `exec` or `fs` on a handle - call `.start()` or `.connect()` to upgrade to a full [`Sandbox`](#instance-methods).

| Property / Method | Type | Description |
|-------------------|------|-------------|
| config() | `Result<`[`SandboxConfig`](#sandboxconfig)`>` | Parsed configuration |
| config_json() | `&str` | Raw JSON configuration |
| connect() | `Result<`[`Sandbox`](#instance-methods)`>` | Connect to a running sandbox; returns an error if it doesn't respond within ten seconds |
| connect_with_timeout(timeout) | `Result<`[`Sandbox`](#instance-methods)`>` | Same as `connect()` with an explicit timeout |
| created_at() | `Option<DateTime<Utc>>` | Creation timestamp |
| kill() | `Result<()>` | Force terminate immediately. Pending writes may be lost |
| logs() | `Result<Vec<`[`LogEntry`](#logentry)`>>` | Read captured `exec.log` (works without starting) |
| metrics() | `Result<`[`SandboxMetrics`](#sandboxmetrics)`>` | Point-in-time resource metrics |
| name() | `&str` | Sandbox name, up to 128 UTF-8 bytes |
| remove() | `Result<()>` | Delete sandbox and state |
| start() | `Result<`[`Sandbox`](#instance-methods)`>` | Start in attached mode |
| start_detached() | `Result<`[`Sandbox`](#instance-methods)`>` | Start in detached mode |
| status() | [`SandboxStatus`](#sandboxstatus) | Current status |
| stop() | `Result<()>` | Gracefully shut down. Waits up to ten seconds for pending writes to flush, then force-kills |
| stop_with_timeout(timeout) | `Result<()>` | Same as `stop()` with an explicit timeout; `Duration::ZERO` force-kills immediately |
| updated_at() | `Option<DateTime<Utc>>` | Last update timestamp |

### SandboxMetrics

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Returned by <a href="#sb-metrics">metrics()</a> · <a href="#sb-metrics_stream">metrics_stream()</a></p>

Point-in-time resource usage snapshot.

| Field | Type | Description |
|-------|------|-------------|
| cpu_percent | `f32` | CPU usage as a percentage |
| disk_read_bytes | `u64` | Total bytes read from disk since boot |
| disk_write_bytes | `u64` | Total bytes written to disk since boot |
| memory_bytes | `u64` | Current memory usage in bytes |
| memory_limit_bytes | `u64` | Memory limit in bytes |
| net_rx_bytes | `u64` | Total bytes received over the network since boot |
| net_tx_bytes | `u64` | Total bytes sent over the network since boot |
| upper_used_bytes | `Option<u64>` | Guest-visible OCI upper filesystem used bytes when the protected reporter is available and fresh |
| upper_free_bytes | `Option<u64>` | Guest-visible OCI upper filesystem free bytes when the protected reporter is available and fresh |
| upper_host_allocated_bytes | `Option<u64>` | Host-allocated bytes for the writable OCI upper image when available |
| timestamp | `DateTime<Utc>` | When this measurement was taken |
| uptime | `Duration` | Time since the sandbox was created |

### SandboxStatus

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div>

<p className="msb-backref">Used by <a href="#sandboxhandle">SandboxHandle.status()</a></p>

| Value | Description |
|-------|-------------|
| `Crashed` | VM exited unexpectedly (kernel panic, OOM, etc.) |
| `Draining` | Graceful shutdown in progress; existing commands finish, new ones rejected |
| `Running` | Guest agent is ready; `exec`, `shell`, `fs` work |
| `Stopped` | VM shut down; configuration persisted; can be restarted |
