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

> TypeScript SDK - Command execution API reference

Run commands inside a running sandbox: collect output in one shot, stream it as it arrives, attach an interactive PTY, or pipe data to stdin. These methods live on a running [`Sandbox`](/sdk/typescript/sandbox). See [Commands](/sandboxes/commands) for usage examples.

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

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

const sandbox = await Sandbox.create("api", { image: "python" });

// 1. one-shot
const out = await sandbox.exec("python3", ["-c", "print(1 + 1)"]);
console.log(out.stdout()); // "2\n"

// 2. stream
const handle = await sandbox.execStream("tail", ["-f", "/var/log/app.log"]);
for await (const event of handle) {
  if (event.kind === "stdout") process.stdout.write(event.data);
  if (event.kind === "exited") break;
}

await sandbox.stop();
```

## Run and collect

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

```typescript theme={null}
exec(cmd: string, args?: Iterable<string>): Promise<ExecOutput>
```

<Accordion title="Example">
  ```typescript theme={null}
  const result = await sandbox.exec("python3", ["-c", "print(1 + 1)"]);
  console.log(result.stdout()); // "2\n"
  console.log(result.code);     // 0
  ```
</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 code. For long-running processes or large output, use [`execStream()`](#sandbox-execstream) instead.

<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">string</span></div>
    <div className="msb-param-desc">Command to execute (e.g. <code>"python3"</code>, <code>"/usr/bin/node"</code>).</div>
  </div>

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

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

```typescript theme={null}
execWith(
  cmd: string,
  configure: (b: ExecOptionsBuilder) => ExecOptionsBuilder,
): Promise<ExecOutput>
```

<Accordion title="Example">
  ```typescript theme={null}
  const out = await sandbox.execWith("python3", (e) =>
    e.args(["script.py"])
      .cwd("/app")
      .env("PYTHONPATH", "/app/lib")
      .timeout(30_000),
  );
  ```
</Accordion>

Run a command with per-execution overrides. Configure working directory, environment variables, timeout, stdin, TTY allocation, and rlimits via the builder callback. 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">string</span></div>
    <div className="msb-param-desc">Command to execute.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>configure</code><a className="msb-type" href="#execoptionsbuilder">(b: ExecOptionsBuilder) => ExecOptionsBuilder</a></div>
    <div className="msb-param-desc">Builder callback for per-call overrides.</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">Promise\<ExecOutput></a></div>
    <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div>
  </div>
</div>

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

```typescript theme={null}
shell(script: string): Promise<ExecOutput>
```

<Accordion title="Example">
  ```typescript theme={null}
  const out = await sandbox.shell("ls -la /app && echo done");
  console.log(out.stdout());
  ```
</Accordion>

Run a command through the sandbox's configured shell (defaults to `/bin/sh`). 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">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">Promise\<ExecOutput></a></div>
    <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div>
  </div>
</div>

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

```typescript theme={null}
attachShell(): Promise<number>
```

<Accordion title="Example">
  ```typescript theme={null}
  const code = await sandbox.attachShell();
  ```
</Accordion>

Bridge your terminal to the sandbox's default shell in a fully 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">Promise\<number></span></div>
    <div className="msb-param-desc">Exit code of the shell process.</div>
  </div>
</div>

## Stream and attach

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

```typescript theme={null}
execStream(cmd: string, args?: Iterable<string>): Promise<ExecHandle>
```

<Accordion title="Example">
  ```typescript theme={null}
  const handle = await sandbox.execStream("tail", ["-f", "/var/log/app.log"]);
  for await (const event of handle) {
    if (event.kind === "stdout") process.stdout.write(event.data);
    if (event.kind === "exited") break;
  }
  ```
</Accordion>

Run a command with streaming output. Returns a handle that emits stdout, stderr, and exit events as they happen, rather than buffering everything.

<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">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">Iterable\<string></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">Promise\<ExecHandle></a></div>
    <div className="msb-param-desc">Streaming handle for receiving events and controlling the process.</div>
  </div>
</div>

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

```typescript theme={null}
execStreamWith(
  cmd: string,
  configure: (b: ExecOptionsBuilder) => ExecOptionsBuilder,
): Promise<ExecHandle>
```

<Accordion title="Example">
  ```typescript theme={null}
  const handle = await sandbox.execStreamWith("python3", (e) =>
    e.args(["-u", "worker.py"]).env("LEVEL", "debug").stdinPipe(),
  );
  const stdin = await handle.takeStdin();
  await stdin?.write("task-1\n");
  ```
</Accordion>

Streaming variant of [`execWith()`](#sandbox-execwith): same configuration via [`ExecOptionsBuilder`](#execoptionsbuilder), but returns an [`ExecHandle`](#exechandle) instead of buffering output.

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

  <div className="msb-param">
    <div className="msb-param-key"><code>configure</code><a className="msb-type" href="#execoptionsbuilder">(b: ExecOptionsBuilder) => ExecOptionsBuilder</a></div>
    <div className="msb-param-desc">Builder callback for per-call overrides.</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">Promise\<ExecHandle></a></div>
    <div className="msb-param-desc">Streaming handle.</div>
  </div>
</div>

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

```typescript theme={null}
shellStream(script: string): Promise<ExecHandle>
```

<Accordion title="Example">
  ```typescript theme={null}
  const handle = await sandbox.shellStream("for i in 1 2 3; do echo $i; sleep 1; done");
  for await (const event of handle) {
    if (event.kind === "stdout") process.stdout.write(event.data);
  }
  ```
</Accordion>

Run a shell command with streaming output.

<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">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">Promise\<ExecHandle></a></div>
    <div className="msb-param-desc">Streaming handle.</div>
  </div>
</div>

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

```typescript theme={null}
attach(cmd: string, args?: Iterable<string>): Promise<number>
```

<Accordion title="Example">
  ```typescript theme={null}
  const code = await sandbox.attach("python3");
  ```
</Accordion>

Bridge your terminal directly to a process inside the sandbox for a fully interactive PTY session. Press `Ctrl+]` (or configured detach keys) to disconnect without stopping the process.

<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">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">Iterable\<string></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">Promise\<number></span></div>
    <div className="msb-param-desc">Exit code of the process.</div>
  </div>
</div>

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

```typescript theme={null}
attachWith(
  cmd: string,
  configure: (b: AttachOptionsBuilder) => AttachOptionsBuilder,
): Promise<number>
```

<Accordion title="Example">
  ```typescript theme={null}
  const code = await sandbox.attachWith("bash", (a) =>
    a.cwd("/app")
      .env("EDITOR", "vim")
      .detachKeys("ctrl-]"),
  );
  ```
</Accordion>

Interactive PTY attach with options for arguments, environment variables, working directory, user, custom detach keys, and rlimits. Configure via the builder callback.

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

  <div className="msb-param">
    <div className="msb-param-key"><code>configure</code><a className="msb-type" href="#attachoptionsbuilder">(b: AttachOptionsBuilder) => AttachOptionsBuilder</a></div>
    <div className="msb-param-desc">Builder callback for the attach session.</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">Promise\<number></span></div>
    <div className="msb-param-desc">Exit code of the process.</div>
  </div>
</div>

## Types

### ExecOutput

<p className="msb-backref">Returned by <a href="#sandbox-exec">exec()</a> · <a href="#sandbox-execwith">execWith()</a> · <a href="#sandbox-shell">shell()</a> · <a href="#exechandle">ExecHandle.collect()</a></p>

The result of a completed command execution: collected output plus exit status.

| Property / Method | Type                                 | Description                                                    |
| ----------------- | ------------------------------------ | -------------------------------------------------------------- |
| `code`            | `number` (getter)                    | Process exit code                                              |
| `success`         | `boolean` (getter)                   | `true` when `code === 0`                                       |
| `status`          | [`ExitStatus`](#exitstatus) (getter) | Exit status object                                             |
| `stdout()`        | `string`                             | Collected stdout decoded as UTF-8 (lossy on invalid sequences) |
| `stderr()`        | `string`                             | Collected stderr decoded as UTF-8 (lossy on invalid sequences) |
| `stdoutBytes()`   | `Uint8Array`                         | Raw stdout bytes                                               |
| `stderrBytes()`   | `Uint8Array`                         | Raw stderr bytes                                               |

### ExecHandle

<p className="msb-backref">Returned by <a href="#sandbox-execstream">execStream()</a> · <a href="#sandbox-execstreamwith">execStreamWith()</a> · <a href="#sandbox-shellstream">shellStream()</a></p>

A handle to a running streaming execution. Implements `AsyncIterable<ExecEvent>` and `AsyncDisposable`, so it works with `for await...of` and `await using`.

| Property / Method          | Type                                           | Description                                                           |
| -------------------------- | ---------------------------------------------- | --------------------------------------------------------------------- |
| `recv()`                   | `Promise<`[`ExecEvent`](#execevent)` \| null>` | Receive the next event, or `null` once the stream ends                |
| `takeStdin()`              | `Promise<`[`ExecSink`](#execsink)` \| null>`   | Take ownership of the stdin sink. Returns `null` after the first call |
| `wait()`                   | `Promise<`[`ExitStatus`](#exitstatus)`>`       | Wait for the process to exit                                          |
| `collect()`                | `Promise<`[`ExecOutput`](#execoutput)`>`       | Drain stdout/stderr and wait for exit                                 |
| `signal(signal)`           | `Promise<void>`                                | Send a POSIX signal (numeric) to the process                          |
| `kill()`                   | `Promise<void>`                                | Force-terminate the process                                           |
| `[Symbol.asyncIterator]()` | `AsyncIterator<`[`ExecEvent`](#execevent)`>`   | Iterate events with `for await...of`                                  |
| `[Symbol.asyncDispose]()`  | `Promise<void>`                                | Best-effort kill on `await using` scope exit                          |

### ExecSink

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

Writer for sending data to a running process's stdin. Implements `AsyncDisposable`. Obtained from [`ExecHandle.takeStdin()`](#exechandle) when the execution was configured with [`.stdinPipe()`](#execoptionsbuilder).

| Method                    | Type                                            | Description                                                   |
| ------------------------- | ----------------------------------------------- | ------------------------------------------------------------- |
| `write(data)`             | `(data: Uint8Array \| string) => Promise<void>` | Write bytes to the process's stdin. Strings are UTF-8 encoded |
| `close()`                 | `() => Promise<void>`                           | Send EOF. Idempotent                                          |
| `[Symbol.asyncDispose]()` | `() => Promise<void>`                           | Calls `close()` on `await using` scope exit                   |

### ExecEvent

<p className="msb-backref">Emitted by <a href="#exechandle">ExecHandle</a></p>

Discriminated union emitted while iterating an [`ExecHandle`](#exechandle). The discriminator is `kind`.

```typescript theme={null}
type ExecEvent =
  | { kind: "started"; pid: number }
  | { kind: "stdout"; data: Uint8Array }
  | { kind: "stderr"; data: Uint8Array }
  | { kind: "exited"; code: number };
