# VibeTunnel Codebase Map A comprehensive navigation guide for the VibeTunnel web terminal system. ## Project Overview VibeTunnel is a web-based terminal multiplexer with distributed architecture support. It provides: - PTY-based terminal sessions via node-pty - Real-time terminal streaming via SSE (asciinema cast files) - Binary-optimized buffer synchronization (current viewport via WebSocket) - Distributed HQ/remote server architecture - Web UI with full terminal emulation - Push notifications for terminal bell events - Multi-method authentication (SSH keys, JWT, PAM) ## Directory Structure ``` web/ ├── src/ │ ├── server/ # Node.js Express server │ │ ├── middleware/ # Auth and other middleware │ │ ├── pty/ # PTY management │ │ ├── routes/ # API endpoints │ │ ├── services/ # Core services │ │ ├── server.ts # Main server implementation │ │ └── fwd.ts # CLI forwarding tool │ ├── client/ # Lit-based web UI │ │ ├── assets/ # Static files (fonts, icons, html) │ │ ├── components/ # UI components │ │ ├── services/ # Client services │ │ └── utils/ # Client utilities │ ├── test/ # Test files │ └── cli.ts # Main entry point ├── scripts/ # Build scripts └── public/ # Built static assets (generated) ``` ## Server Architecture (`src/server/`) ### Core Components #### Entry Points - `cli.ts` (1-62): Main entry point, routes to server or forward mode - `server/server.ts` (1-953): Core server implementation with Express app factory - CLI parsing (132-236): Extensive configuration options - Server modes (432-444): Normal, HQ, Remote initialization - WebSocket upgrade (564-677): Authentication and buffer streaming - Graceful shutdown (888-944): Cleanup intervals and service termination ### Authentication (`middleware/auth.ts`) - Multi-method authentication (1-159) - SSH key authentication with Ed25519 support - Basic auth (username/password) - Bearer token for HQ↔Remote communication - JWT tokens for session persistence - Local bypass for localhost connections (24-48, 68-87) - Query parameter token support for EventSource ### Session Management #### PTY Manager (`pty/pty-manager.ts`) - Session creation (78-163): Spawns PTY processes with node-pty - **Automatic alias resolution** (191-204): Uses `ProcessUtils.resolveCommand()` - Terminal resize handling (63-157): Dimension synchronization - Control pipe support using file watching on all platforms - Bell event emission for push notifications - Clean termination with SIGTERM→SIGKILL escalation #### Process Utils (`pty/process-utils.ts`) - `resolveCommand()` (242-378): Detects if command exists in PATH - Uses `which` (Unix) or `where` (Windows) to check existence - Returns appropriate shell command for aliases/builtins - Sources shell config files for proper alias support - `getUserShell()` (384-484): Determines user's preferred shell - Checks `$SHELL` environment variable first - Platform-specific fallbacks (pwsh/cmd on Windows, zsh/bash on Unix) - Interactive shell detection (220-235): Auto-adds `-i -l` flags #### Session Manager (`pty/session-manager.ts`) - Session persistence in `~/.vibetunnel/control/` - Filesystem-based session discovery - Zombie session cleanup #### Terminal Manager (`services/terminal-manager.ts`) - Headless xterm.js for server-side state - Binary buffer snapshot generation - Watches asciinema cast files and applies to terminal - Debounced buffer change notifications ### API Routes (`routes/`) #### Sessions (`sessions.ts`) - `GET /api/sessions` (51-124): List all sessions - Returns array with `source: 'local' | 'remote'` - HQ mode: Aggregates from all remote servers - `POST /api/sessions` (126-265): Create session - Body: `{ command, workingDir?, name?, remoteId?, spawn_terminal? }` - Returns: `{ sessionId: string, message?: string }` - `GET /api/sessions/:id` (369-410): Get session info - `DELETE /api/sessions/:id` (413-467): Kill session - `DELETE /api/sessions/:id/cleanup` (470-518): Clean session files - `POST /api/cleanup-exited` (521-598): Clean all exited sessions #### Session I/O - `POST /api/sessions/:id/input` (874-950): Send keyboard input - Body: `{ text: string }` OR `{ key: SpecialKey }` - `POST /api/sessions/:id/resize` (953-1025): Resize terminal - Body: `{ cols: number, rows: number }` - `POST /api/sessions/:id/reset-size` (1028-1083): Reset to native size #### Session Output - `GET /api/sessions/:id/stream` (723-871): SSE streaming - Streams asciinema v2 format with custom exit event - Replays existing content, then real-time streaming - `GET /api/sessions/:id/buffer` (662-721): Binary buffer snapshot - `GET /api/sessions/:id/text` (601-659): Plain text output - Optional `?styles` for markup: `[style fg="15" bold]text[/style]` #### Activity Monitoring - `GET /api/sessions/activity` (268-324): All sessions activity - `GET /api/sessions/:id/activity` (327-366): Single session activity - Returns: `{ isActive: boolean, timestamp: string, session: SessionInfo }` #### Remotes (`remotes.ts`) - HQ Mode Only - `GET /api/remotes` (19-33): List registered servers - `POST /api/remotes/register` (36-64): Register remote - `DELETE /api/remotes/:id` (67-84): Unregister remote - `POST /api/remotes/:id/refresh-sessions` (87-152): Refresh session list #### Logs (`logs.ts`) - `POST /api/logs/client` (21-53): Client log submission - `GET /api/logs/raw` (56-74): Stream raw log file - `GET /api/logs/info` (77-102): Log file metadata - `DELETE /api/logs/clear` (105-119): Clear log file ### Binary Buffer Protocol **Note**: "Buffer" refers to the current terminal viewport without scrollback - used for terminal previews. #### Format (`terminal-manager.ts:361-555`) ``` Header (32 bytes): - Magic: 0x5654 "VT" (2 bytes) - Version: 0x01 (1 byte) - Flags: reserved (1 byte) - Dimensions: cols, rows (8 bytes) - Cursor: X, Y, viewport (12 bytes) - Reserved (4 bytes) Rows: 0xFE=empty, 0xFD=content Cells: Variable-length with type byte ``` ### SSE Streaming and Asciinema Files #### Asciinema Writer (`pty/asciinema-writer.ts`) - Writes cast files to `~/.vibetunnel/control/[sessionId]/stream-out` - Format: - Standard: `[timestamp, "o", output]` for terminal output - Standard: `[timestamp, "i", input]` for user input - Standard: `[timestamp, "r", "colsxrows"]` for resize events - **Custom**: `["exit", exitCode, sessionId]` when process terminates #### SSE Streaming (`routes/sessions.ts:723-871`) - Real-time streaming of asciinema cast files - Replays existing content with zeroed timestamps - Watches for new content and streams incrementally - Heartbeat every 30 seconds ### WebSocket (`services/buffer-aggregator.ts`) - Client connections (30-87): Authentication and subscription - Message handling (88-127): Subscribe/unsubscribe/ping - Binary protocol (156-209): `[0xBF][ID Length][Session ID][Buffer Data]` - Local and remote session proxy support ### Activity Monitoring (`services/activity-monitor.ts`) - Monitors `stream-out` file size changes (143-146) - 100ms check interval (41-44) - 500ms inactivity timeout (209-212) - Persists to `activity.json` per session (220-245) - Works for all sessions regardless of creation method ### HQ Mode Components #### Remote Registry (`services/remote-registry.ts`) - Health checks every 15s (150-187) - Session ownership tracking (91-148) - Bearer token authentication - Automatic unhealthy remote removal #### HQ Client (`services/hq-client.ts`) - Registration with HQ (40-90) - Unique ID generation with UUID v4 - Graceful unregistration on shutdown (92-113) ### Additional Services #### Push Notifications (`services/push-notification-service.ts`) - Web Push API integration (64-363) - Subscription management in `~/.vibetunnel/notifications/` - Bell event notifications (231-247) - Automatic expired subscription cleanup #### Bell Event Handler (`services/bell-event-handler.ts`) - Processes terminal bell events (59-182) - Integrates with push notifications - Includes process context in notifications #### Authentication Service (`services/auth-service.ts`) - SSH key authentication (144-159, 201-271) - Ed25519 signature verification - Challenge-response system - Checks `~/.ssh/authorized_keys` - Password authentication (105-120) - PAM authentication fallback (184-196) - JWT token management (176-180) #### Control Directory Watcher (`services/control-dir-watcher.ts`) - Monitors external session changes (20-175) - HQ mode integration (116-163) - Detects new/removed sessions ### Utilities #### Logger (`utils/logger.ts`) - Structured logging with file and console output (1-186) - Color-coded console with chalk - Log levels: log, warn, error, debug - File output to `~/.vibetunnel/log.txt` - Debug mode via `VIBETUNNEL_DEBUG` #### VAPID Manager (`utils/vapid-manager.ts`) - Auto-generates VAPID keys for push notifications (20-331) - Stores in `~/.vibetunnel/vapid/keys.json` - Key rotation support ## Client Architecture (`src/client/`) ### Core Components #### Entry Points - `app-entry.ts` (1-28): Main entry, initializes Monaco and push notifications - `test-entry.ts`: Test terminals entry - `styles.css`: Global Tailwind styles #### Main Application (`app.ts`) - Lit-based SPA (15-1200+): `` - URL-based routing with `?session=` - Global keyboard handlers (Cmd+O, Escape) - View management: auth/list/session - **Events fired**: - `toggle-nav`, `navigate-to-list`, `error`, `success`, `navigate` ### Component Event Architecture ``` vibetunnel-app ├── app-header (navigation, controls) ├── session-list (when view='list') │ └── session-card (per session) │ └── vibe-terminal-buffer (terminal preview) ├── session-view (when view='session') │ ├── session-header │ ├── vibe-terminal (main terminal) │ ├── mobile-input-overlay │ ├── ctrl-alpha-overlay │ └── terminal-quick-keys ├── session-create-form (modal) ├── file-browser (modal) ├── unified-settings (modal) └── auth-login (when view='auth') ``` ### Terminal Components #### Terminal (`terminal.ts`) - Full xterm.js implementation (1-1000+) - Virtual scrolling (537-555) - Touch/momentum support - URL highlighting integration - **Events**: `terminal-ready`, `terminal-input`, `terminal-resize`, `url-clicked` #### VibeTunnelBuffer (`vibe-terminal-buffer.ts`) - Read-only terminal preview (25-268) - WebSocket buffer subscription - Auto-resizing - **Events**: `content-changed` #### SessionView (`session-view.ts`) - Full-screen terminal view (29-1331) - Manager architecture: - ConnectionManager: SSE streaming - InputManager: Keyboard/mouse - MobileInputManager: Mobile input - DirectKeyboardManager: Direct keyboard access - TerminalLifecycleManager: Terminal state - **Events**: `navigate-to-list`, `error`, `warning` ### Session Management Components #### SessionList (`session-list.ts`) - Grid/list layout (61-700+) - Hide/show exited sessions - Search and filtering - **Events**: `navigate-to-session`, `refresh`, `error`, `success` #### SessionCard (`session-card.ts`) - Individual session display (31-420+) - Live terminal preview - Activity detection - **Events**: `session-select`, `session-killed`, `session-kill-error` #### SessionCreateForm (`session-create-form.ts`) - Modal dialog (27-381) - Command input with working directory - Native terminal spawn option - **Events**: `session-created`, `cancel`, `error` ### UI Components #### AppHeader (`app-header.ts`) - Main navigation (15-280+) - Session status display - Theme toggle - **Events**: `toggle-nav`, `navigate-to-list`, `toggle-create-form` #### FileBrowser (`file-browser.ts`) - Filesystem navigation (48-665) - Git status display - Monaco editor preview - **Events**: `insert-path`, `open-in-editor`, `directory-selected` #### LogViewer (`log-viewer.ts`) - Real-time log display (1-432) - SSE-style polling - Level filtering - Search functionality ### Services #### BufferSubscriptionService (`buffer-subscription-service.ts`) - WebSocket client (30-87) - Binary protocol decoder (163-208) - Auto-reconnection with backoff - Per-session subscriptions #### PushNotificationService (`push-notification-service.ts`) - Service worker registration - Push subscription management - Notification action handling #### AuthClient (`auth-client.ts`) - Token management - Authentication state - API header generation ### Utils #### CastConverter (`cast-converter.ts`) - Asciinema v2 parser (31-82) - SSE stream handler (294-427) - Custom exit event support #### TerminalRenderer (`terminal-renderer.ts`) - Binary buffer decoder (279-424) - HTML generation from buffer - Style mapping #### URLHighlighter (`url-highlighter.ts`) - Multi-line URL detection - Protocol validation - Click event handling ## Forward Tool (`src/server/fwd.ts`) ### Purpose CLI tool for spawning PTY sessions using VibeTunnel infrastructure. ### Usage ```bash npx tsx src/fwd.ts [--session-id ] [args...] # Examples npx tsx src/fwd.ts claude --resume npx tsx src/fwd.ts --session-id abc123 bash -l ``` ### Key Features - Interactive terminal forwarding (43-195) - Automatic shell alias support via ProcessUtils - Session ID pre-generation support - Graceful cleanup on exit - Colorful output with chalk ### Integration Points - Uses central PTY Manager (78-82) - Control pipe handling delegated to PTY Manager - Terminal resize synchronization (148-163) - Raw mode for proper input capture (166-172) ## Build System ### Main Build (`scripts/build.js`) - Asset copying (7-121) - CSS compilation with Tailwind - Client bundling with esbuild - Server TypeScript compilation - Native executable creation ### Native Binary (`scripts/build-native.js`) - Node.js SEA integration (1-537) - node-pty patching for compatibility (82-218) - Outputs: - `native/vibetunnel`: Main executable - `native/pty.node`: Terminal emulation - `native/spawn-helper`: Process spawning (macOS) - `native/authenticate_pam.node`: PAM auth ## Key Files Quick Reference ### Server Core - `src/cli.ts`: Main entry point - `src/server/server.ts`: Server implementation - `src/server/middleware/auth.ts`: Authentication - `src/server/routes/sessions.ts`: Session API - `src/server/pty/pty-manager.ts`: PTY management - `src/server/services/terminal-manager.ts`: Terminal state - `src/server/services/activity-monitor.ts`: Activity tracking - `src/server/fwd.ts`: CLI forwarding tool ### Client Core - `src/client/app-entry.ts`: Entry point - `src/client/app.ts`: Main SPA - `src/client/components/terminal.ts`: Terminal renderer - `src/client/components/session-view.ts`: Session viewer - `src/client/services/buffer-subscription-service.ts`: WebSocket - `src/client/utils/cast-converter.ts`: Asciinema parser ### Configuration - Environment: `PORT`, `VIBETUNNEL_USERNAME`, `VIBETUNNEL_PASSWORD`, `VIBETUNNEL_DEBUG` - CLI: `--port`, `--username`, `--password`, `--hq`, `--hq-url`, `--name` - Debug logging: Set `VIBETUNNEL_DEBUG=1` or `true` ### Protocols - REST API: Session CRUD, terminal I/O - SSE: Real-time asciinema streaming - WebSocket: Binary buffer updates - Control pipes: External session control ### Session Data Storage Each session has a directory in `~/.vibetunnel/control/[sessionId]/`: - `session.json`: Session metadata - `stream-out`: Asciinema cast file - `stdin`: Input pipe - `control`: Control pipe - `activity.json`: Activity status ## Development Notes ### Recent Improvements - Push notification support for terminal bells - Multi-method authentication (SSH keys, JWT, PAM) - Unified logging infrastructure with style guide - Activity monitoring for all sessions - Control directory watcher for external sessions - Improved TypeScript types (no "as any") - Colorful CLI output with chalk - Auto-generation of security keys (VAPID) ### Testing - Unit tests: `pnpm test` - E2E tests: `pnpm run test:e2e` - Vitest configuration with coverage ### Key Dependencies - node-pty: Cross-platform PTY - @xterm/headless: Terminal emulation - Lit: Web components - Express: HTTP server - web-push: Push notifications - TailwindCSS: Styling