Skip to main content
This cookbook walks through a small script that attaches your local terminal to a sandbox PTY: every keystroke you type is forwarded to the remote shell, every byte the shell emits streams back to your screen, and the pseudo-terminal resizes when you drag your window. It’s the same idea as ssh into a VM, but the VM is a fresh declaw sandbox created on demand.

What you’ll learn

  • Putting your local TTY in raw mode so keystrokes flow without buffering
  • Installing a SIGWINCH handler that propagates window resizes to the sandbox
  • Writing output bytes to local stdout via the on_data callback
  • Detecting Ctrl-D locally and sending a clean exit\n

Prerequisites

Also install the SDK if you haven’t:

Code

Running it

Drop the snippet into pty_live.py and run it in an interactive terminal (iTerm2, Alacritty, Kitty, Terminal.app, tmux — any real TTY works):
You land at a bash prompt inside a fresh sandbox. Try:
  • ls /etc/os-release — reads a file
  • htop — full-screen TUI, quit with q
  • vim /tmp/x.txt — editor loads, :wq to save
  • stty size — prints cols rows matching your local terminal
  • Resize your window — stty size updates on the next probe
  • Ctrl-D — closes the session cleanly

How it works

  1. Sandbox.create() — new sandbox, 300s default lifetime.
  2. sbx.pty.create(on_data=...) — spawns a real bash -l inside the VM, opens an SSE stream, and invokes on_data with every chunk.
  3. Raw-mode local TTYtty.setraw(fd) disables line buffering and local echo so each keystroke reaches the script immediately. The remote bash echoes for us.
  4. os.read(fd, 1024) — pulls bytes the user typed. We forward them untouched with handle.send_stdin(data).
  5. SIGWINCH handler — calls handle.resize(...) with the new local size, which fires TIOCSWINSZ inside the sandbox; htop and friends redraw for the new dimensions.
  6. Ctrl-D (EOT, \x04) — we intercept locally and send exit\n so the remote shell exits cleanly instead of sending raw EOT and confusing bash.
  7. handle.wait() — blocks until the PTY stream emits its exit frame, returns a PtyResult.

See also

More PTY recipes