Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.declaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

The simplest possible PTY example. Create a sandbox, open a PTY session, send a few commands as raw keystrokes, resize the terminal mid-session, and exit cleanly. Everything uses the sync API and runs without a local TTY (no raw-mode needed).

What you’ll learn

  • Opening a PTY with sbx.pty.create() and the on_data callback
  • Sending keystrokes with handle.send_stdin()
  • Resizing mid-session with handle.resize(PtySize(...))
  • Waiting for a clean exit with handle.wait()

Prerequisites

Also install the SDK if you haven’t:
pip install declaw

Code walkthrough

Create a sandbox and open a PTY at 120x30. The on_data callback writes every chunk straight to local stdout as it arrives:
from declaw import Sandbox
from declaw.sandbox.commands.models import PtySize

with Sandbox.create() as sbx:
    handle = sbx.pty.create(
        size=PtySize(cols=120, rows=30),
        on_data=lambda chunk: (
            sys.stdout.buffer.write(chunk),
            sys.stdout.buffer.flush(),
        ),
        timeout=60,
    )
Send a few commands. A short sleep between sends gives the shell time to print output before the next command arrives:
    handle.send_stdin(b"echo hello-from-pty\n")
    handle.send_stdin(b"python3 -c 'import sys; print(sys.stdout.isatty())'\n")
    handle.send_stdin(b"stty size\n")
isatty() returns True because this is a real PTY, not a piped exec. stty size prints 30 120 matching the size we requested. Resize the terminal to 100x40 and verify:
    handle.resize(PtySize(cols=100, rows=40))
    handle.send_stdin(b"stty size\n")   # → 40 100
Exit the shell and collect the result:
    handle.send_stdin(b"exit\n")
    result = handle.wait(timeout=10)
    print(f"pty exited with code {result.exit_code}")

Running it

export DECLAW_API_KEY="your-api-key"
export DECLAW_DOMAIN="api.declaw.ai"
python cookbook/examples/pty-repl/main.py

Expected output

sandbox: sbx_abc123
pty pid: 7

bash-5.1$ echo hello-from-pty
hello-from-pty
bash-5.1$ python3 -c 'import sys; print(sys.stdout.isatty())'
True
bash-5.1$ stty size
30 120
bash-5.1$ stty size
40 100
bash-5.1$ exit

[pty exited with code 0]
The key takeaway: the remote shell saw a real PTY (isatty() = True) and stty size updated after handle.resize() without reconnecting.

Full source

See cookbook/examples/pty-repl/main.py in the repo.