Clean-up of web/, updated spec.md

This commit is contained in:
Mario Zechner 2025-06-27 21:13:55 +02:00
parent 98e922fd44
commit 4788afb7ed
7 changed files with 300 additions and 413 deletions

View file

@ -1,87 +0,0 @@
# Frontend Logging Update Prompt
## Context
We've just implemented a structured logging system for the server-side code and created endpoints for frontend logging. Now we need to update all frontend components to use this system instead of console.log/error/warn.
## What's Already Done
1. **Server-side logging**: All server files now use the structured logger with proper log levels
2. **Log endpoints created**:
- `POST /api/logs/client` - Frontend can send logs to this endpoint
- The endpoint expects: `{ level: 'log'|'warn'|'error'|'debug', module: string, args: unknown[] }`
3. **Log viewer component**: Available at `/logs.html` to view all logs (both server and client)
4. **Style guide**: Created in `LOGGING_STYLE_GUIDE.md` with rules:
- No colors in error/warn
- Colors only in logger.log (green=success, yellow=warning, blue=info, gray=metadata)
- No prefixes or tags
- Lowercase start, no periods
- Always include error objects
## Your Task
Replace all `console.log`, `console.error`, and `console.warn` calls in frontend code (`src/client/`) with API calls to the logging endpoint.
### Step 1: Create a Frontend Logger Utility
Create `/src/client/utils/logger.ts` with:
```typescript
export function createLogger(moduleName: string) {
const sendLog = async (level: string, ...args: unknown[]) => {
try {
await fetch('/api/logs/client', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ level, module: moduleName, args })
});
} catch {
// Fallback to console on network error
console[level]?.(...args) || console.log(...args);
}
};
return {
log: (...args: unknown[]) => sendLog('log', ...args),
warn: (...args: unknown[]) => sendLog('warn', ...args),
error: (...args: unknown[]) => sendLog('error', ...args),
debug: (...args: unknown[]) => sendLog('debug', ...args)
};
}
```
### Step 2: Find All Console Calls
Use ripgrep to find all console.log/error/warn in frontend:
```bash
rg "console\.(log|error|warn)" src/client/ --type ts
```
### Step 3: Update Each File
For each file with console calls:
1. Import the logger: `import { createLogger } from '../utils/logger.js';`
2. Create logger instance: `const logger = createLogger('component-name');`
3. Replace console calls following the style guide
4. Remove superfluous logs (like "View transition ready")
5. Ensure essential logs use appropriate levels
### Step 4: Special Cases
- For error boundaries and critical failures, you may keep console.error as fallback
- WebSocket/SSE error handling should use logger but can keep console as fallback
- Remove all debug console.logs that were for development (like view transition logs)
### Step 5: Test
After updates, verify:
1. Navigate to `/logs.html`
2. Perform actions in the app
3. Confirm client logs appear with `CLIENT:` prefix
4. Check that log levels and messages follow the style guide
## Files to Update (based on previous analysis)
Key files that likely have console calls:
- `/src/client/app.ts`
- `/src/client/services/terminal-connection.ts`
- `/src/client/services/sse-client.ts`
- `/src/client/services/websocket-client.ts`
- `/src/client/components/*.ts` (all component files)
- Any other files in `/src/client/`
## Remember
- Module names should be descriptive (e.g., 'terminal-connection', 'session-list', 'app')
- Follow the same style guide as server logs (no prefixes, lowercase start)
- Essential logs only - remove debugging/development logs
- Include error objects when logging errors

View file

@ -1,6 +1,6 @@
# VibeTunnel Logging Style Guide # VibeTunnel Logging Style Guide
## Core Rules ## Logging style
### 1. No Colors in Error/Warn ### 1. No Colors in Error/Warn
```typescript ```typescript
@ -19,7 +19,7 @@ logger.warn('Missing config');
logger.log(chalk.green('Session created')); logger.log(chalk.green('Session created'));
logger.log(chalk.green(`Connected to ${server}`)); logger.log(chalk.green(`Connected to ${server}`));
// Warning/Neutral = yellow // Warning/Neutral = yellow
logger.log(chalk.yellow('Shutting down...')); logger.log(chalk.yellow('Shutting down...'));
logger.log(chalk.yellow(`Client disconnected`)); logger.log(chalk.yellow(`Client disconnected`));
@ -50,7 +50,7 @@ logger.error('Failed to connect:', error);
logger.log('The session has been created successfully.'); logger.log('The session has been created successfully.');
logger.error('ERROR: Failed to connect to server!'); logger.error('ERROR: Failed to connect to server!');
// ✅ GOOD // ✅ GOOD
logger.log(`Session ${id} created`); logger.log(`Session ${id} created`);
logger.error('Failed to connect to server'); logger.error('Failed to connect to server');
``` ```
@ -76,7 +76,7 @@ logger.warn('Low memory');
logger.log(chalk.green('Server started')); logger.log(chalk.green('Server started'));
logger.log(chalk.green(`Session ${id} created`)); logger.log(chalk.green(`Session ${id} created`));
// Stopping // Stopping
logger.log(chalk.yellow('Shutting down...')); logger.log(chalk.yellow('Shutting down...'));
logger.log(chalk.yellow(`Session ${id} terminated`)); logger.log(chalk.yellow(`Session ${id} terminated`));

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
{"error": "No coverage data found"}

