PTY sessions run over the machine WebSocket channel and also expose REST helpers for listing, resizing, and killing sessions. Idle PTY streams remain connected while the machine is running. A WebSocket close without a pty_exited message is reported as a transport disconnect. Session IDs are scoped to the current running machine execution; after hibernate/resume, create a new PTY session. PTY sessions are created over the machine WebSocket channel (/v1/machines/{id}/ws); the SDKs and CLI manage that connection. List, resize, and kill also have REST endpoints (see Manage sessions).

Create a session

session = machine.pty.create_session(cols=100, rows=30, cwd="/workspace")
chunks = []

session.send_input("pwd\nexit\n")
session.wait(on_data=lambda chunk: chunks.append(chunk.decode("utf-8")), timeout=5)
print("".join(chunks))

Disconnect and reconnect

Reconnecting to an existing session by session_id is available from the Python SDK and CLI, and over the machine WebSocket for raw clients. The TypeScript SDK opens a new session per pty.open() call and does not reconnect to an existing session.
session_id = session.session_id
session.disconnect()

reattached = machine.pty.connect(
    session_id=session_id,
    on_data=lambda chunk: print(chunk.decode("utf-8"), end=""),
)
reattached.send_input("echo reattached\n")
Use the session_id printed by machine pty create with --session-id. Numeric pid reconnect remains available for legacy scripts. In a local TTY, connect forwards keyboard input, streams PTY output, and tracks terminal resize events. With --json, it waits for completion, forwards piped stdin when present, and prints the final result. PTY session IDs and legacy PIDs are not durable across hibernate/resume.

Manage sessions

Listing, resizing, and killing sessions are available across all clients and use the session_id returned by create.
sessions = machine.pty.list_sessions()
session_id = sessions[0].session_id
machine.pty.resize_session(session_id, 140, 40)
machine.pty.kill_session(session_id)
The session handle exposes id, session_id, pid, is_connected, exit_code, and error. It also supports byte iteration when you want to read PTY output directly:
for chunk in session:
    print(chunk.decode("utf-8"), end="")
Use session.resize(cols, rows) for the active WebSocket handle. Use resize_session(session_id, cols, rows) when you are managing a session by ID.