Skip to main content
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.

Buffered 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.
MCP: the sandbox_exec tool runs a buffered command the same way. The request body (DirectExecRequest) extends the common command shape:
string[]
required
Argv to run. At least one element.
object
Environment variables to set.
string
Working directory.
integer
Timeout in seconds, 1–300.
string
Base64-encoded stdin to feed the process.
string
utf8 or base64, controlling how stdout/stderr are encoded in the response.
Response (DirectExecResponse), always 200:
integer
required
The process’s exit code.
boolean
required
Whether the process was terminated by a signal.
integer
The signal number, if signaled is true.
boolean
required
Whether timeout_s was reached before the process exited.
string
required
Captured stdout, encoded per output_encoding.
string
required
Captured stderr, encoded per output_encoding.
boolean
required
Whether stdout was cut short.
boolean
required
Whether stderr was cut short.
string
required
utf8 or base64, matching the request (or the server default).
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 for what actually does produce a non-2xx response.

TTY 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 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.
Streaming a TTY session (for full interactive forwarding, with resize) works the same way over each SDK’s streaming call — see 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 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.

Sessions

WebSockets

Errors