Protocol Reference
The complete WebSocket message protocol. All messages are JSON over a single WebSocket connection at /ws.
Connection
Connect to the server at ws://host:port/ws. The client has 10 seconds to send an auth or auth:resume message, or the connection is closed.
// HTTP URLs are converted to WS automatically by the client library
// http://localhost:3456 → ws://localhost:3456/ws
// https://example.com → wss://example.com/ws
const ws = new WebSocket('ws://localhost:3456/ws');Constants
shared/src/constants.ts| Constant | Value | Description |
|---|---|---|
DEFAULT_PORT | 3456 | Default server port |
WS_PATH | /ws | WebSocket endpoint path |
AUTH_TIMEOUT_MS | 10,000 | Time to authenticate before disconnect |
TOKEN_TTL_MS | 300,000 | Token validity (5 minutes) |
HEARTBEAT_INTERVAL_MS | 30,000 | Ping/pong keepalive interval |
RECONNECT_BASE_MS | 1,000 | Initial reconnect delay |
RECONNECT_MAX_MS | 30,000 | Maximum reconnect delay |
Client → Server
auth
Authenticate with a one-time token.
interface AuthMessage {
type: 'auth';
token: string; // e.g. "a1b2-c3d4-e5f6-7890"
}auth:resume
Resume an existing session. The server replays the terminal list and scrollback.
interface AuthResumeMessage {
type: 'auth:resume';
sessionId: string; // UUID from a previous auth:ok
}terminal:create
Spawn a new pseudo-terminal.
interface TerminalCreateMessage {
type: 'terminal:create';
cols: number; // Terminal width in columns
rows: number; // Terminal height in rows
shell?: string; // Optional: e.g. "/bin/zsh", "powershell.exe"
}shell is omitted, the server uses $SHELL on Unix or powershell.exe on Windows.terminal:input
Send data (keystrokes, pasted text) to a terminal.
interface TerminalInputMessage {
type: 'terminal:input';
terminalId: string;
data: string; // Raw terminal data (including escape sequences)
}terminal:resize
Resize a terminal. The PTY is resized to match.
interface TerminalResizeMessage {
type: 'terminal:resize';
terminalId: string;
cols: number;
rows: number;
}terminal:kill
Kill a terminal process.
interface TerminalKillMessage {
type: 'terminal:kill';
terminalId: string;
}terminal:list (request)
Request the list of active terminals for the current session.
interface TerminalListMessage {
type: 'terminal:list';
}Server → Client
auth:ok
Authentication succeeded. Save the sessionId for resume.
interface AuthOkMessage {
type: 'auth:ok';
sessionId: string; // UUID — use this for auth:resume
}auth:fail
Authentication failed. The connection is closed after this message.
interface AuthFailMessage {
type: 'auth:fail';
reason: string;
// "invalid_token" — token doesn't exist, expired, or already used
// "invalid_session" — session ID not found
// "auth_timeout" — 10s timeout exceeded
}terminal:created
A new terminal was successfully spawned.
interface TerminalCreatedMessage {
type: 'terminal:created';
terminal: TerminalInfo;
}
interface TerminalInfo {
id: string; // UUID
pid: number; // OS process ID
shell: string; // e.g. "/bin/zsh"
cols: number;
rows: number;
cwd: string; // Working directory
createdAt: number; // Unix timestamp (ms)
}terminal:output
Output data from a terminal. This is the primary data channel.
interface TerminalOutputMessage {
type: 'terminal:output';
terminalId: string;
data: string; // Raw terminal output (includes ANSI codes)
}terminal:exited
A terminal process has exited.
interface TerminalExitedMessage {
type: 'terminal:exited';
terminalId: string;
exitCode: number;
}terminal:list (response)
List of active terminals. Sent in response to a terminal:list request, and also automatically on session resume.
interface TerminalListResponseMessage {
type: 'terminal:list';
terminals: TerminalInfo[];
}error
A general error message.
interface ErrorMessage {
type: 'error';
message: string;
code?: string; // e.g. "spawn_failed"
}Message Flow
Typical connection lifecycle:
Client Server
│ │
│──── WebSocket connect ───────▶│
│ │
│──── auth { token } ──────────▶│
│◀──── auth:ok { sessionId } ───│
│ │
│──── terminal:create ─────────▶│
│◀──── terminal:created ────────│
│ │
│──── terminal:input ──────────▶│ (user types)
│◀──── terminal:output ─────────│ (pty responds)
│◀──── terminal:output ─────────│
│ │
│──── terminal:resize ─────────▶│ (window resized)
│ │
│──── terminal:kill ───────────▶│
│◀──── terminal:exited ─────────│
│ │Session Resume Flow
Client Server
│ │
│──── WebSocket connect ───────▶│
│ │
│──── auth:resume { sid } ─────▶│
│◀──── auth:ok { sessionId } ───│
│◀──── terminal:list ───────────│ (active terminals)
│◀──── terminal:output ─────────│ (scrollback replay)
│◀──── terminal:output ─────────│ (scrollback replay)
│ │
│ (terminals restored) │