VibeTunnel Socket Protocol

Overview

VibeTunnel uses a binary framed message protocol over Unix domain sockets for all inter-process communication (IPC). This protocol replaces the previous file-based IPC system, providing better performance, real-time updates, and cleaner architecture.

Architecture

Components

  1. PTY Manager (Server)
    • Creates Unix domain socket at {session_dir}/ipc.sock
    • Handles multiple client connections
    • Manages PTY process I/O
    • Tracks session state and Claude status
  2. Socket Client (fwd.ts and other clients)
    • Connects to session’s Unix socket
    • Sends stdin data and control commands
    • Receives status updates and errors
    • Supports auto-reconnection

Socket Path

  • Location: {control_dir}/{session_id}/ipc.sock
  • Example: /tmp/vt-1234567890/a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6/ipc.sock
Important: macOS has a 104 character limit for Unix socket paths (103 usable). Keep control directories short to avoid EINVAL errors.

Message Format

Frame Structure

+--------+--------+--------+--------+--------+----------------+
| Type   | Length                           | Payload        |
| 1 byte | 4 bytes (big-endian uint32)      | Length bytes   |
+--------+--------+--------+--------+--------+----------------+
  • Type: Single byte indicating message type
  • Length: 32-bit unsigned integer in big-endian format
  • Payload: Variable-length data (format depends on message type)

Message Types

TypeValueDirectionDescription
STDIN_DATA0x01Client → ServerTerminal input data
CONTROL_CMD0x02Client → ServerControl commands (resize, kill)
STATUS_UPDATE0x03BothActivity status updates
HEARTBEAT0x04BothConnection health check
ERROR0x05Server → ClientError messages

Message Payloads

STDIN_DATA (0x01)

  • Payload: UTF-8 encoded string
  • Example: "ls -la\n"

CONTROL_CMD (0x02)

  • Payload: JSON object
  • Commands:
    // Resize terminal
    { "cmd": "resize", "cols": 120, "rows": 40 }
    
    // Kill process
    { "cmd": "kill", "signal": "SIGTERM" }
    
    // Reset terminal size
    { "cmd": "reset-size" }
    

STATUS_UPDATE (0x03)

  • Payload: JSON object
  • Format:
    {
      "app": "claude",
      "status": "✻ Thinking (5s, ↑2.5k tokens)",
      // Optional extra fields
      "tokens": 2500,
      "duration": 5000
    }
    
  • Broadcast: Server broadcasts status updates to all connected clients

HEARTBEAT (0x04)

  • Payload: Empty (0 bytes)
  • Behavior:
    • Clients can send periodic heartbeats
    • Server echoes heartbeats back
    • Used to detect connection health

ERROR (0x05)

  • Payload: JSON object
  • Format:
    {
      "code": "SESSION_NOT_FOUND",
      "message": "Session does not exist",
      "details": { /* optional */ }
    }
    

Error Codes

CodeDescriptionDetails
SESSION_NOT_FOUNDThe requested session does not existSession ID is invalid or session has been terminated
MESSAGE_PROCESSING_ERRORFailed to process incoming messageMalformed message, invalid JSON, or internal processing error
INVALID_OPERATIONOperation not valid for session typee.g., reset-size on in-memory session
CONTROL_MESSAGE_FAILEDFailed to send control messageUnable to communicate with PTY process
RESET_SIZE_FAILEDFailed to reset terminal sizeError during size reset operation
CONNECTION_LIMITToo many concurrent connectionsServer connection limit reached
PAYLOAD_TOO_LARGEMessage payload exceeds size limitPayload larger than maximum allowed size
INVALID_MESSAGE_TYPEUnknown or unsupported message typeClient sent unrecognized message type
MALFORMED_FRAMEInvalid message frame structureMessage framing protocol violation
Example Error Response:
{
  "code": "MESSAGE_PROCESSING_ERROR",
  "message": "Failed to parse control command",
  "details": {
    "error": "Unexpected token } in JSON at position 42",
    "messageType": 2
  }
}

Client Implementation

