mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-04 11:05:53 +00:00
402 lines
No EOL
14 KiB
Markdown
402 lines
No EOL
14 KiB
Markdown
# VibeTunnel Web Architecture Specification
|
|
|
|
This document provides a comprehensive map of the VibeTunnel web application architecture, including server components, client structure, API specifications, and protocol details. Updated: 2025-07-01
|
|
|
|
## Key Files Quick Reference
|
|
|
|
### Server Core
|
|
- **Entry Point**: `src/server/server.ts:912` - `startVibeTunnelServer()`
|
|
- **App Creation**: `src/server/server.ts:330` - `createApp()`
|
|
- **Configuration**: `src/server/server.ts:57` - `Config` interface
|
|
- **CLI Entry**: `src/server/cli.ts:51-56` - `vibetunnel fwd` command
|
|
|
|
### Authentication
|
|
- **Service**: `src/server/services/auth-service.ts:144-271` - SSH key verification
|
|
- **Middleware**: `src/server/middleware/auth.ts:20-105` - JWT validation
|
|
- **Routes**: `src/server/routes/auth.ts:20-178` - Auth endpoints
|
|
|
|
### Session Management
|
|
- **PTY Manager**: `src/server/pty/pty-manager.ts:57` - Session Map
|
|
- **Session Manager**: `src/server/pty/session-manager.ts:40-141` - Session lifecycle
|
|
- **Routes**: `src/server/routes/sessions.ts:134-1252` - Session API
|
|
|
|
### Real-time Communication
|
|
- **Binary Buffer**: `src/server/services/terminal-manager.ts:378-574` - Buffer encoding
|
|
- **WebSocket Server**: `src/server/services/buffer-aggregator.ts:44-344` - Buffer streaming
|
|
- **Input Handler**: `src/server/routes/websocket-input.ts:156-164` - Input protocol
|
|
|
|
### Client Core
|
|
- **Entry Point**: `src/client/app-entry.ts:1-28` - App initialization
|
|
- **Main Component**: `src/client/app.ts:44-1355` - `<vibetunnel-app>`
|
|
- **Terminal**: `src/client/components/terminal.ts:23-1567` - xterm.js wrapper
|
|
|
|
## Server Architecture
|
|
|
|
### Main Server (`src/server/server.ts`)
|
|
|
|
The server provides a comprehensive API for terminal session management with support for distributed deployments.
|
|
|
|
**Configuration Options**:
|
|
- `port`: Server port (default: 4020)
|
|
- `bind`: Bind address (default: 127.0.0.1)
|
|
- `isHQMode`: Run as headquarters server
|
|
- `hqUrl/hqUsername/hqPassword`: Remote server registration
|
|
- `enableSSHKeys`: Enable SSH key authentication
|
|
- `noAuth`: Disable all authentication
|
|
|
|
**Key Services**:
|
|
- Authentication (JWT + SSH keys)
|
|
- Session management (PTY processes)
|
|
- WebSocket communication (binary buffers + input)
|
|
- File system operations
|
|
- Push notifications
|
|
- Activity monitoring
|
|
|
|
### Authentication System
|
|
|
|
**Supported Methods**:
|
|
1. **SSH Key Authentication** (`src/server/routes/auth.ts:52`)
|
|
- Challenge-response with Ed25519 signatures
|
|
- Verifies against `~/.ssh/authorized_keys`
|
|
2. **Password Authentication** (`src/server/routes/auth.ts:101`)
|
|
- PAM authentication or environment variables
|
|
3. **Bearer Token** (HQ mode)
|
|
- For server-to-server communication
|
|
4. **Local Bypass** (optional)
|
|
- Localhost connections with optional token
|
|
|
|
**JWT Token Flow**:
|
|
1. Client requests challenge from `/api/auth/challenge`
|
|
2. Server generates random challenge
|
|
3. Client signs challenge and sends to `/api/auth/ssh-key`
|
|
4. Server verifies signature and returns JWT token
|
|
|
|
### Session Management
|
|
|
|
**Session Lifecycle**:
|
|
1. **Creation** (`src/server/routes/sessions.ts:134`):
|
|
- Spawns PTY process using node-pty
|
|
- Creates session directory in `~/.vibetunnel/control/`
|
|
- Saves metadata to `session.json`
|
|
|
|
2. **Tracking**:
|
|
- In-memory: `PtyManager.sessions` Map
|
|
- On-disk: Session directories with stdout/stdin files
|
|
|
|
3. **Cleanup** (`src/server/pty/session-manager.ts:297`):
|
|
- Automatic cleanup of exited sessions
|
|
- 5-minute cleanup interval
|
|
- Zombie process detection
|
|
|
|
**Control Directory Structure**:
|
|
```
|
|
~/.vibetunnel/control/
|
|
├── [sessionId]/
|
|
│ ├── session.json # Session metadata
|
|
│ ├── stdout # Terminal output
|
|
│ ├── stdin # Terminal input log
|
|
│ ├── activity.json # Activity status
|
|
│ └── ipc.sock # Unix socket for IPC
|
|
```
|
|
|
|
## Client Architecture
|
|
|
|
### Component Hierarchy
|
|
|
|
```
|
|
<vibetunnel-app> # Main app orchestrator
|
|
├── <auth-login> # Login form
|
|
├── <session-list> # Session listing
|
|
│ └── <session-card> # Individual session
|
|
├── <session-view> # Full-screen terminal
|
|
│ ├── <vibe-terminal> # xterm.js wrapper
|
|
│ └── <vibe-terminal-buffer> # Binary buffer renderer
|
|
└── <unified-settings> # Settings panel
|
|
```
|
|
|
|
### State Management
|
|
- Component-level state using LitElement's `@state()` decorator
|
|
- localStorage for persistent data (auth tokens, preferences)
|
|
- Event-driven communication between components
|
|
- No global state management library
|
|
|
|
### Services
|
|
|
|
**AuthClient** (`src/client/services/auth-client.ts`):
|
|
- Manages authentication state
|
|
- Handles SSH key and password auth
|
|
- Stores tokens in localStorage
|
|
|
|
**BufferSubscriptionService** (`src/client/services/buffer-subscription-service.ts`):
|
|
- WebSocket connection for binary terminal buffers
|
|
- Automatic reconnection with exponential backoff
|
|
- Multiplexed subscriptions per session
|
|
|
|
**WebSocketInputClient** (`src/client/services/websocket-input-client.ts`):
|
|
- Low-latency input transmission
|
|
- Fire-and-forget protocol
|
|
- Per-session connections
|
|
|
|
## API Specification
|
|
|
|
### REST Endpoints
|
|
|
|
#### Sessions
|
|
- `GET /api/sessions` - List all sessions
|
|
- `POST /api/sessions` - Create new session
|
|
- `GET /api/sessions/:id` - Get session info
|
|
- `DELETE /api/sessions/:id` - Kill session
|
|
- `POST /api/sessions/:id/input` - Send input
|
|
- `POST /api/sessions/:id/resize` - Resize terminal
|
|
- `GET /api/sessions/:id/stream` - SSE output stream
|
|
- `GET /api/sessions/:id/text` - Get text output
|
|
- `GET /api/sessions/:id/buffer` - Get binary buffer
|
|
- `GET /api/sessions/activity` - Get all activity
|
|
|
|
#### Authentication
|
|
- `POST /api/auth/challenge` - Request challenge
|
|
- `POST /api/auth/ssh-key` - SSH key auth
|
|
- `POST /api/auth/password` - Password auth
|
|
- `GET /api/auth/verify` - Verify token
|
|
- `GET /api/auth/config` - Get auth config
|
|
|
|
#### HQ Mode (Distributed)
|
|
- `GET /api/remotes` - List remote servers
|
|
- `POST /api/remotes/register` - Register remote
|
|
- `DELETE /api/remotes/:id` - Unregister remote
|
|
|
|
#### Git Integration
|
|
- `GET /api/worktrees` - List worktrees
|
|
- `POST /api/worktrees` - Create worktree
|
|
- `POST /api/worktrees/follow` - Enable/disable follow mode
|
|
- `GET /api/worktrees/follow` - Get follow mode status
|
|
- `POST /api/git/events` - Git hook notifications
|
|
|
|
### WebSocket Protocols
|
|
|
|
#### Binary Buffer Protocol (`/buffers`)
|
|
|
|
**Connection**: WebSocket with Bearer token authentication
|
|
|
|
**Client → Server Messages** (JSON):
|
|
```json
|
|
{ "type": "subscribe", "sessionId": "session_123" }
|
|
{ "type": "unsubscribe", "sessionId": "session_123" }
|
|
{ "type": "ping" }
|
|
```
|
|
|
|
**Server → Client Messages** (Binary):
|
|
```
|
|
[0xBF][ID Length (4 bytes)][Session ID (UTF-8)][Buffer Data]
|
|
```
|
|
|
|
**Buffer Data Format** (32-byte header + cells):
|
|
```
|
|
Header (32 bytes):
|
|
├── Magic: 0x5654 "VT" (2 bytes)
|
|
├── Version: 0x01 (1 byte)
|
|
├── Flags: reserved (1 byte)
|
|
├── Columns (4 bytes)
|
|
├── Rows (4 bytes)
|
|
├── ViewportY (4 bytes)
|
|
├── CursorX (4 bytes)
|
|
├── CursorY (4 bytes)
|
|
└── Reserved (4 bytes)
|
|
|
|
Row Encoding:
|
|
├── Empty rows: [0xFE][count]
|
|
└── Content rows: [0xFD][cell count (2 bytes)][cells...]
|
|
|
|
Cell Type Byte:
|
|
├── Bit 7: Has extended data
|
|
├── Bit 6: Is Unicode
|
|
├── Bit 5: Has foreground color
|
|
├── Bit 4: Has background color
|
|
├── Bit 3: Is RGB foreground
|
|
├── Bit 2: Is RGB background
|
|
└── Bits 1-0: Character type (00=space, 01=ASCII, 10=Unicode)
|
|
```
|
|
|
|
#### Input Protocol (`/ws/input`)
|
|
|
|
**Connection**: `ws://host/ws/input?sessionId=X&token=Y`
|
|
|
|
**Message Format**:
|
|
- Regular text: Sent as-is
|
|
- Special keys: `\x00key_name\x00`
|
|
|
|
### Server-Sent Events (SSE)
|
|
|
|
**Session Output Stream** (`/api/sessions/:id/stream`)
|
|
|
|
Uses asciinema cast v2 format:
|
|
```json
|
|
[timestamp, "o", "output text"] // Terminal output
|
|
[timestamp, "i", "input text"] // User input
|
|
[timestamp, "r", "80x24"] // Resize event
|
|
["exit", exitCode, sessionId] // Process exit
|
|
```
|
|
|
|
## fwd.ts Application
|
|
|
|
The `fwd.ts` tool (`src/server/fwd.ts`) wraps any command in a VibeTunnel session:
|
|
|
|
**Usage**: `pnpm exec tsx src/fwd.ts [options] <command> [args...]`
|
|
|
|
**Options**:
|
|
- `--session-id <id>`: Use specific session ID
|
|
- `--title-mode <mode>`: none|filter|static|dynamic
|
|
- `--update-title <title>`: Update existing session title
|
|
|
|
**Features**:
|
|
- Auto-detects Claude AI and enables dynamic titles
|
|
- Forwards stdin/stdout through PTY infrastructure
|
|
- Creates sessions accessible via web interface
|
|
- Activity detection for intelligent status updates
|
|
|
|
**Socket Protocol** (`src/server/pty/socket-protocol.ts`):
|
|
```
|
|
Message Types:
|
|
├── stdin: { type: 'stdin', data: Buffer }
|
|
├── resize: { type: 'resize', cols: number, rows: number }
|
|
├── kill: { type: 'kill', signal?: string }
|
|
└── status: { type: 'status', message: string }
|
|
```
|
|
|
|
## HQ Mode & Distributed Architecture
|
|
|
|
### Remote Registration
|
|
1. Remote servers register with HQ using bearer tokens
|
|
2. HQ maintains registry of all remote servers
|
|
3. Health checks every 15 seconds
|
|
4. Automatic session discovery
|
|
|
|
### Request Routing
|
|
- HQ checks session ownership via registry
|
|
- Forwards API requests to appropriate remote
|
|
- Proxies SSE streams transparently
|
|
- Multiplexes WebSocket connections
|
|
|
|
### High Availability
|
|
- Graceful degradation on remote failure
|
|
- Continues serving local sessions
|
|
- Automatic reconnection for WebSocket streams
|
|
- Session ownership tracking for reliability
|
|
|
|
## Activity Tracking
|
|
|
|
### Activity Monitor (`src/server/services/activity-monitor.ts`)
|
|
- Monitors stdout file changes (100ms intervals)
|
|
- Marks sessions inactive after 500ms of no output
|
|
- Persists activity to `activity.json`
|
|
- Provides real-time activity status
|
|
|
|
### Activity Detection (`src/server/utils/activity-detector.ts`)
|
|
- App-specific status detection (Claude AI)
|
|
- Filters prompt-only output
|
|
- Dynamic title updates based on activity
|
|
- 5-second activity timeout
|
|
|
|
## Additional Features
|
|
|
|
### Push Notifications
|
|
- Web Push API with VAPID authentication
|
|
- Bell event notifications from terminal
|
|
- Service worker for offline support
|
|
- Process context in notifications
|
|
|
|
### File Browser
|
|
- Full filesystem browsing with Git status
|
|
- Monaco Editor for code preview
|
|
- Git diff visualization
|
|
- Image preview support
|
|
|
|
### SSH Key Management
|
|
- Browser-based Ed25519 key generation
|
|
- Import/export functionality
|
|
- Password-protected key support
|
|
- Web Crypto API integration
|
|
|
|
### Native Terminal Spawning (macOS)
|
|
- Unix socket at `/tmp/vibetunnel-terminal.sock`
|
|
- Requests native Terminal.app windows
|
|
- Falls back to web terminal
|
|
|
|
### Performance Optimizations
|
|
- Binary buffer compression (empty row encoding)
|
|
- Fire-and-forget input protocol
|
|
- Debounced buffer notifications (50ms)
|
|
- Efficient cell encoding with bit-packing
|
|
|
|
## Development Commands
|
|
|
|
```bash
|
|
# Web directory commands
|
|
cd web/
|
|
|
|
# Development (auto-rebuild)
|
|
pnpm run dev
|
|
|
|
# Code quality (must run before commit)
|
|
pnpm run check # Run all checks in parallel
|
|
pnpm run check:fix # Auto-fix issues
|
|
|
|
# Individual commands
|
|
pnpm run lint # ESLint
|
|
pnpm run format # Prettier
|
|
pnpm run typecheck # TypeScript
|
|
```
|
|
|
|
## Git Follow Mode
|
|
|
|
Git follow mode creates an intelligent synchronization between a main repository and a specific worktree, enabling seamless development workflows where agents work in worktrees while developers maintain their IDE and server setups in the main repository.
|
|
|
|
**Key Components**:
|
|
- **Git Hooks** (`src/server/utils/git-hooks.ts`): Manages post-commit, post-checkout, post-merge hooks
|
|
- **Git Event Handler** (`src/server/routes/git.ts:186-482`): Processes git events and handles synchronization
|
|
- **Socket API** (`src/server/api-socket-server.ts:217-267`): Socket-based follow mode control
|
|
- **CLI Integration** (`web/bin/vt`): Smart command handling with path/branch detection
|
|
|
|
**Configuration**:
|
|
- Single config option: `vibetunnel.followWorktree` stores the worktree path being followed
|
|
- Config is stored in the main repository's `.git/config`
|
|
- Follow mode is active when this config contains a valid worktree path
|
|
|
|
**Synchronization Behavior**:
|
|
1. **Worktree → Main** (Primary): Branch switches, commits, and checkouts sync to main repo
|
|
2. **Main → Worktree** (Limited): Only commits sync; branch switches auto-unfollow
|
|
3. **Auto-unfollow**: Switching branches in main repo disables follow mode
|
|
|
|
**Command Usage**:
|
|
```bash
|
|
# From worktree - follow this worktree
|
|
vt follow
|
|
|
|
# From main repo - smart detection
|
|
vt follow # Follow current branch's worktree (if exists)
|
|
vt follow feature/new-api # Follow worktree for this branch
|
|
vt follow ~/project-feature # Follow worktree by path
|
|
```
|
|
|
|
**Hook Installation**:
|
|
- Hooks installed in BOTH main repository and worktree
|
|
- Hooks execute `vt git event` which notifies server via socket API
|
|
- Server processes events based on source (main vs worktree)
|
|
- Existing hooks are preserved with `.vtbak` extension
|
|
|
|
**Event Flow**:
|
|
1. Git event occurs (checkout, commit, merge)
|
|
2. Hook executes `vt git event`
|
|
3. CLI sends event via socket to server
|
|
4. Server determines sync action based on event source
|
|
5. Appropriate git commands executed to maintain sync
|
|
|
|
## Architecture Principles
|
|
|
|
1. **Modular Design**: Clear separation between auth, sessions, and real-time communication
|
|
2. **Scalability**: Horizontal scaling via HQ mode and remote servers
|
|
3. **Reliability**: Automatic reconnection, health checks, graceful degradation
|
|
4. **Performance**: Binary protocols, compression, minimal latency
|
|
5. **Security**: Multiple auth methods, JWT tokens, secure WebSocket connections
|
|
|
|
For implementation details, refer to the line numbers provided in the Key Files Quick Reference section. |