```

| `kind`      | Payload            | Description             |
| ----------- | ------------------ | ----------------------- |
| `"started"` | `pid: number`      | The process has started |
| `"stdout"`  | `data: Uint8Array` | A chunk of stdout data  |
| `"stderr"`  | `data: Uint8Array` | A chunk of stderr data  |
| `"exited"`  | `code: number`     | The process has exited  |

### ExitStatus

<p className="msb-backref">Returned by <a href="#exechandle">ExecHandle.wait()</a> · <a href="#execoutput">ExecOutput.status</a></p>

The exit result of a process.

| Field   | Type      | Description              |
| ------- | --------- | ------------------------ |
| code    | `number`  | Process exit code        |
| success | `boolean` | `true` when `code === 0` |

### ExecOptionsBuilder

<p className="msb-backref">Used by <a href="#sandbox-execwith">execWith()</a> · <a href="#sandbox-execstreamwith">execStreamWith()</a></p>

Fluent builder passed to the callback in `execWith(cmd, b => ...)` and `execStreamWith(cmd, b => ...)`. Every setter mutates the builder and returns it, so calls chain.

| Method                              | Type                                                                                    | Description                                                                           |
| ----------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `arg(arg)`                          | `(arg: string) => this`                                                                 | Append a single argument                                                              |
| `args(args)`                        | `(args: string[]) => this`                                                              | Append many arguments                                                                 |
| `cwd(cwd)`                          | `(cwd: string) => this`                                                                 | Working directory                                                                     |
| `user(user)`                        | `(user: string) => this`                                                                | Guest user                                                                            |
| `env(key, value)`                   | `(key: string, value: string) => this`                                                  | Add a single env var                                                                  |
| `envs(vars)`                        | `(vars: Record<string, string>) => this`                                                | Add many env vars                                                                     |
| `timeout(ms)`                       | `(ms: number) => this`                                                                  | Kill the process after this many milliseconds                                         |
| `stdinNull()`                       | `() => this`                                                                            | Connect stdin to `/dev/null` (default)                                                |
| `stdinPipe()`                       | `() => this`                                                                            | Open a writable stdin pipe; read it back with [`ExecHandle.takeStdin()`](#exechandle) |
| `stdinBytes(data)`                  | `(data: Buffer) => this`                                                                | Pre-supply stdin bytes and close it                                                   |
| `tty(enabled)`                      | `(enabled: boolean) => this`                                                            | Allocate a pseudo-terminal                                                            |
| `rlimit(resource, limit)`           | `(resource: `[`RlimitResource`](#rlimitresource)`, limit: number) => this`              | Set both soft and hard rlimit                                                         |
| `rlimitRange(resource, soft, hard)` | `(resource: `[`RlimitResource`](#rlimitresource)`, soft: number, hard: number) => this` | Set distinct soft and hard rlimits                                                    |

### AttachOptionsBuilder

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

Fluent builder passed to the callback in `attachWith(cmd, b => ...)`. Every setter mutates the builder and returns it, so calls chain.

| Method                              | Type                                                                                    | Description                                                |
| ----------------------------------- | --------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `arg(arg)`                          | `(arg: string) => this`                                                                 | Append a single argument                                   |
| `args(args)`                        | `(args: string[]) => this`                                                              | Append many arguments                                      |
| `cwd(cwd)`                          | `(cwd: string) => this`                                                                 | Working directory                                          |
| `user(user)`                        | `(user: string) => this`                                                                | Guest user                                                 |
| `env(key, value)`                   | `(key: string, value: string) => this`                                                  | Add a single env var                                       |
| `envs(vars)`                        | `(vars: Record<string, string>) => this`                                                | Add many env vars                                          |
| `detachKeys(spec)`                  | `(spec: string) => this`                                                                | Detach key sequence (e.g. `"ctrl-]"` or `"ctrl-p,ctrl-q"`) |
| `rlimit(resource, limit)`           | `(resource: `[`RlimitResource`](#rlimitresource)`, limit: number) => this`              | Set both soft and hard rlimit                              |
| `rlimitRange(resource, soft, hard)` | `(resource: `[`RlimitResource`](#rlimitresource)`, soft: number, hard: number) => this` | Set distinct soft and hard rlimits                         |

### Stdin

<p className="msb-backref">Produces <a href="#stdinmode">StdinMode</a></p>

Helper factory for constructing a [`StdinMode`](#stdinmode). Equivalent to the `stdinNull` / `stdinPipe` / `stdinBytes` setters on [`ExecOptionsBuilder`](#execoptionsbuilder).

| Method              | Type                                                        | Description                                                                     |
| ------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `Stdin.null()`      | `() => `[`StdinMode`](#stdinmode)                           | Connect stdin to `/dev/null`                                                    |
| `Stdin.pipe()`      | `() => `[`StdinMode`](#stdinmode)                           | Open a writable pipe; caller writes via [`ExecHandle.takeStdin()`](#exechandle) |
| `Stdin.bytes(data)` | `(data: Uint8Array \| string) => `[`StdinMode`](#stdinmode) | Send the given bytes (or UTF-8-encoded string) and close stdin                  |

### StdinMode

<p className="msb-backref">Produced by <a href="#stdin">Stdin</a></p>

Discriminated union describing stdin behavior for an execution.

```typescript theme={null}
type StdinMode =
  | { kind: "null" }
  | { kind: "pipe" }
  | { kind: "bytes"; data: Uint8Array };
