Wire Protocol

All WebSocket messages are binary frames. The first byte is the command, the rest is the payload.

Commands

DirectionCmdPayloadDescription
client → server0x00raw bytesTerminal input
client → server0x01rows(u16 BE) + cols(u16 BE)Resize
server → client0x00raw bytesTerminal output
server → client0x10UUID stringSession ID
server → client0x12Shell exited
server → client0x13rows(u16 BE) + cols(u16 BE)Window size
server → client0x14Replay end

Close codes

CodeMeaning
4404Session not found (invalid or expired sid)

Handshake sequence

1. Handshakeresolve / create session2. Replay3. Streaming4. ShutdownWS connect (?sid, view)0x10 Session ID0x13 Window size0x00 Output (scrollback)0x13 Window size(scrollback)0x14 Replay end0x00 Output0x00 Input0x01 Resize0x13 Window size(broadcast)0x00 Output0x12 Shell exitedClientServerClientServer
1. Handshakeresolve / create session2. Replay3. Streaming4. ShutdownWS connect (?sid, view)0x10 Session ID0x13 Window size0x00 Output (scrollback)0x13 Window size(scrollback)0x14 Replay end0x00 Output0x00 Input0x01 Resize0x13 Window size(broadcast)0x00 Output0x12 Shell exitedClientServerClientServer
1. Handshakeresolve / create session2. Replay3. Streaming4. ShutdownWS connect (?sid, view)0x10 Session ID0x13 Window size0x00 Output (scrollback)0x13 Window size(scrollback)0x14 Replay end0x00 Output0x00 Input0x01 Resize0x13 Window size(broadcast)0x00 Output0x12 Shell exitedClientServerClientServer
1. Handshakeresolve / create session2. Replay3. Streaming4. ShutdownWS connect (?sid, view)0x10 Session ID0x13 Window size0x00 Output (scrollback)0x13 Window size(scrollback)0x14 Replay end0x00 Output0x00 Input0x01 Resize0x13 Window size(broadcast)0x00 Output0x12 Shell exitedClientServerClientServer
1. Handshakeresolve / create session2. Replay3. Streaming4. ShutdownWS connect (?sid, view)0x10 Session ID0x13 Window size0x00 Output (scrollback)0x13 Window size(scrollback)0x14 Replay end0x00 Output0x00 Input0x01 Resize0x13 Window size(broadcast)0x00 Output0x12 Shell exitedClientServerClientServer
  1. The client opens a WebSocket to /ws with an optional sid query parameter and an optional view flag.
  2. The server resolves an existing session or creates a new one. If sid is provided but not found, the connection is closed with code 4404.
  3. The server sends 0x10 with the session UUID. The client enters replay mode (input suppressed, terminal reset).
  4. The server sends 0x13 with the current PTY window size. View-mode clients use this to match their terminal dimensions to the interactive session before scrollback replay.
  5. The server replays the scrollback event log as a sequence of 0x00 (output) and 0x13 (window size) frames — one per stored event. The subscription is established atomically so no messages are lost between the replay and live streaming.
  6. The server sends 0x14 (replay end). The client exits replay mode, shows the cursor, and sends its initial resize.
  7. The main loop begins: output is forwarded as 0x00 frames, input and resize commands are read from the client. In view mode, client input is ignored.
  8. When an interactive client sends a resize (0x01), the server updates the PTY and broadcasts 0x13 to all connected clients.
  9. When the shell process exits, the server sends 0x12 and the connection closes.