ADR-166: WebSocket Protocol for Browser IDE - Sidecar Communication
Status: Proposed Date: 2026-02-09 Author: Claude (Opus 4.6) Deciders: Hal Casteel, Engineering Team Tags: protocol, websocket, browser-ide, sidecar
Context
The CODITECT Browser IDE requires a real-time bidirectional communication channel between the WASM client in the browser and the native sidecar process. This channel must support:
- Agent streaming - Token-by-token LLM responses (high throughput, low latency)
- Terminal I/O - Raw byte streams for PTY (latency-critical)
- File operations - Large file content transfers (throughput-critical)
- Tool use events - Structured agent tool calls and results (reliability-critical)
- Diagnostics - LSP-like diagnostics pushed from sidecar (periodic)
We must choose a protocol and wire format for this communication.
Decision
Use WebSocket with MessagePack binary framing over two dedicated connections:
Connection 1: IDE Channel (ws://localhost:42424/ws)
- Agent messages, file operations, completions, search, diagnostics
- MessagePack binary frames for efficiency
- Request-response correlation via UUID
idfield - Server-initiated push for diagnostics and agent streaming
Connection 2: Terminal Channel (ws://localhost:42424/ws/terminal)
- Raw binary frames for PTY I/O
- Text frames for control messages (resize, close)
- One WebSocket per terminal session
Wire Format
MessagePack envelope:
{
"id": "uuid-v4", // Request correlation
"type": "AgentChat", // Message type enum
"ts": 1707436800000, // Unix millis
"payload": { ... } // Type-specific data
}
Reconnection Strategy
- Heartbeat: client sends Ping every 15s, expects Pong within 5s
- On disconnect: exponential backoff (1s, 2s, 4s, 8s, max 30s)
- On reconnect: send
Reconnect{session_id}to resume agent state - Session state persisted in SQLite, survives sidecar restart
Alternatives Considered
Alternative 1: HTTP/2 + SSE
Use HTTP/2 for requests, Server-Sent Events for streaming responses.
Rejected because:
- SSE is unidirectional (server-to-client only)
- Terminal I/O requires bidirectional binary streaming
- Two separate transports (HTTP + SSE) add complexity
- No standard reconnection protocol for SSE
Alternative 2: gRPC-Web
Use gRPC-Web with Protocol Buffers.
Rejected because:
- Requires Envoy proxy or grpc-web-proxy for browser compatibility
- Complex tooling overhead for a localhost connection
- Protobuf code generation adds build complexity
- MessagePack is more flexible for evolving schemas
Alternative 3: JSON over WebSocket
Use JSON text frames instead of MessagePack binary frames.
Rejected as default because:
- 2-3x larger payload size than MessagePack
- Slower serialization/deserialization
- Retained as fallback for debugging (
?format=jsonquery parameter)
Alternative 4: WebTransport (HTTP/3)
Use WebTransport for multiplexed streams.
Rejected because:
- Not universally supported in browsers (2026 coverage ~85%)
- Requires HTTPS/TLS for localhost (self-signed cert management)
- Overkill for localhost communication
- Could revisit for cloud deployment
Consequences
Positive
- Single WebSocket connection for IDE operations (simple lifecycle)
- MessagePack is 30-50% smaller than JSON, faster to parse
- Separate terminal WebSocket isolates high-frequency PTY I/O
- UUID correlation enables concurrent requests without head-of-line blocking
- Reconnection with session resume prevents data loss
Negative
- MessagePack requires library in both Rust (rmp-serde) and TypeScript (msgpack-lite)
- Binary frames harder to debug than JSON (mitigated by JSON fallback mode)
- Two WebSocket connections per browser tab
Protocol Evolution
- Version byte in frame header allows future format changes
- New message types can be added without breaking existing clients
- Payload schema is flexible JSON/MessagePack (no rigid protobuf schema)
Message Type Catalog
Client -> Server (22 types)
| Category | Types |
|---|---|
| Session | Authenticate, Ping, Reconnect |
| Agent | AgentChat, AgentCancel, AgentUndo |
| File | FileOpen, FileEdit, FileSave, FileList, FileCreate, FileDelete |
| Terminal | TerminalCreate, TerminalInput, TerminalResize, TerminalClose |
| Completion | InlineComplete |
| Search | SearchFiles, SearchSymbols, SearchRepoMap |
| Config | GetConfig, SetConfig |
Server -> Client (18 types)
| Category | Types |
|---|---|
| Session | Authenticated, Pong, Error, SessionResumed |
| Agent | AgentThinking, AgentToolUse, AgentToolResult, AgentStreamChunk, AgentComplete |
| File | FileContent, FileTree, DiagnosticUpdate |
| Terminal | TerminalCreated, TerminalOutput, TerminalExited |
| Completion | InlineCompletionResult |
| Search | SearchResults |
Related
- ADR-165: WASM Split Architecture
- ADR-169: Browser Terminal Emulation
- SDD:
docs/architecture/browser-ide/SDD-CODITECT-BROWSER-IDE.md