Skip to content

Terminals

Connections returned by client.pty.attach() and client.experimental.persistent_pty.attach(). See the terminals guide.

PtyConnection

PtyConnection(
    ws: ClientConnection,
    protocol: _Protocol,
    resize: Callable[[int, int], object],
    on_event: Callable[[dict[str, Any]], object]
    | None = None,
)

A synchronous connection to a remote terminal.

Iterate over it, or call :meth:recv, for output bytes; it stops when the terminal ends. Control frames are handled internally: :attr:cursor holds the latest output position the server reported, and on_event (persistent terminals) receives every JSON event.

Example::

with client.pty.attach(pty.id) as term:
    term.send("echo hi\n")
    for chunk in term:
        print(chunk.decode(errors="replace"), end="")

cursor property

cursor: int | None

Output position to pass as cursor when reattaching, once the server has reported one.

attached property

attached: dict[str, Any] | None

The attached event of a persistent terminal (attachment id, role, info, replay offsets).

close_code property

close_code: int | None

The WebSocket close code once the connection has closed.

send

send(data: bytes | str) -> None

Writes input to the terminal. str is sent as UTF-8.

resize

resize(cols: int, rows: int) -> None

Resizes the terminal.

recv

recv(timeout: float | None = None) -> bytes | None

Returns the next output chunk, or None once the terminal has ended.

Raises:

Type Description
TimeoutError

No output within timeout seconds.

PtyConnectionError

The server closed the connection abnormally (4404: terminal unavailable).

wait_attached

wait_attached(timeout: float | None) -> None

Reads frames until the attached event of a persistent terminal; attach already does this.

close

close() -> None

Closes the connection. The terminal keeps running on the server.

AsyncPtyConnection

AsyncPtyConnection(
    ws: ClientConnection,
    protocol: _Protocol,
    resize: Callable[[int, int], Awaitable[object]],
    on_event: Callable[[dict[str, Any]], object]
    | None = None,
)

An asyncio connection to a remote terminal. Same interface as :class:PtyConnection, with awaitables.

Example::

async with await client.pty.attach(pty.id) as term:
    await term.send("echo hi\n")
    async for chunk in term:
        print(chunk.decode(errors="replace"), end="")

cursor property

cursor: int | None

Output position to pass as cursor when reattaching, once the server has reported one.

attached property

attached: dict[str, Any] | None

The attached event of a persistent terminal (attachment id, role, info, replay offsets).

close_code property

close_code: int | None

The WebSocket close code once the connection has closed.

send async

send(data: bytes | str) -> None

Writes input to the terminal. str is sent as UTF-8.

resize async

resize(cols: int, rows: int) -> None

Resizes the terminal.

recv async

recv() -> bytes | None

Returns the next output chunk, or None once the terminal has ended.

Raises:

Type Description
PtyConnectionError

The server closed the connection abnormally (4404: terminal unavailable).

wait_attached async

wait_attached() -> None

Reads frames until the attached event of a persistent terminal; attach already does this.

close async

close() -> None

Closes the connection. The terminal keeps running on the server.

PtyConnectionError

PtyConnectionError(
    message: str,
    *,
    status: int | None = None,
    code: int | None = None,
    reason: str = "",
)

Bases: OpencodeError

The terminal WebSocket could not be opened or closed abnormally.

Attributes:

Name Type Description
status

HTTP status of a refused handshake (403 for a bad ticket, 404 for an unknown PTY).

code

WebSocket close code (4404 when the terminal is not found, exited or unavailable).

reason

WebSocket close reason.

status instance-attribute

status = status

code instance-attribute

code = code

reason instance-attribute

reason = reason