File diff suppressed because one or more lines are too long

View file

@ -35,6 +35,7 @@
"onlyBuiltDependencies": [ "onlyBuiltDependencies": [
"authenticate-pam", "authenticate-pam",
"esbuild", "esbuild",
"node-pty",
"puppeteer" "puppeteer"
] ]
}, },

View file

@ -10,6 +10,8 @@ VibeTunnel is a web-based terminal multiplexer with distributed architecture sup
- Binary-optimized buffer synchronization (current viewport via WebSocket) - Binary-optimized buffer synchronization (current viewport via WebSocket)
- Distributed HQ/remote server architecture - Distributed HQ/remote server architecture
- Web UI with full terminal emulation - Web UI with full terminal emulation
- Push notifications for terminal bell events
- Multi-method authentication (SSH keys, JWT, PAM)
## Directory Structure ## Directory Structure
@ -21,7 +23,7 @@ web/
│ │ ├── pty/ # PTY management │ │ ├── pty/ # PTY management
│ │ ├── routes/ # API endpoints │ │ ├── routes/ # API endpoints
│ │ ├── services/ # Core services │ │ ├── services/ # Core services
│ │ ├── server.ts # Server loader │ │ ├── server.ts # Main server implementation
│ │ └── fwd.ts # CLI forwarding tool │ │ └── fwd.ts # CLI forwarding tool
│ ├── client/ # Lit-based web UI │ ├── client/ # Lit-based web UI
│ │ ├── assets/ # Static files (fonts, icons, html) │ │ ├── assets/ # Static files (fonts, icons, html)
@ -29,7 +31,7 @@ web/
│ │ ├── services/ # Client services │ │ ├── services/ # Client services
│ │ └── utils/ # Client utilities │ │ └── utils/ # Client utilities
│ ├── test/ # Test files │ ├── test/ # Test files
│ └── index.ts # Main entry point │ └── cli.ts # Main entry point
├── scripts/ # Build scripts ├── scripts/ # Build scripts
└── public/ # Built static assets (generated) └── public/ # Built static assets (generated)
``` ```
@ -39,101 +41,102 @@ web/
### Core Components ### Core Components
#### Entry Points #### Entry Points
- `index.ts` (1-25): Main entry point, chooses between server and forward modes - `cli.ts` (1-62): Main entry point, routes to server or forward mode
- `server/server.ts` (1-4): Simple loader for modular server - `server/server.ts` (1-953): Core server implementation with Express app factory
- `server/index.ts` (1-49): Server initialization, cleanup intervals, graceful shutdown - CLI parsing (132-236): Extensive configuration options
- `server/app.ts` (198-404): Express app factory, CLI parsing, mode configuration - Server modes (432-444): Normal, HQ, Remote initialization
- WebSocket upgrade (564-677): Authentication and buffer streaming
#### Server Modes - Graceful shutdown (888-944): Cleanup intervals and service termination
1. **Normal Mode**: Standalone terminal server
2. **HQ Mode** (`--hq`): Central server managing remotes
3. **Remote Mode** (`--hq-url`): Registers with HQ server
### Authentication (`middleware/auth.ts`) ### Authentication (`middleware/auth.ts`)
- Basic Auth: Username/password (46-55) - Multi-method authentication (1-159)
- Bearer Token: HQ↔Remote communication (28-44) - SSH key authentication with Ed25519 support
- Health endpoint bypass (14-16) - 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 ### Session Management
#### PTY Manager (`pty/pty-manager.ts`) #### PTY Manager (`pty/pty-manager.ts`)
- `createSession()` (155-287): Spawns PTY processes - Session creation (78-163): Spawns PTY processes with node-pty
- Supports `forwardToStdout` option for direct stdout forwarding - **Automatic alias resolution** (191-204): Uses `ProcessUtils.resolveCommand()`
- Supports `onExit` callback for handling process termination - Terminal resize handling (63-157): Dimension synchronization
- **Automatic alias resolution**: Uses `ProcessUtils.resolveCommand()` to detect and run aliases through shell - Control pipe support using file watching on all platforms
- `sendInput()` (515-588): Handles keyboard input - Bell event emission for push notifications
- `killSession()` (687-764): SIGTERM→SIGKILL escalation - Clean termination with SIGTERM→SIGKILL escalation
- `resizeSession()` (638-681): Terminal dimension changes
- Control pipe support using file watching on all platforms (414-475)
- `shutdown()` (937-974): Clean termination of all active sessions
- Proper TypeScript types throughout (no "as any" assertions)
#### Process Utils (`pty/process-utils.ts`) #### Process Utils (`pty/process-utils.ts`)
- `resolveCommand()` (168-242): Detects if command exists in PATH or needs shell execution - `resolveCommand()` (242-378): Detects if command exists in PATH
- Uses `which` (Unix) or `where` (Windows) to check command existence - Uses `which` (Unix) or `where` (Windows) to check existence
- Returns appropriate shell command with args for aliases/builtins - Returns appropriate shell command for aliases/builtins
- Platform-specific shell argument handling - Sources shell config files for proper alias support
- `getUserShell()` (219-281): Determines user's preferred shell - `getUserShell()` (384-484): Determines user's preferred shell
- Checks `$SHELL` environment variable first - Checks `$SHELL` environment variable first
- Windows: Checks for pwsh, PowerShell, Git Bash, then cmd.exe - Platform-specific fallbacks (pwsh/cmd on Windows, zsh/bash on Unix)
- Unix: Checks common shell paths (/bin/zsh, /bin/bash, etc.) - Interactive shell detection (220-235): Auto-adds `-i -l` flags
#### Session Manager (`pty/session-manager.ts`) #### Session Manager (`pty/session-manager.ts`)
- Session persistence in `~/.vibetunnel/control/` - Session persistence in `~/.vibetunnel/control/`
- `listSessions()` (155-224): Filesystem-based discovery - Filesystem-based session discovery
- `updateZombieSessions()` (231-257): Dead process cleanup - Zombie session cleanup
#### Terminal Manager (`services/terminal-manager.ts`) #### Terminal Manager (`services/terminal-manager.ts`)
- Headless xterm.js for server-side state (40-69) - Headless xterm.js for server-side state
- `getBufferSnapshot()` (255-323): Captures terminal buffer - Binary buffer snapshot generation
- `encodeSnapshot()` (328-555): Binary protocol encoding - Watches asciinema cast files and applies to terminal
- Debounced buffer notifications (627-642) - Debounced buffer change notifications
### API Routes (`routes/`) ### API Routes (`routes/`)
#### Sessions (`sessions.ts`) #### Sessions (`sessions.ts`)
- `GET /api/sessions` (40-120): List with HQ aggregation - `GET /api/sessions` (51-124): List all sessions
- Returns array of `SessionEntryWithId` objects with additional fields: - Returns array with `source: 'local' | 'remote'`
- All fields from `SessionEntryWithId` (see types.ts) - HQ mode: Aggregates from all remote servers
- `source`: 'local' | 'remote' - `POST /api/sessions` (126-265): Create session
- For remote sessions: `remoteId`, `remoteName`, `remoteUrl` - Body: `{ command, workingDir?, name?, remoteId?, spawn_terminal? }`
- `POST /api/sessions` (123-199): Create local/remote - Returns: `{ sessionId: string, message?: string }`
- `DELETE /api/sessions/:id` (270-323): Kill session - `GET /api/sessions/:id` (369-410): Get session info
- `GET /api/sessions/:id/stream` (517-627): SSE streaming of asciinema cast files - `DELETE /api/sessions/:id` (413-467): Kill session
- `POST /api/sessions/:id/input` (630-695): Send input - `DELETE /api/sessions/:id/cleanup` (470-518): Clean session files
- `POST /api/sessions/:id/resize` (698-767): Resize terminal - `POST /api/cleanup-exited` (521-598): Clean all exited sessions
- `GET /api/sessions/:id/buffer` (569-631): Binary snapshot of current terminal view
- `GET /api/sessions/:id/text` (504-654): Plain text of current terminal view #### Session I/O
- Optional `?styles` query parameter adds style markup - `POST /api/sessions/:id/input` (874-950): Send keyboard input
- Style format: `[style fg="color" bg="color" bold italic ...]text[/style]` - Body: `{ text: string }` OR `{ key: SpecialKey }`
- Colors: indexed (0-255) as `"15"`, RGB as `"255,128,0"` - `POST /api/sessions/:id/resize` (953-1025): Resize terminal
- Attributes: bold, dim, italic, underline, inverse, invisible, strikethrough - Body: `{ cols: number, rows: number }`
- `GET /api/sessions/activity` (255-311): Activity status for all sessions - `POST /api/sessions/:id/reset-size` (1028-1083): Reset to native size
- Returns: `{ [sessionId]: ActivityStatus }` where ActivityStatus includes:
- `isActive`: boolean - Currently generating output #### Session Output
- `timestamp`: string - Last update time - `GET /api/sessions/:id/stream` (723-871): SSE streaming
- `session`: SessionInfo object (see types.ts) - Streams asciinema v2 format with custom exit event
- In HQ mode: aggregates activity from all remote servers - Replays existing content, then real-time streaming
- `GET /api/sessions/:id/activity` (314-370): Activity status for specific session - `GET /api/sessions/:id/buffer` (662-721): Binary buffer snapshot
- Returns: `ActivityStatus` object (same format as above) - `GET /api/sessions/:id/text` (601-659): Plain text output
- In HQ mode: forwards to appropriate remote server - 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 #### Remotes (`remotes.ts`) - HQ Mode Only
- `GET /api/remotes` (15-27): List registered servers - `GET /api/remotes` (19-33): List registered servers
- `POST /api/remotes/register` (30-52): Remote registration - `POST /api/remotes/register` (36-64): Register remote
- `DELETE /api/remotes/:id` (55-69): Unregister remote - `DELETE /api/remotes/:id` (67-84): Unregister remote
- `POST /api/remotes/:id/refresh-sessions` (87-152): Refresh session list
#### Logs (`logs.ts`) #### Logs (`logs.ts`)
- `POST /api/logs/client` (24-56): Client-side log submission - `POST /api/logs/client` (21-53): Client log submission
- Accepts: `{ level, module, args }` - `GET /api/logs/raw` (56-74): Stream raw log file
- Prefixes module with `CLIENT:` for identification - `GET /api/logs/info` (77-102): Log file metadata
- `GET /api/logs/raw` (59-76): Stream raw log file - `DELETE /api/logs/clear` (105-119): Clear log file
- `GET /api/logs/info` (79-104): Log file metadata
- `DELETE /api/logs/clear` (107-121): Clear log file
### Binary Buffer Protocol ### Binary Buffer Protocol
**Note**: "Buffer" refers to the current terminal display state (visible viewport) without scrollback history - just what's currently shown at the bottom of the terminal. This is used for rendering terminal previews in the session list. **Note**: "Buffer" refers to the current terminal viewport without scrollback - used for terminal previews.
#### Format (`terminal-manager.ts:361-555`) #### Format (`terminal-manager.ts:361-555`)
``` ```
@ -151,356 +154,329 @@ Cells: Variable-length with type byte
### SSE Streaming and Asciinema Files ### SSE Streaming and Asciinema Files
#### File Writing (`pty/asciinema-writer.ts`) #### Asciinema Writer (`pty/asciinema-writer.ts`)
- **AsciinemaWriter** (separate file) writes cast files to `~/.vibetunnel/control/[sessionId]/stream-out` - Writes cast files to `~/.vibetunnel/control/[sessionId]/stream-out`
- Used by PtyManager when creating sessions - Format:
- Records in asciinema v2 format with custom extensions:
- Standard: `[timestamp, "o", output]` for terminal output - Standard: `[timestamp, "o", output]` for terminal output
- Standard: `[timestamp, "i", input]` for user input - Standard: `[timestamp, "i", input]` for user input
- Standard: `[timestamp, "r", "colsxrows"]` for resize events - Standard: `[timestamp, "r", "colsxrows"]` for resize events
- **Custom**: `["exit", exitCode, sessionId]` when process terminates - **Custom**: `["exit", exitCode, sessionId]` when process terminates
#### SSE Streaming (`routes/sessions.ts:517-627`) #### SSE Streaming (`routes/sessions.ts:723-871`)
- Streams asciinema cast files from disk in real-time - Real-time streaming of asciinema cast files
- **StreamWatcher** monitors file changes and broadcasts to clients - Replays existing content with zeroed timestamps
- Replays existing content first (timestamps zeroed)
- Watches for new content and streams incrementally - Watches for new content and streams incrementally
- Closes connections on exit event - Heartbeat every 30 seconds
#### Client Playback (`client/utils/cast-converter.ts`)
- Parses asciinema v2 format
- Handles custom exit event to dispatch `session-exit`
- Supports batch loading and real-time streaming
### WebSocket (`services/buffer-aggregator.ts`) ### WebSocket (`services/buffer-aggregator.ts`)
- Client connections (31-68) - Client connections (30-87): Authentication and subscription
- Message handling (69-127) - Message handling (88-127): Subscribe/unsubscribe/ping
- Local session buffers (131-195) - Binary protocol (156-209): `[0xBF][ID Length][Session ID][Buffer Data]`
- Remote session proxy (200-232) - Local and remote session proxy support
- Binary message format (136-164)
### Activity Monitoring (`services/activity-monitor.ts`) ### Activity Monitoring (`services/activity-monitor.ts`)
- Monitors `stream-out` file size changes (143-146)
#### Overview - 100ms check interval (41-44)
Monitors all terminal sessions for activity by watching `stream-out` file changes. - 500ms inactivity timeout (209-212)
- Works for ALL sessions regardless of creation method (server or fwd.ts) - Persists to `activity.json` per session (220-245)
- No performance impact on terminal output - Works for all sessions regardless of creation method
- File-based persistence for cross-process access
#### Implementation
- `start()` (26-37): Begins monitoring with 100ms check interval
- `scanSessions()` (61-98): Discovers and monitors session directories
- `handleFileChange()` (146-168): Detects output by file size increase
- `updateActivityStates()` (173-182): Marks inactive after 500ms timeout
- `writeActivityStatus()` (187-198): Persists to `activity.json` per session
#### Activity Status Format
```json
{
"isActive": boolean,
"timestamp": "ISO 8601 date string",
"session": { // SessionInfo object from session.json
"cmdline": ["command", "args"],
"name": "session name",
"cwd": "/working/directory",
"pid": 12345,
"status": "starting" | "running" | "exited",
"exit_code": 0,
"started_at": "ISO 8601 date string",
"term": "xterm-256color",
"spawn_type": "pty"
}
}
```
### HQ Mode Components ### HQ Mode Components
#### Remote Registry (`services/remote-registry.ts`) #### Remote Registry (`services/remote-registry.ts`)
- Health checks every 15s (118-146) - Health checks every 15s (150-187)
- Session ownership tracking (82-96) - Session ownership tracking (91-148)
- Bearer token authentication - Bearer token authentication
- Automatic unhealthy remote removal
#### HQ Client (`services/hq-client.ts`) #### HQ Client (`services/hq-client.ts`)
- Registration with HQ (29-58) - Registration with HQ (40-90)
- Unregister on shutdown (60-72) - Unique ID generation with UUID v4
- Graceful unregistration on shutdown (92-113)
### Logging Infrastructure (`utils/logger.ts`) ### Additional Services
#### Server Logger #### Push Notifications (`services/push-notification-service.ts`)
- Unified logging with file and console output - 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 - Log levels: log, warn, error, debug
- File output to `~/.vibetunnel/log.txt` - File output to `~/.vibetunnel/log.txt`
- Formatted timestamps and module names - Debug mode via `VIBETUNNEL_DEBUG`
- Debug mode toggle
- Style guide compliance (see LOGGING_STYLE_GUIDE.md)
#### Client Logger (`client/utils/logger.ts`) #### VAPID Manager (`utils/vapid-manager.ts`)
- Mirrors server logger interface - Auto-generates VAPID keys for push notifications (20-331)
- Logs to browser console - Stores in `~/.vibetunnel/vapid/keys.json`
- Sends logs to `/api/logs/client` endpoint - Key rotation support
- Objects formatted as JSON before sending
- Integrates with server logging system
## Client Architecture (`src/client/`) ## Client Architecture (`src/client/`)
### Core Components ### Core Components
#### Entry Points #### Entry Points
- `app-entry.ts` - Main application entry point - `app-entry.ts` (1-28): Main entry, initializes Monaco and push notifications
- `test-terminals-entry.ts` - Test terminals entry point - `test-entry.ts`: Test terminals entry
- `styles.css` - Global styles - `styles.css`: Global Tailwind styles
#### Main Application Component #### Main Application (`app.ts`)
- `app.ts` - Lit-based SPA (15-331) - Lit-based SPA (15-1200+): `<vibetunnel-app>`
- URL-based routing `?session=<id>` - URL-based routing with `?session=<id>`
- Global keyboard handlers - Global keyboard handlers (Cmd+O, Escape)
- Error/success message handling (74-90) - View management: auth/list/session
- **Events fired**: - **Events fired**:
- `toggle-nav` - Toggle navigation - `toggle-nav`, `navigate-to-list`, `error`, `success`, `navigate`
- `navigate-to-list` - Navigate to session list
- `error` - Display error message
- `success` - Display success message
- `navigate` - Navigate to specific session
- **Events listened**: Various events from child components
### Component Event Architecture ### Component Event Architecture
#### Terminal Components ```
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.ts` - Custom DOM terminal renderer (17-1000+) ### Terminal Components
Full terminal implementation with xterm.js for rendering and input handling.
#### Terminal (`terminal.ts`)
- Full xterm.js implementation (1-1000+)
- Virtual scrolling (537-555) - Virtual scrolling (537-555)
- Touch/momentum support - Touch/momentum support
- URL highlighting integration - URL highlighting integration
- Copy/paste handling - **Events**: `terminal-ready`, `terminal-input`, `terminal-resize`, `url-clicked`
- **Events fired**:
- `terminal-ready` - When terminal is initialized and ready
- `terminal-input` - When user types (detail: string)
- `terminal-resize` - When terminal is resized (detail: { cols: number, rows: number })
- `url-clicked` - When a URL is clicked (detail: string)
##### `session-view.ts` - Full-screen terminal view (29-1331) #### VibeTunnelBuffer (`vibe-terminal-buffer.ts`)
Full-screen terminal view for an active session. Handles terminal I/O, streaming updates via SSE, file browser integration, and mobile overlays. - Read-only terminal preview (25-268)
- SSE streaming (275-333) - WebSocket buffer subscription
- Mobile input overlays - Auto-resizing
- Resize synchronization - **Events**: `content-changed`
- **Events fired**:
- `navigate-to-list` - When navigating back to session list
- `error` - When an error occurs (detail: string)
- `warning` - When a warning occurs (detail: string)
- **Events listened**:
- `session-exit` - From SSE stream when session exits
- `terminal-ready` - From terminal component when ready
- `file-selected` - From file browser when file is selected
- `browser-cancel` - From file browser when cancelled
##### `vibe-terminal-buffer.ts` - Terminal buffer display (25-268) #### SessionView (`session-view.ts`)
Displays a read-only terminal buffer snapshot with automatic resizing. Subscribes to buffer updates via WebSocket and renders the terminal content. - Full-screen terminal view (29-1331)
- **Events fired**: - Manager architecture:
- `content-changed` - When terminal content changes (no detail) - 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 ### Session Management Components
##### `session-list.ts` - Active sessions list view (61-700+) #### SessionList (`session-list.ts`)
Main session list view showing all active terminal sessions with real-time updates, search/filtering, and session management capabilities. - Grid/list layout (61-700+)
- **Events fired**: - Hide/show exited sessions
- `navigate` - When clicking on a session (detail: { sessionId: string }) - Search and filtering
- `error` - When an error occurs (detail: string) - **Events**: `navigate-to-session`, `refresh`, `error`, `success`
- `success` - When an operation succeeds (detail: string)
- `session-created` - When a new session is created (detail: Session)
- `session-updated` - When a session is updated (detail: Session)
- `sessions-changed` - When the session list changes
- `toggle-create-form` - When toggling the create form
- **Events listened**:
- `session-created` - From create form
- `cancel` - From create form
- `error` - From create form
##### `session-card.ts` - Individual session card (31-420+) #### SessionCard (`session-card.ts`)
Individual session card component showing terminal preview and session controls. Displays a live terminal buffer preview and detects activity changes. - Individual session display (31-420+)
- **Events fired**: - Live terminal preview
- `view-session` - When viewing a session (detail: Session) - Activity detection
- `kill-session` - When killing a session (detail: Session) - **Events**: `session-select`, `session-killed`, `session-kill-error`
- `copy-session-id` - When copying session ID (detail: Session)
- **Events listened**:
- `content-changed` - From vibe-terminal-buffer component
##### `session-create-form.ts` - New session creation form (27-381) #### SessionCreateForm (`session-create-form.ts`)
Modal dialog for creating new terminal sessions. Provides command input, working directory selection, and options for spawning in native terminal. - Modal dialog (27-381)
- **Events fired**: - Command input with working directory
- `session-created` - When session is successfully created (detail: { sessionId: string, message?: string }) - Native terminal spawn option
- `cancel` - When form is cancelled - **Events**: `session-created`, `cancel`, `error`
- `error` - When creation fails (detail: string)
- **Events listened**:
- `file-selected` - From file browser when directory is selected
- `browser-cancel` - From file browser when cancelled
#### UI Components ### UI Components
##### `app-header.ts` - Application header (15-280+) #### AppHeader (`app-header.ts`)
Main application header with logo, title, navigation controls, and session status. - Main navigation (15-280+)
- **Events fired**: - Session status display
- `toggle-nav` - Toggle navigation menu - Theme toggle
- `navigate-to-list` - Navigate to session list - **Events**: `toggle-nav`, `navigate-to-list`, `toggle-create-form`
- `toggle-create-form` - Toggle session create form
- `toggle-theme` - Toggle dark/light theme
- `open-settings` - Open settings modal
##### `file-browser.ts` - File browser component (48-665) #### FileBrowser (`file-browser.ts`)
Modal file browser for navigating the filesystem and selecting files/directories. Supports Git status display, file preview with Monaco editor, and diff viewing. - Filesystem navigation (48-665)
- **Events fired**: - Git status display
- `insert-path` - When inserting a file path into terminal (detail: { path: string, type: 'file' | 'directory' }) - Monaco editor preview
- `open-in-editor` - When opening a file in external editor (detail: { path: string }) - **Events**: `insert-path`, `open-in-editor`, `directory-selected`
- `directory-selected` - When a directory is selected in 'select' mode (detail: string)
- `browser-cancel` - When the browser is cancelled or closed
##### `log-viewer.ts` - System log viewer (1-432) #### LogViewer (`log-viewer.ts`)
Real-time log viewer with filtering and search capabilities. - Real-time log display (1-432)
- SSE-style polling every 2 seconds - SSE-style polling
- Client/server log distinction - Level filtering
- Log level filtering - Search functionality
- Relative timestamps
- Mobile-responsive layout
- Mac-style auto-hiding scrollbars
- **Features**:
- Filter by log level (error, warn, log, debug)
- Toggle client/server logs
- Search/filter by text
- Auto-scroll (smart - only when near bottom)
- Download logs
- Clear logs
##### Icon Components
- `vibe-logo.ts` - Application logo
- `terminal-icon.ts` - Terminal icon
- `copy-icon.ts` - Copy icon
### Services ### Services
#### Buffer Subscription (`services/buffer-subscription-service.ts`) #### BufferSubscriptionService (`buffer-subscription-service.ts`)
- WebSocket client (30-87) - WebSocket client (30-87)
- Binary protocol decoder (163-208) - Binary protocol decoder (163-208)
- Auto-reconnection with backoff - 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 ### Utils
#### Cast Converter (`utils/cast-converter.ts`) #### CastConverter (`cast-converter.ts`)
- Asciinema v2 parser (31-82) - Asciinema v2 parser (31-82)
- SSE stream handler (294-427) - SSE stream handler (294-427)
- Batch loading (221-283) - Custom exit event support
#### Terminal Renderer (`utils/terminal-renderer.ts`) #### TerminalRenderer (`terminal-renderer.ts`)
- Binary buffer decoder (279-424) - Binary buffer decoder (279-424)
- HTML generation - HTML generation from buffer
- Style mapping - Style mapping
#### Additional Utilities #### URLHighlighter (`url-highlighter.ts`)
- `url-highlighter.ts` - URL detection and highlighting - Multi-line URL detection
- `xterm-colors.ts` - Terminal color definitions - Protocol validation
- `terminal-preferences.ts` - Terminal preference management - Click event handling
## Forward Tool (`src/server/fwd.ts`) ## Forward Tool (`src/server/fwd.ts`)
### Purpose ### Purpose
Simplified CLI tool that spawns PTY sessions using VibeTunnel infrastructure. CLI tool for spawning PTY sessions using VibeTunnel infrastructure.
### Key Features
- Interactive terminal forwarding with colorful output (chalk)
- Session creation with pre-generated IDs support
- Graceful cleanup on exit
- **Automatic shell alias support** via ProcessUtils.resolveCommand()
### Usage ### Usage
```bash ```bash
npx tsx src/fwd.ts [--session-id <id>] <command> [args...] npx tsx src/fwd.ts [--session-id <id>] <command> [args...]
# Examples with aliases # Examples
npx tsx src/fwd.ts claude-danger # Automatically resolved through shell 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 ### Integration Points
- Uses PtyManager for all session management - Uses central PTY Manager (78-82)
- Control pipe and stdin forwarding handled by PtyManager - Control pipe handling delegated to PTY Manager
- Automatic cleanup via PtyManager's shutdown() method - 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 ## Key Files Quick Reference
### Server Core ### Server Core
- `src/index.ts`: Main entry point - `src/cli.ts`: Main entry point
- `src/server/server.ts`: Server loader - `src/server/server.ts`: Server implementation
- `src/server/app.ts`: App configuration, CLI parsing - `src/server/middleware/auth.ts`: Authentication
- `src/server/middleware/auth.ts`: Authentication logic - `src/server/routes/sessions.ts`: Session API
- `src/server/routes/sessions.ts`: Session API endpoints - `src/server/pty/pty-manager.ts`: PTY management
- `src/server/pty/pty-manager.ts`: PTY process management with file-watching control pipes - `src/server/services/terminal-manager.ts`: Terminal state
- `src/server/pty/asciinema-writer.ts`: Cast file writer - `src/server/services/activity-monitor.ts`: Activity tracking
- `src/server/services/terminal-manager.ts`: Terminal state & binary protocol - `src/server/fwd.ts`: CLI forwarding tool
- `src/server/services/buffer-aggregator.ts`: WebSocket buffer distribution
- `src/server/services/stream-watcher.ts`: SSE file streaming
- `src/server/services/activity-monitor.ts`: Session activity detection
- `src/server/fwd.ts`: Simplified CLI forwarding tool
### Client Core ### Client Core
- `src/client/app-entry.ts`: Application entry point - `src/client/app-entry.ts`: Entry point
- `src/client/app.ts`: Main SPA component - `src/client/app.ts`: Main SPA
- `src/client/components/terminal.ts`: Terminal renderer - `src/client/components/terminal.ts`: Terminal renderer
- `src/client/components/session-view.ts`: Session viewer - `src/client/components/session-view.ts`: Session viewer
- `src/client/components/session-list.ts`: Session list view - `src/client/services/buffer-subscription-service.ts`: WebSocket
- `src/client/services/buffer-subscription-service.ts`: WebSocket client
- `src/client/utils/cast-converter.ts`: Asciinema parser - `src/client/utils/cast-converter.ts`: Asciinema parser
- `src/client/assets/`: Static files (fonts, icons, HTML)
### Configuration ### Configuration
- Environment: `PORT`, `VIBETUNNEL_USERNAME`, `VIBETUNNEL_PASSWORD`, `VIBETUNNEL_DEBUG` - Environment: `PORT`, `VIBETUNNEL_USERNAME`, `VIBETUNNEL_PASSWORD`, `VIBETUNNEL_DEBUG`
- CLI: `--port`, `--username`, `--password`, `--hq`, `--hq-url`, `--name` - CLI: `--port`, `--username`, `--password`, `--hq`, `--hq-url`, `--name`
- Express static: `.html` extension handling for clean URLs - Debug logging: Set `VIBETUNNEL_DEBUG=1` or `true`
- Debug logging: Set `VIBETUNNEL_DEBUG=1` or `VIBETUNNEL_DEBUG=true`
### Protocols ### Protocols
- REST API: Session CRUD, terminal I/O, activity status - REST API: Session CRUD, terminal I/O
- SSE: Real-time streaming of asciinema cast files from disk - SSE: Real-time asciinema streaming
- WebSocket: Binary buffer updates (current terminal viewport) - WebSocket: Binary buffer updates
- Control pipes: External session control - Control pipes: External session control
### Session Data Storage ### Session Data Storage
Each session has a directory in `~/.vibetunnel/control/[sessionId]/` containing: Each session has a directory in `~/.vibetunnel/control/[sessionId]/`:
- `session.json`: Session metadata - `session.json`: Session metadata
- `stream-out`: Asciinema cast file with terminal output - `stream-out`: Asciinema cast file
- `stdin`: Input pipe for sending keystrokes - `stdin`: Input pipe
- `control`: Control pipe for resize/kill commands - `control`: Control pipe
- `activity.json`: Activity status (written by ActivityMonitor) - `activity.json`: Activity status
## Development Notes ## Development Notes
### Architecture Changes (Recent) ### Recent Improvements
- PTY Manager now uses file watching for control pipes on all platforms (not just FIFO) - Push notification support for terminal bells
- No global exit handlers - clean shutdown via `shutdown()` method - Multi-method authentication (SSH keys, JWT, PAM)
- Simplified fwd.ts - control pipe and stdin forwarding handled by PTY Manager - Unified logging infrastructure with style guide
- Added proper TypeScript types throughout (removed all "as any" assertions) - Activity monitoring for all sessions
- Cleaned up logging and added colorful output messages using chalk - Control directory watcher for external sessions
- **Unified logging infrastructure**: - Improved TypeScript types (no "as any")
- Server-wide adoption of structured logger - Colorful CLI output with chalk
- Client-side logger with server integration - Auto-generation of security keys (VAPID)
- Centralized log viewer at `/logs`
- Consistent style guide (LOGGING_STYLE_GUIDE.md)
- **Express enhancements**:
- Auto `.html` extension resolution for static files
### Build System
- `pnpm run dev`: Auto-rebuilds TypeScript
- `pnpm run build`: Full build including Node.js SEA executable
- ESBuild: Fast bundling
- Node.js SEA: Creates standalone executable (Node.js 20+ required)
- Vitest: Testing framework
- Assets: Copied from `src/client/assets/` to `public/` during build
### Testing ### Testing
- Unit tests: `pnpm test` - Unit tests: `pnpm test`
- E2E tests: `pnpm run test:e2e` - E2E tests: `pnpm run test:e2e`
- Integration: `pnpm run test:integration` - Vitest configuration with coverage
### Key Dependencies ### Key Dependencies
- node-pty: Cross-platform PTY - node-pty: Cross-platform PTY
- @xterm/headless: Terminal emulation - @xterm/headless: Terminal emulation
- Lit: Web components - Lit: Web components
- Express: HTTP server - Express: HTTP server
- web-push: Push notifications
- TailwindCSS: Styling - TailwindCSS: Styling