Skip to main content
The PTY endpoint gives you a full interactive terminal inside a capsule. Unlike the exec and stream endpoints, PTY sessions allocate a pseudo-terminal device — the same infrastructure that powers SSH and terminal emulators. This means programs that rely on a TTY (interactive shells, editors like vim, full-screen CLI apps) behave correctly. Sessions persist across WebSocket disconnections. If your connection drops, the process keeps running inside the capsule and you can reconnect using the session tag.

Endpoint

GET https://app.wrenn.dev/api/v1/capsules/{id}/pty
Upgrade this request to a WebSocket by including the standard Upgrade: websocket headers.

Authentication

X-API-Key
string
required
Your team’s API key.

Path parameters

id
string
required
The capsule ID.

WebSocket protocol

Client messages — starting a session

Send this as the first message to start a new PTY session:
{
  "type": "start",
  "cmd": "/bin/bash",
  "args": [],
  "cols": 80,
  "rows": 24,
  "envs": {"TERM": "xterm-256color"},
  "cwd": "/home/user",
  "user": "user"
}
FieldTypeRequiredDefaultDescription
typestringYesMust be "start".
cmdstringNo"/bin/bash"Command to run as the terminal process.
argsstring[]No[]Arguments to pass to the command.
colsintegerNo80Terminal width in columns.
rowsintegerNo24Terminal height in rows.
envsobjectNo{}Additional environment variables.
cwdstringNoWorking directory for the process.
userstringNoUser to run the process as.

Client messages — reconnecting

To reconnect to an existing PTY session, send the tag you received in the started server message:
{
  "type": "connect",
  "tag": "pty-abc123de"
}

Client messages — during a session

Once the session is established (after receiving started from the server), you can send: Input — keystrokes or pasted text, base64-encoded:
{
  "type": "input",
  "data": "<base64-encoded bytes>"
}
Resize — when the terminal window changes size:
{
  "type": "resize",
  "cols": 120,
  "rows": 40
}
Kill — terminate the terminal process:
{
  "type": "kill"
}

Server messages

typeFieldsWhen sent
startedtag: string, pid: integerSession started. Save tag to reconnect later.
outputdata: stringTerminal output, base64-encoded. Decode before rendering.
exitexit_code: integerTerminal process exited.
errordata: string, fatal: booleanAn error occurred. When fatal is true, the connection closes.
pingKeepalive from the server; no response required.
{"type": "started", "tag": "pty-abc123de", "pid": 42}
{"type": "output", "data": "YmFzaC01LjIkIA=="}
{"type": "exit", "exit_code": 0}
All PTY data — both input you send and output you receive — is base64-encoded. Raw terminal bytes include ANSI escape sequences and control codes that are not valid UTF-8. Decode the data field before passing it to your terminal renderer.
PTY sessions survive WebSocket disconnections. The process keeps running in the capsule. Save the tag from the started message and use {"type": "connect", "tag": "..."} to rejoin a session after a disconnect.

Python SDK

The SDK wraps the WebSocket protocol and decodes base64 output automatically. Iterate over the session directly to receive events.
import sys
from wrenn import Capsule

with Capsule(wait=True) as capsule:
    with capsule.pty(cmd="/bin/bash", cols=120, rows=40) as term:
        # Send input as raw bytes
        term.write(b"ls -la\n")

        # Iterate events
        for event in term:
            if event.type == "output":
                sys.stdout.buffer.write(event.data)
            elif event.type == "exit":
                break

# Reconnect to an existing session using its tag
saved_tag = term.tag
with capsule.pty_connect(saved_tag) as term:
    term.write(b"echo reconnected\n")
    for event in term:
        if event.type == "output":
            sys.stdout.buffer.write(event.data)
        elif event.type == "exit":
            break

Errors

StatusMeaning
404Capsule not found or does not belong to your team.
409Capsule is not in the running state. Start or resume the capsule first.