Connection Flow

  1. Connect to Unix socket at {session_dir}/ipc.sock
  2. Receive any initial status updates from server
  3. Send messages as needed
  4. Handle incoming messages asynchronously
  5. Reconnect automatically on disconnection (optional)

Example Usage

import { VibeTunnelSocketClient } from './socket-client.js';

// Connect to session
const client = new VibeTunnelSocketClient('/path/to/session/ipc.sock', {
  autoReconnect: true,
  heartbeatInterval: 30000 // 30 seconds
});

// Listen for events
client.on('connect', () => console.log('Connected'));
client.on('status', (status) => console.log('Status:', status));
client.on('error', (err) => console.error('Error:', err));

// Connect and use
await client.connect();

// Send terminal input
client.sendStdin('echo "Hello, World!"\n');

// Resize terminal
client.resize(120, 40);

// Send Claude status
client.sendStatus('claude', '✻ Thinking', { tokens: 1000 });

// Disconnect when done
client.disconnect();

Server Implementation

Socket Server Setup

The PTY manager creates a Unix domain socket for each session:
// Create socket server
const server = net.createServer((client) => {
  const parser = new MessageParser();
  
  // Send initial status if available
  if (claudeStatus) {
    client.write(frameMessage(MessageType.STATUS_UPDATE, claudeStatus));
  }
  
  // Handle incoming messages
  client.on('data', (chunk) => {
    parser.addData(chunk);
    
    for (const { type, payload } of parser.parseMessages()) {
      handleMessage(type, payload, client);
    }
  });
});

// Listen on socket
server.listen(socketPath);

Message Handling

The server processes messages based on type:
  • STDIN_DATA: Write to PTY process
  • CONTROL_CMD: Handle resize/kill commands
  • STATUS_UPDATE: Store status and broadcast to other clients
  • HEARTBEAT: Echo back to sender

Protocol Features

Message Framing

The protocol handles:
  • Partial messages: TCP may split messages across packets
  • Multiple messages: TCP may combine messages in one packet
  • Large payloads: No practical size limit (up to 4GB per message)
  • Binary safety: Handles null bytes and non-UTF8 data

Connection Management

  • Multiple clients: Server supports multiple simultaneous connections
  • Auto-reconnection: Clients can automatically reconnect on failure
  • Heartbeats: Optional periodic heartbeats for connection health
  • Graceful shutdown: Proper cleanup of resources

Status Broadcasting

When a client sends a STATUS_UPDATE:
  1. Server stores the status in memory
  2. Server broadcasts to all other connected clients
  3. New clients receive current status on connection

Migration from File-Based IPC

Previous System

  • Control commands via {session_dir}/control-pipe file
  • Activity updates via {session_dir}/activity.json file
  • Required file watching and polling

New System

  • All communication through single Unix socket
  • Real-time bidirectional messaging
  • No file watching or polling needed
  • Better performance and cleaner architecture

Error Handling

Connection Errors

  • ENOENT: Socket file doesn’t exist (session not found)
  • ECONNREFUSED: Server not listening (session crashed)
  • EINVAL: Socket path too long (macOS limit)

Protocol Errors

  • Malformed messages are logged and ignored
  • Server sends ERROR message for processing failures
  • Clients should handle disconnections gracefully

Performance Considerations

  1. Message Size: Keep messages reasonably sized (< 1MB)
  2. Heartbeat Interval: 30-60 seconds is typical
  3. Reconnect Delay: 1-5 seconds between attempts
  4. Socket Backlog: Default is sufficient for typical usage

Security Notes

  • Sockets are created with 0666 permissions (world-writable)
  • Rely on directory permissions for access control
  • No authentication or encryption (local use only)
  • Validate all JSON payloads before processing

Implementation Files

  • Protocol: src/server/pty/socket-protocol.ts
  • Client: src/server/pty/socket-client.ts
  • Server: src/server/pty/pty-manager.ts (setupIPCSocket method)
  • Tests: src/test/unit/socket-*.test.ts, src/test/integration/socket-*.test.ts

Future Enhancements

Potential improvements to consider:
  • Message compression for large payloads
  • Authentication for multi-user systems
  • Encryption for sensitive data
  • Request/response correlation IDs
  • Batch message support