```

| `kind`    | Payload            | Description                         |
| --------- | ------------------ | ----------------------------------- |
| `"null"`  | -                  | Stdin connected to `/dev/null`      |
| `"pipe"`  | -                  | Writable pipe opened for the caller |
| `"bytes"` | `data: Uint8Array` | Pre-supplied stdin bytes, then EOF  |

### Rlimit

<p className="msb-backref">Set via <a href="#execoptionsbuilder">ExecOptionsBuilder.rlimit()</a> · <a href="#attachoptionsbuilder">AttachOptionsBuilder.rlimit()</a></p>

A POSIX resource limit applied to the process.

| Field    | Type                                | Description               |
| -------- | ----------------------------------- | ------------------------- |
| resource | [`RlimitResource`](#rlimitresource) | Which resource is limited |
| soft     | `number`                            | Soft limit                |
| hard     | `number`                            | Hard limit                |

### RlimitResource

<p className="msb-backref">Used by <a href="#rlimit">Rlimit.resource</a> · <a href="#execoptionsbuilder">rlimit()</a> · <a href="#attachoptionsbuilder">rlimit()</a></p>

String union naming a limitable POSIX resource.

```typescript theme={null}
type RlimitResource =
  | "cpu" | "fsize" | "data" | "stack" | "core" | "rss"
  | "nproc" | "nofile" | "memlock" | "as" | "locks"
  | "sigpending" | "msgqueue" | "nice" | "rtprio" | "rttime";
```
