Runtime

How to stream command output from a sandbox

Pass onStdout to exec (on_stdout in Python), or loop over execStream(); each chunk arrives as the command prints it.

On Runtime a streamed command has no output limit, and a long stream picks itself up again from the right byte. When a stream runs past the server's time limit, the SDK resumes it from a cursor, so no line is lost or printed twice. A command in a sandbox already in use answered in a median 105 ms, measured on 24 September 2026 (speed), so the first line of a build or a test run reaches your terminal almost at once.

The callbacks get each piece of stdout and stderr as text, and the result still holds everything the command printed:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();const result = await sbx.exec("for i in 1 2 3; do echo line $i; sleep 1; done", {  onStdout: (text) => process.stdout.write(text),  onStderr: (text) => process.stderr.write(text),});console.log("exit", result.exitCode, result.stdoutTruncated);
Pythonimport sysfrom withruntime import Sandboxwith Sandbox.create() as sbx:    result = sbx.exec("for i in 1 2 3; do echo line $i; sleep 1; done",                      on_stdout=sys.stdout.write, on_stderr=sys.stderr.write)    print("exit", result.exit_code, result.stdout_truncated)

From a terminal, runtime sandbox exec streams by default and exits with the command's own exit code, 124 when it timed out, so set -e scripts behave:

Terminalid=$(runtime sandbox create)runtime sandbox exec "${id}" -- python3 -c 'print(6 * 7)'runtime sandbox stop "${id}"

Read the events one by one

When you want to tell the streams apart or react to the exit, iterate the events. Each has a type: start, stdout, stderr or exit.

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();for await (const event of sbx.execStream("npm --version")) {  if (event.type === "stdout") process.stdout.write(event.data);  if (event.type === "stderr") process.stderr.write(event.data);  if (event.type === "exit") console.log("exit", event.exitCode);}
Pythonfrom withruntime import Sandboxwith Sandbox.create() as sbx:    for event in sbx.exec_stream("npm --version"):        if event["type"] == "stdout":            print(event["data"], end="")        elif event["type"] == "exit":            print("exit", event["exitCode"])

Over plain HTTP, POST /v1/sandboxes/{id}:exec with "stream": true answers NDJSON, one event a line, and a continue event carries the cursor to resume from (commands and processes).

Output limits

Case What you get back
exec with no callback, timeout up to 60s At most 64 KiB of stdout and 64 KiB of stderr in the result
exec with onStdout or onStderr Streams; the result keeps everything the command printed
exec with timeoutMs over 60,000 Streams by itself, as if you passed a callback
execStream() Every event, with no output limit
A reader far behind The sandbox keeps the latest 1 MiB; a truncated event says so
Timeout 60 seconds by default, 24 hours at most; a timeout is a result
runtime sandbox exec --json One result, at most 64 KiB of each stream, with the truncation flags

Output costs nothing on its own. The sandbox is billed for the CPU it uses, $0.025 per active vCPU-hour, and its memory, $0.0075 per GiB-hour (pricing).

Mistakes to avoid

  • Reading a big log from the plain result. Past 64 KiB the rest is dropped and stdoutTruncated is true. Check the flag, add a callback, or send the output to a file (cmd > /workspace/out.log) and read it with sbx.files.readText.
  • Treating a timeout as an exception. It comes back as timedOut: true (timed_out in Python) with the output so far. Add check: true to throw CommandError on a non-zero exit instead.
  • A reader that stops reading. The sandbox holds the latest 1 MiB of a command's output. A consumer that falls further behind loses the oldest part, gets a truncated event, and both truncation flags are set. Keep the loop reading, or write to a file.
  • Streaming a server. exec waits for the command to end. A dev server or a watcher belongs in a background process, whose output you follow separately.
  • A secret in the command line. Pass it in env: it is never echoed back, and journals record a hash, not the value.

Facts on this page were checked on 25 September 2026.