commands.run, which returns a
single {stdout, stderr, exit_code} blob when the process finishes, a
PTY lets you:
- Stream bytes as they’re produced — the right choice for anything that paints the screen (progress bars, TUI apps, live logs).
- Send keystrokes mid-execution — required for password prompts, OAuth pasteback, confirmation dialogs, REPLs, and editors.
- Resize on the fly — if the user drags a terminal pane, the remote
program sees a
SIGWINCHand redraws. - Reconnect and fan out — multiple clients can subscribe to the same PTY concurrently, and clients can disconnect without killing the shell.
bash -l (login shell)
with TERM=xterm-256color pre-set, so ANSI colour codes, cursor escapes,
tput queries, and ncurses-based TUIs (vim, htop, less, nano)
all render correctly.
When to use PTY vs commands.run
Use commands.run when… | Use pty.create when… |
|---|---|
| Command takes input once (argv / piped stdin) and exits | Command prompts for input mid-run |
| You only care about the final stdout / exit code | You need live output as bytes arrive |
| Output is line-oriented plain text | Output has ANSI escapes or cursor movement |
pip install, pytest, python script.py, go build | gh auth login, vim, htop, sudo, ssh |
commands.run. Reach for pty.create only when the
command requires a terminal.
Architecture
pty.create takes four REST calls plus one SSE stream:
| Operation | Method / route |
|---|---|
| Create session | POST /sandboxes/{id}/pty — returns the remote pid |
| Send stdin | POST /sandboxes/{id}/pty/{pid}/stdin |
| Resize | PATCH /sandboxes/{id}/pty/{pid} |
| Kill | DELETE /sandboxes/{id}/pty/{pid} |
| Live output | GET /sandboxes/{id}/pty/{pid}/stream (Server-Sent Events, base64-encoded frames) |
event: data frames with base64-encoded payload, and a final
event: exit frame announces the remote exit code.
Session lifecycle
A PTY session is bounded by two independent timeouts — whichever fires first ends the session:- The sandbox timeout (set at
Sandbox.create(timeout=...), default 300s) kills the whole microVM and every PTY inside it. - The PTY timeout (set at
sandbox.pty.create(timeout=...), default 3600s) kills just that one PTY. Pass0for no PTY-level TTL — sessions then live until the sandbox itself expires.
Quick start
Callback-style — your function receives every chunk of PTY output as it arrives. Good for forwarding to anxterm.js instance or your local
terminal.
- Python
- TypeScript
Next steps
- Python SDK: PTY reference —
PtyHandle,PtyResult, iterator-style streaming,connect() - TypeScript SDK: PTY reference — same surface in TypeScript
- Cookbook: interactive terminal — drop your local TTY into a sandbox shell,
ssh-style