Skip to main content

Protocol Specifications

Terminal Transport (WebSocket v3)

VibeTunnel uses a single WebSocket endpoint for terminal transport, multiplexing sessions over binary frames.

Connection Establishment

const ws = new WebSocket('ws://localhost:4020/ws?token=JWT_TOKEN');
ws.binaryType = 'arraybuffer';

Subscriptions

  • Subscribe per session: send a v3 SUBSCRIBE frame with sessionId + flags (Stdout, Snapshots, Events).
  • Global events: use an empty sessionId and the Events flag.
Source of truth: docs/websocket.md and web/src/shared/ws-v3.ts.

Error Codes

CodeMeaningAction
1000Normal closureSession ended
1001Going awayServer shutdown
1003Unsupported dataProtocol error
1008Policy violationAuth failed
1011Server errorRetry connection

PTY Protocol

Process Spawning

interface PTYOptions {
  name: string;
  cols: number;
  rows: number;
  cwd: string;
  env: Record<string, string>;
  command: string;
  args: string[];
}

Control Sequences

SequencePurposeExample
\x03SIGINT (Ctrl+C)Interrupt process
\x04EOF (Ctrl+D)End input
\x1aSIGTSTP (Ctrl+Z)Suspend process
\x1cSIGQUIT (Ctrl+)Quit process
\x7fBackspaceDelete character

Terminal Modes

// Raw mode for full control
pty.setRawMode(true);

// Canonical mode for line editing
pty.setRawMode(false);

Session Recording Protocol

Asciinema v2 Format

Header:
{
  "version": 2,
  "width": 80,
  "height": 24,
  "timestamp": 1704067200,
  "env": {
    "SHELL": "/bin/zsh",
    "TERM": "xterm-256color"
  }
}
Events:
[0.123456, "o", "$ ls -la\r\n"]
[0.234567, "o", "total 48\r\n"]
[1.345678, "i", "c"]
[1.456789, "i", "l"]
[1.567890, "i", "e"]
Event types:
  • o: Output from terminal
  • i: Input from user
  • r: Terminal resize

Recording Storage

~/.vibetunnel/recordings/
├── session-uuid-1.cast
├── session-uuid-2.cast
└── metadata.json

HTTP Protocol

Request Headers

Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
X-Session-ID: <SESSION_UUID>
X-Client-Version: 1.0.0

Response Headers

X-Request-ID: <REQUEST_UUID>
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1704067200

Status Codes

CodeMeaningUsage
200OKSuccessful operation
201CreatedSession created
204No ContentSession deleted
400Bad RequestInvalid parameters
401UnauthorizedAuth required
404Not FoundSession not found
409ConflictSession exists
429Too Many RequestsRate limited
500Server ErrorInternal error

Terminal Transport (WebSocket v3)

VibeTunnel uses a single WebSocket endpoint for terminal transport:
  • Endpoint: GET /ws (upgrade)
  • Binary framing: "VT" magic + version + type + sessionId + payload
  • Multiplexing: one socket can carry multiple sessions
  • Subscriptions: flags for stdout, snapshots, events
Details: docs/websocket.md.

Authentication Protocol

JWT Token Structure

{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "user-id",
    "iat": 1704067200,
    "exp": 1704153600,
    "sessionId": "session-uuid"
  }
}

Token Refresh Flow

1. Client token expires in 5 minutes
2. Client requests refresh: POST /api/auth/refresh
3. Server validates refresh token
4. Server issues new access token
5. Client updates Authorization header

See Also