Skip to content
Runtime

How to open an interactive terminal in a sandbox

Run runtime sandboxes shell <id> from your terminal. Or call sbx.terminal() in code to open a real terminal over a WebSocket.

On Runtime, the terminal is a real one, with colors, prompts and resizing. The sandbox opens no port to provide it. The terminal travels over one authenticated WebSocket through Runtime's API. So only a key that may run commands in that sandbox can connect.

From your own terminal

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

${id} can be the sandbox's id or its name. On first use, ssh makes an SSH key for this machine. It sends only the public half. Run runtime sandboxes ssh config --install once. After that, every sandbox answers as the host <id>.runtime for 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 and 2 per sandbox, up to 340; 12 in one sandbox at most
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 sandboxes shell
Your editor, scp or rsync runtime sandboxes ssh and ssh <id>.runtime
A port on your laptop runtime sandboxes port-forward <id> <port>

Mistakes to avoid

  • Sending a command without a newline. The terminal runs what you type only when it sees \n, the same as a keyboard's Enter.
  • Parsing terminal output as plain text. It carries color and cursor codes. For output you plan to parse, run the command with exec. It returns clean stdout and stderr.
  • Leaving terminals open. An organization can have 64 terminals open at the same time, and 12 in any one sandbox. Write exit, or close the socket, when a session ends. Past the limit, you get 429 with Retry-After.
  • Setting a time limit for a long session. An open terminal keeps a sandbox running. A sandbox has no time limit by default. One created with timeoutSeconds still ends at that limit. Leave it out, or see extend a sandbox's time limit.

Facts on this page were checked on 26 October 2026.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card