Copy text from a range of absolute row/col positions in scrollback + viewport:
[0x1B][nonce:2][pty_id:2][start_tail:4][start_col:2][end_tail:4][end_col:2][flags:1]
start_tail/end_tail: physical row distance from the bottom (0 = last row).
start is the earlier position (closer to top), so start_tail >= end_tail.
flags: reserved (0 for now).
Server responds with S2C_TEXT using the same nonce.
Generic create: [0x18][nonce:2][rows:2][cols:2][features:1][tag_len:2][tag:N][…optional fields]
Features: bit 0 = has src_pty_id (2 bytes after tag), bit 1 = has command (remaining bytes after src_pty_id if present)
Server responds with S2C_CREATED_N using the same nonce.
Mouse event: [0x06][pty_id:2][type:1][button:1][col:2][row:2]
type: 0=down, 1=up, 2=move
button: 0=left, 1=mid, 2=right, 3=release, 64=wheel_up, 65=wheel_down
The server generates the correct escape sequence based on mouse_mode and mouse_encoding.
Read text from a PTY’s scrollback + viewport: [0x19][nonce:2][pty_id:2][offset:4][limit:4][flags:1]
offset: number of lines to skip from the top (oldest = 0), or from the end if READ_TAIL is set
limit: max lines to return (0 = all)
flags: bit 0 = include ANSI styling, bit 1 = offset counts from the end
Server responds with S2C_TEXT using the same nonce.
Desired viewport size(s): [0x01][pty_id:2][rows:2][cols:2]…
Clients may batch multiple PTY resize entries in one message. The server
mediates these per-client desired sizes into each PTY’s effective size.
A rows, cols pair of 0, 0 clears this client’s desired size for that PTY.
Keyboard input for a Wayland surface: [0x20][session_id:2][surface_id:2][data:N]
data contains evdev keycodes encoded as [keycode:4][pressed:1] sequences.
Pointer motion/button for a Wayland surface: [0x21][session_id:2][surface_id:2][type:1][button:1][x:2][y:2]
type: 0=down, 1=up, 2=move
x,y: pixel coordinates relative to the surface origin
The PTY’s subprocess has exited but the terminal state is retained.
Clients can still read/scroll the last frame. Send C2S_CLOSE to dismiss.
Wire: [0x08][pty_id:2][exit_status:4]
exit_status: WEXITSTATUS if normal exit, negative signal number if signalled,
EXIT_STATUS_UNKNOWN if not yet collected.
Sent after the initial burst (HELLO, LIST, TITLE*, EXITED*) is complete.
Clients can use this to know when the initial state has been fully transmitted.
Screenshot of a surface: [0x27][surface_id:2][width:4][height:4][image_data:N]
image_data is PNG or AVIF depending on the request format.
If the surface was not found or has no buffer, width=0 and height=0 with empty data.
A new Wayland toplevel surface was created:
[0x20][session_id:2][surface_id:2][parent_id:2][width:2][height:2][title_len:2][title:N][app_id_len:2][app_id:N]
parent_id: 0 = no parent (top-level), non-zero = dialog/child of that surface
An encoded video frame for a Wayland surface:
[0x22][session_id:2][surface_id:2][timestamp:4][flags:1][width:2][height:2][data:N]
flags: bit 0 = keyframe, bits 1-2 = codec (0 = H.264, 1 = AV1).
timestamp: milliseconds since compositor session start.
List of all compositor surfaces:
[0x26][count:2] repeated{ [surface_id:2][parent_id:2][width:2][height:2][title_len:2][title:N][app_id_len:2][app_id:N] }
Text response: [0x0A][nonce:2][pty_id:2][total_lines:4][offset:4][text:N]
nonce: echoed from C2S_READ request
total_lines: total available lines (scrollback + viewport rows)
offset: the offset that was requested
text: UTF-8 text, lines separated by \n
scale_120 is the device-pixel-ratio in 1/120th units, matching
Wayland’s fractional_scale_v1 convention: 120 = 1×, 180 = 1.5×,
240 = 2×. A value of 0 means “unspecified” (server defaults to 1×).