Runtime

How to open an interactive terminal in a sandbox

Run runtime sandbox shell <id> from your terminal, or call sbx.terminal() in code for a real terminal over a WebSocket.

On Runtime the terminal is a real one, with colours, prompts and resizing, and the sandbox opens no port to get it. It travels over one authenticated WebSocket through Runtime's API, so only a key that may run commands in that sandbox can connect. A paused sandbox wakes for it by itself, usually in about half a second, and a pause took a median 234 ms when you are done, measured on 24 September 2026 (speed).

From your own terminal

Terminalruntime sandbox shell "${id}"          # an interactive terminal, like sshruntime sandbox ssh "${id}"            # the same through OpenSSH, as the sandbox userruntime sandbox ssh "${id}" -- make test   # one command; exits with its code

${id} can be the sandbox's id or its name. ssh makes an SSH key for this machine on first use and sends only its public half. Run runtime sandbox ssh config --install once and every sandbox answers as the host <id>.runtime to ssh, scp, VS Code and JetBrains Gateway (SSH and editors).

From code

What you write is typed into the terminal; what it prints comes back as bytes, escape codes included:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();const term = await sbx.terminal({  cols: 120,  rows: 40,  onData: (bytes) => process.stdout.write(bytes),});term.write("echo hello from the terminal\n");term.resize(100, 30);term.write("exit\n");console.log("exit code", await term.exited);
Pythonfrom withruntime import Sandboxwith Sandbox.create() as sbx:    term = sbx.terminal(cols=120, rows=40)    term.write("echo hello from the terminal\n")    term.write("exit\n")    while (chunk := term.recv()) is not None:        print(chunk.decode(errors="replace"), end="")

In TypeScript, term.exited resolves with the shell's exit code. In Python, recv() returns None once the terminal has closed.

The protocol, if you speak it yourself

GET /v1/sandboxes/{id}/terminal with Upgrade: websocket and the bearer header opens one (terminals).

Part What it is
Query cols, rows, command (default bash -l), cwd, or processId
Binary frames Terminal bytes, both ways
Text frames you send {"type":"resize","cols":120,"rows":40}
Text frames it sends {"type":"ready","processId":...}, then {"type":"exit","exitCode":...}
Attach to a process Start it with spawn(..., { pty: { cols, rows } }), then pass its processId
Limits 64 terminals open per organization, at most 12 of them in one sandbox
Who you are The runtime user, whose home is /workspace, with sudo
Cost Nothing for the terminal; the sandbox's measured CPU and reserved memory

Terminal, exec or SSH?

You want Use
One command and its result exec, which waits and returns the exit code and output
A program that asks questions or redraws terminal() or runtime sandbox shell
Your editor, scp or rsync runtime sandbox ssh and ssh <id>.runtime
A port on your laptop runtime sandbox port-forward <id> <port>

Mistakes to avoid

  • Sending a command without a newline. The terminal only runs what you type when it sees \n, as a keyboard's Enter.
  • Parsing terminal output as plain text. It carries colour and cursor codes. For output you mean to parse, run the command with exec, which returns clean stdout and stderr.
  • Leaving terminals open. An organization holds 64 at once, 12 in any one sandbox. Write exit, or close the socket, when a session ends; past the limit you get 429 with Retry-After.
  • Expecting an open terminal to hold the sandbox awake forever. The lease still ends at timeoutSeconds. Extend it, or see extend a sandbox lease.

Facts on this page were checked on 25 September 2026.