> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bonya.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Exec

> Three ways to run a command in a sandbox

There are three distinct ways to run a command in a sandbox. Pick based on whether you need a single buffered result, a live interactive terminal, or a command that outlives the connection that started it.

| Mode | Endpoint | Use it when |
| - | - | - |
| Buffered exec | `POST /v1/sandbox/{sandbox_id}/exec` | You want one command's exit code and output as a single JSON response. |
| TTY exec | `GET /v1/sandbox/{sandbox_id}/exec` (WebSocket) | You want an interactive, transient terminal for one command. |
| Managed sessions | `POST /v1/sandbox/{sandbox_id}/sessions` | You want a named command you can list, re-attach to, or kill independently of the connection that started it. |

## Buffered exec

```
POST /v1/sandbox/{sandbox_id}/exec
```

Synchronous, non-TTY, JSON request and response — no WebSocket upgrade involved. One JSON request, one JSON response; a non-zero exit code is still a `200` — check `exit_code` in the body.

```shell cURL theme={null}
curl -s -X POST "https://api.bonya.ai/v1/sandbox/$SANDBOX_ID/exec" \
  -H "Authorization: Bearer $BONYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"cmd": ["echo", "hello from bonya"]}'
```

```shell CLI theme={null}
bonya exec $SANDBOX_ID -- echo "hello from bonya"
```

```ts TypeScript theme={null}
const result = await sandbox.exec(["echo", "hello from bonya"]);
console.log(result.stdout, result.exitCode);
```

```python Python theme={null}
result = sandbox.exec(["echo", "hello from bonya"])
print(result.stdout, result.exit_code)
```

```go Go theme={null}
result, err := sandbox.Exec(ctx, []string{"echo", "hello from bonya"})
if err != nil {
    log.Fatal(err)
}
fmt.Println(result.Stdout(), result.ExitCode)
```

**MCP:** the `sandbox_exec` tool runs a buffered command the same way.

The request body (`DirectExecRequest`) extends the common command shape:

**cmd** `string[]` *required*

Argv to run. At least one element.

**env** `object`

Environment variables to set.

**path** `string`

Working directory.

**timeout\_s** `integer`

Timeout in seconds, 1–300.

**stdin\_b64** `string`

Base64-encoded stdin to feed the process.

**output\_encoding** `string`

`utf8` or `base64`, controlling how `stdout`/`stderr` are encoded in the response.

Response (`DirectExecResponse`), always `200`:

**exit\_code** `integer` *required*

The process's exit code.

**signaled** `boolean` *required*

Whether the process was terminated by a signal.

**signal** `integer`

The signal number, if `signaled` is true.

**timed\_out** `boolean` *required*

Whether `timeout_s` was reached before the process exited.

**stdout** `string` *required*

Captured stdout, encoded per `output_encoding`.

**stderr** `string` *required*

Captured stderr, encoded per `output_encoding`.

**stdout\_truncated** `boolean` *required*

Whether `stdout` was cut short.

**stderr\_truncated** `boolean` *required*

Whether `stderr` was cut short.

**output\_encoding** `string` *required*

`utf8` or `base64`, matching the request (or the server default).

> [!WARNING]
>
> A non-zero `exit_code` is still a **200 response** — it is not an API error. Buffered exec's HTTP status reflects whether the call itself succeeded (reached the sandbox, ran the command, and returned a result), not whether the command exited cleanly. Check `exit_code` and `signaled` in the body to determine command success; don't infer it from HTTP status. See [Errors](https://docs.bonya.ai/concepts/errors.md) for what actually does produce a non-2xx response.

## TTY exec

```
GET /v1/sandbox/{sandbox_id}/exec
```

An HTTP upgrade to a WebSocket for a transient, interactive TTY session — one-off, not tracked as a named session. The START frame carries a `TTYStartRequest`. See [WebSockets](https://docs.bonya.ai/concepts/websockets.md) for how the upgrade, START frame, and admission-at-START model work — that mechanism isn't repeated here.

There's no raw cURL example for this mode — it's a WebSocket upgrade, not a single request/response — but the CLI and every SDK reach it directly: the CLI's `--tty` flag and each SDK's `tty: true` option both drive this exact endpoint, not a separate mechanism.

```shell CLI theme={null}
bonya exec $SANDBOX_ID --tty -- bash
```

```ts TypeScript theme={null}
const result = await sandbox.exec(["bash", "-lc", "stty size; printf done"], { tty: true, check: true });
console.log(result.stdout);
```

```python Python theme={null}
result = sandbox.exec(["bash", "-lc", "stty size; printf done"], tty=True, check=True)
print(result.stdout)
```

```go Go theme={null}
result, err := sandbox.Exec(ctx, []string{"bash", "-lc", "stty size; printf done"}, bonya.ExecOptions{TTY: true, Check: true})
if err != nil {
    log.Fatal(err)
}
fmt.Println(result.Stdout())
```

Streaming a TTY session (for full interactive forwarding, with resize) works the same way over each SDK's streaming call — see [Streaming exec](https://docs.bonya.ai/guides/examples.md#stream-a-command-streaming-exec) for the non-TTY version of that pattern; pass `tty: true` (plus matching `cols`/`rows`) to get terminal semantics on the stream instead.

There's no MCP tool for TTY exec — [MCP tools](https://docs.bonya.ai/mcp/tools.md) notes the WebSocket `exec` and session `attach` endpoints don't fit a request/response tool call; `sandbox_exec` is buffered-only.

## Managed sessions

For a command that should persist and be addressable by name independent of any single connection — list it, re-attach to it later, kill it explicitly — use a managed session instead of either exec mode. See [Sessions](https://docs.bonya.ai/concepts/sessions.md).

## Related

> [card] [Sessions](https://docs.bonya.ai/concepts/sessions.md)

> [card] [WebSockets](https://docs.bonya.ai/concepts/websockets.md)

> [card] [Errors](https://docs.bonya.ai/concepts/errors.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.