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

# Execution

> Rust SDK - Command execution API reference

Run commands inside a running sandbox: buffer the output in one call, stream it event by event, drive a shell, or bridge your terminal to an interactive PTY session. See [Commands](/sandboxes/commands) for usage examples.

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

```rust theme={null}
use microsandbox::Sandbox;

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

// Buffered: run and collect everything
let out = sb.exec("python", ["-c", "print('hi')"]).await?;
println!("{}", out.stdout()?);

// Streaming: process output as it arrives
let mut handle = sb.exec_stream("tail", ["-f", "/var/log/app.log"]).await?;
while let Some(event) = handle.recv().await {
    if let microsandbox::ExecEvent::Stdout(chunk) = event {
        print!("{}", String::from_utf8_lossy(&chunk));
    }
}

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

## Run methods

#### <span className="msb-recv">sb.</span><span className="msb-hn">exec()</span>

```rust theme={null}
async fn exec(
    &self,
    cmd: impl Into<String>,
    args: impl IntoIterator<Item = impl Into<String>>,
) -> MicrosandboxResult<ExecOutput>
```

<Accordion title="Example">
  ```rust theme={null}
  let out = sb.exec("python", ["-V"]).await?;
  println!("{}", out.stdout()?);
  ```
</Accordion>

Run a command inside the sandbox and wait for it to complete. Collects all stdout and stderr into memory and returns them along with the exit status. `cmd` is passed literally to the guest agent: the image ENTRYPOINT is **not** consulted, and `args` are not shell-interpreted. For long-running processes or large output, use [`exec_stream()`](#sb-exec_stream); for shell syntax like pipes and redirects, use [`shell()`](#sb-shell).

<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\<String></span></div>
    <div className="msb-param-desc">Command to execute, e.g. <code>"python"</code> or <code>"/usr/bin/node"</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div>
    <div className="msb-param-desc">Command arguments, e.g. <code>\["-c", "print('hi')"]</code>.</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="#execoutput">ExecOutput</a></div>
    <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div>
  </div>
</div>

#### <span className="msb-recv">sb.</span><span className="msb-hn">exec\_with()</span>

```rust theme={null}
async fn exec_with(
    &self,
    cmd: impl Into<String>,
    f: impl FnOnce(ExecOptionsBuilder) -> ExecOptionsBuilder,
) -> MicrosandboxResult<ExecOutput>
```

<Accordion title="Example">
  ```rust theme={null}
  use std::time::Duration;

  let out = sb.exec_with("python", |e| e
      .args(["compute.py"])
      .cwd("/app")
      .env("LOG_LEVEL", "debug")
      .timeout(Duration::from_secs(30)))
      .await?;
  ```
</Accordion>

Run a command with per-execution overrides and wait for completion. The closure receives an [`ExecOptionsBuilder`](#execoptionsbuilder) to set args, working directory, environment variables, user, timeout, resource limits, stdin mode, and TTY allocation. These overrides apply only to this execution and don't change the sandbox's defaults.

<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\<String></span></div>
    <div className="msb-param-desc">Command to execute.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#execoptionsbuilder">FnOnce(ExecOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure execution options.</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="#execoutput">ExecOutput</a></div>
    <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div>
  </div>
</div>

#### <span className="msb-recv">sb.</span><span className="msb-hn">shell()</span>

```rust theme={null}
async fn shell(&self, script: impl Into<String>) -> MicrosandboxResult<ExecOutput>
```

<Accordion title="Example">
  ```rust theme={null}
  let out = sb.shell("cat /etc/os-release | grep PRETTY_NAME").await?;
  println!("{}", out.stdout()?);
  ```
</Accordion>

Run a command through the sandbox's configured shell (default: `/bin/sh`, set via [`SandboxBuilder::shell()`](/sdk/rust/sandbox#shell)). The script is run as `<shell> -c "<script>"`, so shell syntax like pipes, redirects, and `&&` chains works.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>script</code><span className="msb-type">impl Into\<String></span></div>
    <div className="msb-param-desc">Shell command string, e.g. <code>"ls -la /app && echo done"</code>.</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="#execoutput">ExecOutput</a></div>
    <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div>
  </div>
</div>

#### <span className="msb-recv">sb.</span><span className="msb-hn">shell\_with()</span>

```rust theme={null}
async fn shell_with(
    &self,
    script: impl Into<String>,
    f: impl FnOnce(ExecOptionsBuilder) -> ExecOptionsBuilder,
) -> MicrosandboxResult<ExecOutput>
```

<Accordion title="Example">
  ```rust theme={null}
  let out = sb.shell_with("env | sort", |e| e.env("STAGE", "build")).await?;
  ```
</Accordion>

Run a shell command with per-execution overrides and wait for completion. The `-c <script>` arguments are prepended to whatever the [`ExecOptionsBuilder`](#execoptionsbuilder) configures, so use the builder for env, cwd, user, timeout, and resource limits rather than for positional args.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>script</code><span className="msb-type">impl Into\<String></span></div>
    <div className="msb-param-desc">Shell command string.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#execoptionsbuilder">FnOnce(ExecOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure execution options.</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="#execoutput">ExecOutput</a></div>
    <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div>
  </div>
</div>

#### <span className="msb-recv">sb.</span><span className="msb-hn">exec\_stream()</span>

```rust theme={null}
async fn exec_stream(
    &self,
    cmd: impl Into<String>,
    args: impl IntoIterator<Item = impl Into<String>>,
) -> MicrosandboxResult<ExecHandle>
```

<Accordion title="Example">
  ```rust theme={null}
  use microsandbox::ExecEvent;

  let mut handle = sb.exec_stream("tail", ["-f", "/var/log/app.log"]).await?;
  while let Some(event) = handle.recv().await {
      match event {
          ExecEvent::Stdout(chunk) => print!("{}", String::from_utf8_lossy(&chunk)),
          ExecEvent::Exited { code } => { println!("exited {code}"); break; }
          _ => {}
      }
  }
  ```
</Accordion>

Run a command with streaming output. Returns an [`ExecHandle`](#exechandle) that emits stdout, stderr, started, and exit events as they happen, rather than buffering everything until the command finishes. Use this for long-running processes, large output, or when you need to process output incrementally.

<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\<String></span></div>
    <div className="msb-param-desc">Command to execute.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div>
    <div className="msb-param-desc">Command arguments.</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="#exechandle">ExecHandle</a></div>
    <div className="msb-param-desc">Streaming handle for receiving events and controlling the process.</div>
  </div>
</div>

#### <span className="msb-recv">sb.</span><span className="msb-hn">exec\_stream\_with()</span>

```rust theme={null}
async fn exec_stream_with(
    &self,
    cmd: impl Into<String>,
    f: impl FnOnce(ExecOptionsBuilder) -> ExecOptionsBuilder,
) -> MicrosandboxResult<ExecHandle>
```

<Accordion title="Example">
  ```rust theme={null}
  let mut handle = sb.exec_stream_with("python", |e| e.stdin_pipe().tty(true)).await?;
  if let Some(stdin) = handle.take_stdin() {
      stdin.write(b"print(2 + 2)\n").await?;
      stdin.close().await?;
  }
  ```
</Accordion>

Streaming execution with per-execution overrides. Enable [`stdin_pipe()`](#stdin_pipe) to write to the process's stdin via [`ExecHandle::take_stdin()`](#exechandle), and [`tty(true)`](#tty) to allocate a pseudo-terminal for interactive programs like shells, REPLs, or editors.

<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\<String></span></div>
    <div className="msb-param-desc">Command to execute.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#execoptionsbuilder">FnOnce(ExecOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure execution options.</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="#exechandle">ExecHandle</a></div>
    <div className="msb-param-desc">Streaming handle.</div>
  </div>
</div>

#### <span className="msb-recv">sb.</span><span className="msb-hn">shell\_stream()</span>

```rust theme={null}
async fn shell_stream(&self, script: impl Into<String>) -> MicrosandboxResult<ExecHandle>
```

<Accordion title="Example">
  ```rust theme={null}
  let mut handle = sb.shell_stream("for i in 1 2 3; do echo $i; sleep 1; done").await?;
  let out = handle.collect().await?;
  ```
</Accordion>

Like [`shell()`](#sb-shell), but returns a streaming [`ExecHandle`](#exechandle) instead of waiting for completion.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>script</code><span className="msb-type">impl Into\<String></span></div>
    <div className="msb-param-desc">Shell command string.</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="#exechandle">ExecHandle</a></div>
    <div className="msb-param-desc">Streaming handle.</div>
  </div>
</div>

#### <span className="msb-recv">sb.</span><span className="msb-hn">shell\_stream\_with()</span>

```rust theme={null}
async fn shell_stream_with(
    &self,
    script: impl Into<String>,
    f: impl FnOnce(ExecOptionsBuilder) -> ExecOptionsBuilder,
) -> MicrosandboxResult<ExecHandle>
```

<Accordion title="Example">
  ```rust theme={null}
  let mut handle = sb.shell_stream_with("npm run build", |e| e.cwd("/app")).await?;
  ```
</Accordion>

Run a shell command with per-execution overrides and streaming I/O. As with [`shell_with()`](#sb-shell_with), the `-c <script>` arguments are prepended to whatever the builder configures.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>script</code><span className="msb-type">impl Into\<String></span></div>
    <div className="msb-param-desc">Shell command string.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#execoptionsbuilder">FnOnce(ExecOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure execution options.</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="#exechandle">ExecHandle</a></div>
    <div className="msb-param-desc">Streaming handle.</div>
  </div>
</div>

## Attach methods

#### <span className="msb-recv">sb.</span><span className="msb-hn">attach()</span>

```rust theme={null}
async fn attach(
    &self,
    cmd: impl Into<String>,
    args: impl IntoIterator<Item = impl Into<String>>,
) -> MicrosandboxResult<i32>
```

<Accordion title="Example">
  ```rust theme={null}
  let exit_code = sb.attach("bash", ["-l"]).await?;
  ```
</Accordion>

Bridge your terminal directly to a process inside the sandbox for a fully interactive PTY session. The host terminal is put into raw mode and its stdin, stdout, and window-size changes are wired to the guest process. Press the detach key (default `Ctrl+]`) to disconnect without stopping the process; it keeps running in the guest. Returns when the process exits or you detach.

<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\<String></span></div>
    <div className="msb-param-desc">Command to run.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div>
    <div className="msb-param-desc">Command arguments.</div>
  </div>
</div>

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">i32</span></div>
    <div className="msb-param-desc">Exit code of the process, or <code>-1</code> if you detached before it exited.</div>
  </div>
</div>

#### <span className="msb-recv">sb.</span><span className="msb-hn">attach\_with()</span>

```rust theme={null}
async fn attach_with(
    &self,
    cmd: impl Into<String>,
    f: impl FnOnce(AttachOptionsBuilder) -> AttachOptionsBuilder,
) -> MicrosandboxResult<i32>
```

<Accordion title="Example">
  ```rust theme={null}
  let exit_code = sb.attach_with("zsh", |a| a
      .env("TERM", "xterm-256color")
      .detach_keys("ctrl-p,ctrl-q"))
      .await?;
  ```
</Accordion>

Interactive PTY attach with options. The closure receives an [`AttachOptionsBuilder`](#attachoptionsbuilder) to set args, environment variables, working directory, user, custom detach keys, and resource limits.

<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\<String></span></div>
    <div className="msb-param-desc">Command to run.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#attachoptionsbuilder">FnOnce(AttachOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure attach options.</div>
  </div>
</div>

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">i32</span></div>
    <div className="msb-param-desc">Exit code of the process, or <code>-1</code> if you detached.</div>
  </div>
</div>

#### <span className="msb-recv">sb.</span><span className="msb-hn">attach\_shell()</span>

```rust theme={null}
async fn attach_shell(&self) -> MicrosandboxResult<i32>
```

<Accordion title="Example">
  ```rust theme={null}
  let exit_code = sb.attach_shell().await?;
  ```
</Accordion>

Attach to the sandbox's default shell (configured via [`SandboxBuilder::shell()`](/sdk/rust/sandbox#shell), default `/bin/sh`) with an interactive PTY session.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">i32</span></div>
    <div className="msb-param-desc">Exit code, or <code>-1</code> if you detached.</div>
  </div>
</div>

## ExecOptionsBuilder

Builder for per-execution overrides passed to [`exec_with()`](#sb-exec_with), [`exec_stream_with()`](#sb-exec_stream_with), [`shell_with()`](#sb-shell_with), and [`shell_stream_with()`](#sb-shell_stream_with). Does not change the sandbox's defaults. Every setter returns `Self`, so calls chain.

#### <span className="msb-recv">.</span><span className="msb-hn">arg()</span>

```rust theme={null}
fn arg(self, arg: impl Into<String>) -> Self
```

Append a single command-line argument, e.g. `"-la"` or `"/tmp"`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>arg</code><span className="msb-type">impl Into\<String></span></div>
    <div className="msb-param-desc">Argument to append.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">args()</span>

```rust theme={null}
fn args(self, args: impl IntoIterator<Item = impl Into<String>>) -> Self
```

Append multiple command-line arguments.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div>
    <div className="msb-param-desc">Arguments to append.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">cwd()</span>

```rust theme={null}
fn cwd(self, cwd: impl Into<String>) -> Self
```

Override the working directory for this command. Overrides the sandbox default set via the builder's `workdir`.

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

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

#### <span className="msb-recv">.</span><span className="msb-hn">user()</span>

```rust theme={null}
fn user(self, user: impl Into<String>) -> Self
```

Override the guest user for this command.

<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\<String></span></div>
    <div className="msb-param-desc">User name or UID.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">env()</span>

```rust theme={null}
fn env(self, key: impl Into<String>, value: impl Into<String>) -> Self
```

Set an environment variable for this command. Merged on top of the sandbox-level env vars.

<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\<String></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\<String></span></div>
    <div className="msb-param-desc">Variable value.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">envs()</span>

```rust theme={null}
fn envs(
    self,
    vars: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self
```

Set multiple environment variables for this command at once.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>vars</code><span className="msb-type">impl IntoIterator</span></div>
    <div className="msb-param-desc">Key-value pairs to set.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">timeout()</span>

```rust theme={null}
fn timeout(self, timeout: Duration) -> Self
```

Kill the process with SIGKILL if it hasn't exited within this duration.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>timeout</code><span className="msb-type">Duration</span></div>
    <div className="msb-param-desc">Maximum run time before SIGKILL.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">tty()</span>

```rust theme={null}
fn tty(self, enabled: bool) -> Self
```

Allocate a pseudo-terminal. Enable for interactive programs (shells, editors, `top`); disable for scripts and batch jobs. When enabled, stdout and stderr are merged at the kernel level inside the guest. Default: `false`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>enabled</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc"><code>true</code> to allocate a PTY.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">stdin\_null()</span>

```rust theme={null}
fn stdin_null(self) -> Self
```

Stdin reads from `/dev/null`. This is the default.

#### <span className="msb-recv">.</span><span className="msb-hn">stdin\_pipe()</span>

```rust theme={null}
fn stdin_pipe(self) -> Self
```

Enable a stdin writer via [`ExecSink`](#execsink). Use with [`ExecHandle::take_stdin()`](#exechandle) on the returned streaming handle to send data to the process.

#### <span className="msb-recv">.</span><span className="msb-hn">stdin\_bytes()</span>

```rust theme={null}
fn stdin_bytes(self, data: impl Into<Vec<u8>>) -> Self
```

Provide fixed bytes as stdin. The process reads them and then sees EOF.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>data</code><span className="msb-type">impl Into\<Vec\<u8>></span></div>
    <div className="msb-param-desc">Bytes fed to the process's stdin.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">rlimit()</span>

```rust theme={null}
fn rlimit(self, resource: RlimitResource, limit: u64) -> Self
```

<Accordion title="Example">
  ```rust theme={null}
  use microsandbox::sandbox::RlimitResource;

  let out = sb.exec_with("./worker", |e| e.rlimit(RlimitResource::Nofile, 1024)).await?;
  ```
</Accordion>

Set a POSIX resource limit with soft equal to hard. Applied via `setrlimit()` before exec.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>resource</code><a className="msb-type" href="#rlimitresource">RlimitResource</a></div>
    <div className="msb-param-desc">Which resource to limit.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>limit</code><span className="msb-type">u64</span></div>
    <div className="msb-param-desc">Limit value (soft = hard).</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">rlimit\_range()</span>

```rust theme={null}
fn rlimit_range(self, resource: RlimitResource, soft: u64, hard: u64) -> Self
```

Set a resource limit with different soft and hard values. [`build()`](#build) errors if `soft > hard`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>resource</code><a className="msb-type" href="#rlimitresource">RlimitResource</a></div>
    <div className="msb-param-desc">Which resource to limit.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>soft</code><span className="msb-type">u64</span></div>
    <div className="msb-param-desc">Soft limit (raisable by the process up to hard).</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>hard</code><span className="msb-type">u64</span></div>
    <div className="msb-param-desc">Hard ceiling.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">build()</span>

```rust theme={null}
fn build(self) -> MicrosandboxResult<ExecOptions>
```

Finalize the options. Called automatically by the `*_with` methods when you use the closure form. Returns an error if any rlimit has `soft > hard`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">ExecOptions</span></div>
    <div className="msb-param-desc">Validated execution options.</div>
  </div>
</div>

## AttachOptionsBuilder

Builder for interactive attach options passed to [`attach_with()`](#sb-attach_with). Every setter returns `Self`, so calls chain.

#### <span className="msb-recv">.</span><span className="msb-hn">arg()</span>

```rust theme={null}
fn arg(self, arg: impl Into<String>) -> Self
```

Append a single command-line argument to the attached command.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>arg</code><span className="msb-type">impl Into\<String></span></div>
    <div className="msb-param-desc">Argument to append.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">args()</span>

```rust theme={null}
fn args(self, args: impl IntoIterator<Item = impl Into<String>>) -> Self
```

Append multiple command-line arguments.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div>
    <div className="msb-param-desc">Arguments to append.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">cwd()</span>

```rust theme={null}
fn cwd(self, cwd: impl Into<String>) -> Self
```

Override the working directory for the attached session.

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

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

#### <span className="msb-recv">.</span><span className="msb-hn">user()</span>

```rust theme={null}
fn user(self, user: impl Into<String>) -> Self
```

Override the guest user for the attached session.

<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\<String></span></div>
    <div className="msb-param-desc">User name or UID.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">env()</span>

```rust theme={null}
fn env(self, key: impl Into<String>, value: impl Into<String>) -> Self
```

Set an environment variable for the attached session. Merged on top of the sandbox-level env vars.

<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\<String></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\<String></span></div>
    <div className="msb-param-desc">Variable value.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">envs()</span>

```rust theme={null}
fn envs(
    self,
    vars: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self
```

Set multiple environment variables for the attached session at once.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>vars</code><span className="msb-type">impl IntoIterator</span></div>
    <div className="msb-param-desc">Key-value pairs to set.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">detach\_keys()</span>

```rust theme={null}
fn detach_keys(self, keys: impl Into<String>) -> Self
```

Set the key sequence that detaches from the session without stopping the process. Docker-style syntax: `"ctrl-]"` (default), `"ctrl-p,ctrl-q"` for a multi-key sequence, or a single character like `"q"`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>keys</code><span className="msb-type">impl Into\<String></span></div>
    <div className="msb-param-desc">Detach key specification.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">rlimit()</span>

```rust theme={null}
fn rlimit(self, resource: RlimitResource, limit: u64) -> Self
```

Set a POSIX resource limit with soft equal to hard for the attached process.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>resource</code><a className="msb-type" href="#rlimitresource">RlimitResource</a></div>
    <div className="msb-param-desc">Which resource to limit.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>limit</code><span className="msb-type">u64</span></div>
    <div className="msb-param-desc">Limit value (soft = hard).</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">rlimit\_range()</span>

```rust theme={null}
fn rlimit_range(self, resource: RlimitResource, soft: u64, hard: u64) -> Self
```

Set a resource limit with different soft and hard values for the attached process. [`build()`](#build-2) errors if `soft > hard`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>resource</code><a className="msb-type" href="#rlimitresource">RlimitResource</a></div>
    <div className="msb-param-desc">Which resource to limit.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>soft</code><span className="msb-type">u64</span></div>
    <div className="msb-param-desc">Soft limit.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>hard</code><span className="msb-type">u64</span></div>
    <div className="msb-param-desc">Hard ceiling.</div>
  </div>
</div>

#### <span className="msb-recv">.</span><span className="msb-hn">build()</span>

```rust theme={null}
fn build(self) -> MicrosandboxResult<AttachOptions>
```

Finalize the options. Called automatically by [`attach_with()`](#sb-attach_with). Returns an error if any rlimit has `soft > hard`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">AttachOptions</span></div>
    <div className="msb-param-desc">Validated attach options.</div>
  </div>
</div>

## Types

### ExecHandle

<p className="msb-backref">Returned by <a href="#sb-exec_stream">exec\_stream()</a> · <a href="#sb-exec_stream_with">exec\_stream\_with()</a> · <a href="#sb-shell_stream">shell\_stream()</a> · <a href="#sb-shell_stream_with">shell\_stream\_with()</a></p>

A handle to a running streaming execution. Receives [`ExecEvent`](#execevent)s as the process produces output, and provides control over stdin, signals, and the PTY size.

| Method             | Returns                                 | Description                                                                                           |
| ------------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| recv()             | `Option<`[`ExecEvent`](#execevent)`>`   | Receive the next event. `None` when the session has ended and all output has been delivered.          |
| wait()             | `Result<`[`ExitStatus`](#exitstatus)`>` | Wait for the process to exit, discarding any remaining output.                                        |
| collect()          | `Result<`[`ExecOutput`](#execoutput)`>` | Wait for exit and collect all remaining stdout/stderr.                                                |
| id()               | `String`                                | Session ID for this execution. Can be used to reattach later.                                         |
| control()          | [`ExecControl`](#execcontrol)           | A cloneable control handle for sending signals and resizes from another task.                         |
| take\_stdin()      | `Option<`[`ExecSink`](#execsink)`>`     | Take the stdin writer. Only available if `stdin_pipe()` was set; returns `None` after the first call. |
| signal(signal)     | `Result<()>`                            | Send a POSIX signal to the process (e.g. `libc::SIGTERM`).                                            |
| kill()             | `Result<()>`                            | Send SIGKILL to the process.                                                                          |
| resize(rows, cols) | `Result<()>`                            | Resize the PTY for this session.                                                                      |

### ExecControl

<p className="msb-backref">Returned by <a href="#exechandle">ExecHandle.control()</a></p>

A cloneable, lightweight control handle for a streaming exec session. Lets a task other than the one owning the [`ExecHandle`](#exechandle) send signals and PTY resizes. Carries no event stream.

| Method             | Returns      | Description                                                |
| ------------------ | ------------ | ---------------------------------------------------------- |
| id()               | `String`     | Session ID for this execution.                             |
| signal(signal)     | `Result<()>` | Send a POSIX signal to the process (e.g. `libc::SIGTERM`). |
| kill()             | `Result<()>` | Send SIGKILL to the process.                               |
| resize(rows, cols) | `Result<()>` | Resize the PTY for this session.                           |

### ExecSink

<p className="msb-backref">Returned by <a href="#exechandle">ExecHandle.take\_stdin()</a></p>

A writer for sending data to a running process's stdin. Obtained via [`ExecHandle::take_stdin()`](#exechandle) after enabling [`stdin_pipe()`](#stdin_pipe).

| Method      | Parameters               | Description                                     |
| ----------- | ------------------------ | ----------------------------------------------- |
| write(data) | `data: impl AsRef<[u8]>` | Write bytes to the process's stdin.             |
| close()     | -                        | Close stdin. The process sees EOF on its stdin. |

### ExecEvent

<p className="msb-backref">Yielded by <a href="#exechandle">ExecHandle.recv()</a></p>

An event emitted by a streaming execution.

| Variant      | Fields           | Description                                                                                                                                    |
| ------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `Started`    | `pid: u32`       | The process has started. `pid` is the guest-side PID.                                                                                          |
| `Stdout`     | `Bytes`          | A chunk of stdout data. May arrive in arbitrary sizes.                                                                                         |
| `Stderr`     | `Bytes`          | A chunk of stderr data.                                                                                                                        |
| `Exited`     | `code: i32`      | The process exited normally. `code` is the exit code.                                                                                          |
| `Failed`     | `ExecFailed`     | The process failed to spawn (binary not found, permission denied, etc.). The user code never ran. Terminal: no further events follow.          |
| `StdinError` | `ExecStdinError` | A stdin write to the child failed (e.g. broken pipe). Non-terminal: the session keeps running and may still emit output and an `Exited` event. |

### ExecOutput

<p className="msb-backref">Returned by <a href="#sb-exec">exec()</a> · <a href="#sb-exec_with">exec\_with()</a> · <a href="#sb-shell">shell()</a> · <a href="#sb-shell_with">shell\_with()</a> · <a href="#exechandle">ExecHandle.collect()</a></p>

The result of a completed command execution. Holds the exit status and all captured output.

| Method          | Returns                         | Description                                                                 |
| --------------- | ------------------------------- | --------------------------------------------------------------------------- |
| status()        | [`ExitStatus`](#exitstatus)     | Exit code and success flag.                                                 |
| stdout()        | `Result<String, FromUtf8Error>` | Collected stdout decoded as UTF-8. Errors if the output is not valid UTF-8. |
| stderr()        | `Result<String, FromUtf8Error>` | Collected stderr decoded as UTF-8.                                          |
| stdout\_bytes() | `&Bytes`                        | Raw stdout bytes without decoding.                                          |
| stderr\_bytes() | `&Bytes`                        | Raw stderr bytes without decoding.                                          |

### ExitStatus

<p className="msb-backref">Returned by <a href="#exechandle">ExecHandle.wait()</a> · <a href="#execoutput">ExecOutput.status()</a> · <a href="/sdk/rust/sandbox#sb-wait">sb.wait()</a> · <a href="/sdk/rust/sandbox#sb-stop_and_wait">sb.stop\_and\_wait()</a></p>

The exit status of a completed process.

| Field   | Type   | Description                             |
| ------- | ------ | --------------------------------------- |
| code    | `i32`  | Exit code. `0` typically means success. |
| success | `bool` | `true` if `code` is `0`.                |

### Rlimit

<p className="msb-backref">Configured via <a href="#rlimit">rlimit()</a> · <a href="#rlimit_range">rlimit\_range()</a></p>

A POSIX resource limit. Built indirectly by [`rlimit()`](#rlimit) and [`rlimit_range()`](#rlimit_range) on the option builders; you rarely construct it by hand.

| Field    | Type                                | Description                                        |
| -------- | ----------------------------------- | -------------------------------------------------- |
| resource | [`RlimitResource`](#rlimitresource) | Which resource to limit.                           |
| soft     | `u64`                               | Soft limit; the process may raise it up to `hard`. |
| hard     | `u64`                               | Hard ceiling; raising it requires privileges.      |

### RlimitResource

<p className="msb-backref">Used by <a href="#rlimit">rlimit()</a> · <a href="#rlimit_range">rlimit\_range()</a> · <a href="#rlimit-3">AttachOptionsBuilder.rlimit()</a></p>

POSIX resource limit identifiers. Each maps to an `RLIMIT_*` constant.

| Value        | Description                                           |
| ------------ | ----------------------------------------------------- |
| `Cpu`        | Max CPU time in seconds (`RLIMIT_CPU`)                |
| `Fsize`      | Max file size in bytes (`RLIMIT_FSIZE`)               |
| `Data`       | Max data segment size (`RLIMIT_DATA`)                 |
| `Stack`      | Max stack size (`RLIMIT_STACK`)                       |
| `Core`       | Max core file size (`RLIMIT_CORE`)                    |
| `Rss`        | Max resident set size (`RLIMIT_RSS`)                  |
| `Nproc`      | Max number of processes (`RLIMIT_NPROC`)              |
| `Nofile`     | Max open file descriptors (`RLIMIT_NOFILE`)           |
| `Memlock`    | Max locked memory (`RLIMIT_MEMLOCK`)                  |
| `As`         | Max address space size (`RLIMIT_AS`)                  |
| `Locks`      | Max file locks (`RLIMIT_LOCKS`)                       |
| `Sigpending` | Max pending signals (`RLIMIT_SIGPENDING`)             |
| `Msgqueue`   | Max bytes in POSIX message queues (`RLIMIT_MSGQUEUE`) |
| `Nice`       | Max nice priority (`RLIMIT_NICE`)                     |
| `Rtprio`     | Max real-time priority (`RLIMIT_RTPRIO`)              |
| `Rttime`     | Max real-time timeout (`RLIMIT_RTTIME`)               |
