shellphone 0.2.0

Pipe CLI commands to a secure mobile web terminal
---
id: websocket-protocol
title: WebSocket protocol
altitude: 2
topics:
- server
- frontend
relations:
- type: refines
  target: http-server
- type: references
  target: frontend-terminal
summary: 'The typed JSON message protocol over WebSocket: ClientMessage and ServerMessage.'
---

# WebSocket protocol

`src/protocol.rs` defines the typed message format used over the WebSocket connection. Binary frames carry raw PTY output; text frames carry JSON control messages.

## ClientMessage (browser → server)

```rust
#[serde(tag = "type", rename_all = "snake_case")]
enum ClientMessage {
    Input { data: String },
    Resize { cols: u16, rows: u16 },
}
```

- **Input:** keystroke data from `term.onData`. Serialized as `{"type": "input", "data": "ls\n"}`.
- **Resize:** terminal dimensions after `fitAddon.fit()`. Serialized as `{"type": "resize", "cols": 120, "rows": 40}`.

## ServerMessage (server → browser)

```rust
#[serde(tag = "type", rename_all = "snake_case")]
enum ServerMessage {
    RefreshToken { token: String },
    Exit { code: Option<u32> },
}
```

- **RefreshToken:** sent once after successful initial authentication. The client stores the token in localStorage for reconnection.
- **Exit:** sent when the child process terminates. The client shows the exit code and stops reconnection attempts.

## Design decision

PTY output stays as binary WebSocket frames for performance — no JSON wrapping overhead for high-throughput terminal output. Control messages are infrequent and benefit from structured typing.