add release docs and spec

This commit is contained in:
Peter Steinberger 2025-06-17 02:08:59 +02:00
parent 518b1dd7c1
commit 9f926ea381
3 changed files with 1423 additions and 0 deletions

258
docs/RELEASE.md Normal file
View file

@ -0,0 +1,258 @@
# VibeTunnel Release Process
This guide explains how to create and publish releases for VibeTunnel, a macOS menu bar application using Sparkle 2.x for automatic updates.
## 🎯 Release Process Overview
VibeTunnel uses an automated release process that handles all the complexity of:
- Building and code signing
- Notarization with Apple
- Creating DMG disk images
- Publishing to GitHub
- Updating Sparkle appcast files
## 🚀 Creating a Release
### Step 1: Pre-flight Check
```bash
./scripts/preflight-check.sh
```
This validates your environment is ready for release.
### Step 2: Create/Update CHANGELOG.md
Before creating any release, ensure the CHANGELOG.md file exists and contains a proper section for the version being released. If this is your first release, create a CHANGELOG.md file in the project root:
```markdown
# Changelog
All notable changes to VibeTunnel will be documented in this file.
## [1.1.0] - 2025-06-10
### 🎨 UI Improvements
- **Enhanced feature** - Description of the improvement
...
```
**CRITICAL**: The appcast generation relies on the local CHANGELOG.md file, NOT the GitHub release description. The changelog must be added to CHANGELOG.md BEFORE running the release script.
### Step 3: Create the Release
```bash
# For stable releases:
./scripts/release.sh stable
# For pre-releases (beta, alpha, rc):
./scripts/release.sh beta 1 # Creates version-beta.1
./scripts/release.sh alpha 2 # Creates version-alpha.2
./scripts/release.sh rc 1 # Creates version-rc.1
```
**IMPORTANT**: The release script does NOT automatically increment build numbers. You must manually update the build number in VibeTunnel.xcodeproj before running the script, or it will fail the pre-flight check.
The script will:
1. Validate build number is unique and incrementing
2. Build, sign, and notarize the app
3. Create a DMG
4. Publish to GitHub
5. Update the appcast files with EdDSA signatures
6. Commit and push all changes
### Step 4: Verify Success
- Check the GitHub releases page
- Verify the appcast was updated correctly with proper changelog content
- Test updating from a previous version
- **Important**: Verify that the Sparkle update dialog shows the formatted changelog, not HTML tags
## ⚠️ Critical Requirements
### 1. Build Numbers MUST Increment
Sparkle uses build numbers (CFBundleVersion) to determine updates, NOT version strings!
| Version | Build | Result |
|---------|-------|--------|
| 1.0.0-beta.1 | 100 | ✅ |
| 1.0.0-beta.2 | 101 | ✅ |
| 1.0.0-beta.3 | 99 | ❌ Build went backwards |
| 1.0.0 | 101 | ❌ Duplicate build number |
### 2. Required Environment Variables
```bash
export APP_STORE_CONNECT_KEY_ID="YOUR_KEY_ID"
export APP_STORE_CONNECT_ISSUER_ID="YOUR_ISSUER_ID"
export APP_STORE_CONNECT_API_KEY_P8="-----BEGIN PRIVATE KEY-----
YOUR_PRIVATE_KEY_CONTENT
-----END PRIVATE KEY-----"
```
### 3. Prerequisites
- Xcode 16.4+ installed
- GitHub CLI authenticated: `gh auth status`
- Apple Developer ID certificate in Keychain
- Sparkle tools in `~/.local/bin/` (sign_update, generate_appcast)
## 🔐 Sparkle Configuration
### Sparkle Requirements for Non-Sandboxed Apps
VibeTunnel is not sandboxed, which simplifies Sparkle configuration:
#### 1. Entitlements (VibeTunnel.entitlements)
```xml
<!-- App is NOT sandboxed -->
<key>com.apple.security.app-sandbox</key>
<false/>
<!-- Required for code injection/library validation -->
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
```
#### 2. Info.plist Configuration
```swift
"SUEnableInstallerLauncherService": false, // Not needed for non-sandboxed apps
"SUEnableDownloaderService": false, // Not needed for non-sandboxed apps
```
#### 3. Code Signing Requirements
The notarization script handles all signing correctly:
1. **Do NOT use --deep flag** when signing the app
2. Sign the app with hardened runtime and entitlements
The `notarize-app.sh` script should sign the app:
```bash
# Sign the app WITHOUT --deep flag
codesign --force --sign "Developer ID Application" --entitlements VibeTunnel.entitlements --options runtime VibeTunnel.app
```
### Common Sparkle Errors and Solutions
| Error | Cause | Solution |
|-------|-------|----------|
| "You're up to date!" when update exists | Build number not incrementing | Check build numbers in appcast are correct |
| "Update installation failed" | Signing or permission issues | Verify app signature and entitlements |
| "Cannot verify update signature" | EdDSA key mismatch | Ensure sparkle-public-ed-key.txt matches private key |
## 📋 Update Channels
VibeTunnel supports two update channels:
1. **Stable Channel** (`appcast.xml`)
- Production releases only
- Default for all users
2. **Pre-release Channel** (`appcast-prerelease.xml`)
- Includes beta, alpha, and RC versions
- Users opt-in via Settings
## 🐛 Common Issues and Solutions
### Appcast Shows HTML Tags Instead of Formatted Text
**Problem**: Sparkle update dialog shows escaped HTML like `&lt;h2&gt;` instead of formatted text.
**Root Cause**: The generate-appcast.sh script is escaping HTML content from GitHub release descriptions.
**Solution**:
1. Ensure CHANGELOG.md has the proper section for the release version BEFORE running release script
2. The appcast should use local CHANGELOG.md, not GitHub release body
3. If the appcast is wrong, manually fix the generate-appcast.sh script to use local changelog content
### Build Numbers Not Incrementing
**Problem**: Sparkle doesn't detect new version as an update.
**Solution**: Always increment the build number in the Xcode project before releasing.
## 🛠️ Manual Process (If Needed)
If the automated script fails, here's the manual process:
### 1. Update Build Number
Edit the project build settings in Xcode:
- Open VibeTunnel.xcodeproj
- Select the project
- Update CURRENT_PROJECT_VERSION (build number)
### 2. Clean and Build
```bash
rm -rf build DerivedData .build
./scripts/build.sh --configuration Release
```
### 3. Sign and Notarize
```bash
./scripts/notarize-app.sh build/Build/Products/Release/VibeTunnel.app
```
### 4. Create DMG
```bash
./scripts/create-dmg.sh
```
### 5. Sign DMG for Sparkle
```bash
export PATH="$HOME/.local/bin:$PATH"
sign_update build/VibeTunnel-X.X.X.dmg
# Copy the sparkle:edSignature value
```
### 6. Create GitHub Release
```bash
gh release create "v1.0.0-beta.1" \
--title "VibeTunnel 1.0.0-beta.1" \
--notes "Beta release 1" \
--prerelease \
build/VibeTunnel-1.0.0-beta.1.dmg
```
### 7. Update Appcast
```bash
./scripts/update-appcast.sh
git add appcast*.xml
git commit -m "Update appcast for v1.0.0-beta.1"
git push
```
## 🔍 Troubleshooting
### Debug Sparkle Updates
```bash
# Monitor VibeTunnel logs
log stream --predicate 'process == "VibeTunnel"' --level debug
# Check XPC errors
log stream --predicate 'process == "VibeTunnel"' | grep -i -E "(sparkle|xpc|installer)"
# Verify XPC services
codesign -dvv "VibeTunnel.app/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc"
```
### Verify Signing and Notarization
```bash
# Check app signature
./scripts/verify-app.sh build/VibeTunnel-1.0.0.dmg
# Verify XPC bundle IDs (should be org.sparkle-project.*)
/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" \
"VibeTunnel.app/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc/Contents/Info.plist"
```
### Appcast Issues
```bash
# Verify appcast has correct build numbers
./scripts/verify-appcast.sh
# Check if build number is "1" (common bug)
grep '<sparkle:version>' appcast-prerelease.xml
```
## 📚 Important Links
- [Sparkle Sandboxing Guide](https://sparkle-project.org/documentation/sandboxing/)
- [Sparkle Code Signing](https://sparkle-project.org/documentation/sandboxing/#code-signing)
- [Apple Notarization](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution)
---
**Remember**: Always use the automated release script, ensure build numbers increment, and test updates before announcing!

View file

@ -0,0 +1,171 @@
# Code Signing and Notarization for VibeTunnel
This document explains how to set up code signing and notarization for VibeTunnel to create a distributable macOS app that users can run without security warnings.
## Prerequisites
1. **Apple Developer Program membership** ($99/year)
2. **Developer ID Application certificate** in your Keychain
3. **App Store Connect API key** for notarization
## Setting Up Code Signing
### 1. Developer ID Certificate
You need a "Developer ID Application" certificate from Apple:
1. Go to [Apple Developer Portal](https://developer.apple.com/account/resources/certificates/list)
2. Create a new certificate → Developer ID → Developer ID Application
3. Download and install the certificate in your Keychain
### 2. Environment Variables for Release Signing
For local development team configuration, see [CODE_SIGNING_SETUP.md](CODE_SIGNING_SETUP.md).
For release signing, create a `.env` file in the project root (this file is gitignored):
```bash
# Optional: Specify signing identity (otherwise uses first Developer ID found)
SIGN_IDENTITY="Developer ID Application: Your Name (TEAM123456)"
```
## Setting Up Notarization
### 1. Create App Store Connect API Key
1. Go to [App Store Connect](https://appstoreconnect.apple.com/access/api)
2. Click "Generate API Key"
3. Set role to "Developer"
4. Download the `.p8` file
5. Note the Key ID and Issuer ID
### 2. Environment Variables for Notarization
Add these to your `.env` file:
```bash
# App Store Connect API Key for notarization
APP_STORE_CONNECT_API_KEY_P8="-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQg...
-----END PRIVATE KEY-----"
APP_STORE_CONNECT_KEY_ID="ABC123DEF4"
APP_STORE_CONNECT_ISSUER_ID="12345678-1234-1234-1234-123456789012"
```
## Usage
### Sign Only (for development)
```bash
./scripts/sign-and-notarize.sh --sign-only
```
### Sign and Notarize (for distribution)
```bash
./scripts/sign-and-notarize.sh --sign-and-notarize
```
### Using Individual Scripts
```bash
# Just code signing
./scripts/codesign-app.sh build/Build/Products/Release/VibeTunnel.app
# Just notarization (requires signed app)
./scripts/notarize-app.sh build/Build/Products/Release/VibeTunnel.app
```
## CI/CD Setup (GitHub Actions)
Add these secrets to your GitHub repository:
1. `APP_STORE_CONNECT_API_KEY_P8` - The complete .p8 key content
2. `APP_STORE_CONNECT_KEY_ID` - The Key ID
3. `APP_STORE_CONNECT_ISSUER_ID` - The Issuer ID
The CI workflow will automatically use these for notarization when building on the main branch.
## Script Options
The `sign-and-notarize.sh` script supports various options:
```bash
# Show help
./scripts/sign-and-notarize.sh --help
# Sign and notarize with custom app path
./scripts/sign-and-notarize.sh --app-path path/to/VibeTunnel.app --sign-and-notarize
# Skip stapling (for CI environments where stapling may fail)
./scripts/sign-and-notarize.sh --sign-and-notarize --skip-staple
# Don't create ZIP archive
./scripts/sign-and-notarize.sh --sign-and-notarize --no-zip
# Verbose output for debugging
./scripts/sign-and-notarize.sh --sign-and-notarize --verbose
```
## Troubleshooting
### Code Signing Issues
1. **"No signing identity found"**
- Make sure you have a Developer ID Application certificate installed
- Check with: `security find-identity -v -p codesigning`
2. **"User interaction is not allowed"**
- Unlock your keychain: `security unlock-keychain`
- Or use `security unlock-keychain -p <password> login.keychain`
### Notarization Issues
1. **"Invalid API key"**
- Verify your API key content, ID, and Issuer ID are correct
- Make sure the .p8 key content includes the BEGIN/END lines
2. **"App bundle not eligible for notarization"**
- Ensure the app is properly code signed with hardened runtime
- Check entitlements are properly configured
3. **"Notarization failed"**
- The script will show detailed error messages
- Common issues: unsigned binaries, invalid entitlements, prohibited code
### Testing Signed/Notarized Apps
```bash
# Verify code signature
codesign --verify --verbose=2 VibeTunnel.app
# Test with Gatekeeper (should pass for notarized apps)
spctl -a -t exec -vv VibeTunnel.app
# Check if notarization ticket is stapled
stapler validate VibeTunnel.app
```
## File Structure
After successful signing and notarization:
```
build/
├── Build/Products/Release/VibeTunnel.app # Signed and notarized app
├── VibeTunnel-notarized.zip # Distributable archive
└── VibeTunnel-1.0.0.dmg # DMG (if created)
```
## Security Notes
- Never commit signing certificates or API keys to version control
- Use environment variables or secure CI/CD secrets
- The `.env` file is gitignored for security
- API keys should have minimal required permissions (Developer role)
## References
- [Apple Code Signing Guide](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution)
- [App Store Connect API](https://developer.apple.com/documentation/appstoreconnectapi)
- [notarytool Documentation](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow)

994
docs/spec.md Normal file
View file

@ -0,0 +1,994 @@
# VibeTunnel Technical Specification
## Table of Contents
1. [Executive Summary](#executive-summary)
2. [System Architecture](#system-architecture)
3. [Core Components](#core-components)
4. [Server Implementations](#server-implementations)
5. [Web Frontend](#web-frontend)
6. [Security Model](#security-model)
7. [Session Management](#session-management)
8. [CLI Integration](#cli-integration)
9. [API Specifications](#api-specifications)
10. [User Interface](#user-interface)
11. [Configuration System](#configuration-system)
12. [Build and Release](#build-and-release)
13. [Testing Strategy](#testing-strategy)
14. [Performance Requirements](#performance-requirements)
15. [Error Handling](#error-handling)
16. [Update System](#update-system)
17. [Platform Integration](#platform-integration)
18. [Data Formats](#data-formats)
19. [Networking](#networking)
20. [Future Roadmap](#future-roadmap)
## Executive Summary
### Project Overview
VibeTunnel is a macOS application that provides browser-based access to Mac terminals, designed to make terminal access as simple as opening a web page. The project specifically targets developers and engineers who need to monitor AI agents (like Claude Code) remotely.
### Key Features
- **Zero-Configuration Terminal Access**: Launch terminals with a simple `vt` command
- **Browser-Based Interface**: Access terminals from any modern web browser
- **Real-Time Streaming**: Live terminal updates via WebSocket
- **Session Recording**: Full asciinema format recording support
- **Security Options**: Password protection, localhost-only mode, Tailscale/ngrok integration
- **Multiple Server Backends**: Choice between Swift (Hummingbird) and Rust (tty-fwd) implementations
- **Auto-Updates**: Sparkle framework integration for seamless updates
- **AI Agent Integration**: Special support for Claude Code with shortcuts
### Technical Stack
- **Native App**: Swift 6.0, SwiftUI, macOS 14.0+
- **HTTP Servers**: Hummingbird (Swift), tty-fwd (Rust)
- **Web Frontend**: TypeScript, JavaScript, Tailwind CSS
- **Build System**: Xcode, Swift Package Manager, Cargo
- **Distribution**: Signed/notarized DMG with Sparkle updates
## System Architecture
### High-Level Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ macOS Application │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Menu Bar UI │ │ Server │ │ Session │ │
│ │ (SwiftUI) │──│ Manager │──│ Monitor │ │
│ └─────────────┘ └──────────────┘ └──────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Server Abstraction │ │
│ │ ┌──────────────────┐ ┌──────────────────────┐ │ │
│ │ │ Hummingbird │ │ Rust Server │ │ │
│ │ │ Server │ │ (tty-fwd) │ │ │
│ │ └──────────────────┘ └──────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
├── HTTP API
├── WebSocket
┌─────────────────────────────────────────────────────────────┐
│ Web Browser │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │ Dashboard │ │ Terminal │ │ Asciinema │ │
│ │ View │ │ Interface │ │ Player │ │
│ └──────────────┘ └──────────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
### Component Interaction Flow
1. **Terminal Launch**: User executes `vt` command
2. **Session Creation**: ServerManager creates new terminal session
3. **PTY Allocation**: Server allocates pseudo-terminal
4. **WebSocket Connection**: Browser establishes real-time connection
5. **Data Streaming**: Terminal I/O streams to/from browser
6. **Recording**: Session data recorded in asciinema format
7. **Session Cleanup**: Resources freed on terminal exit
### Design Principles
- **Modularity**: Clean separation between UI, business logic, and server implementations
- **Protocol-Oriented**: Interfaces define contracts between components
- **Thread Safety**: Swift actors ensure concurrent access safety
- **Minimal Dependencies**: Only essential third-party libraries
- **User Privacy**: No telemetry or user tracking
## Core Components
### ServerManager
**Location**: `VibeTunnel/Core/Services/ServerManager.swift`
**Responsibilities**:
- Orchestrates server lifecycle (start/stop/restart)
- Manages server selection (Hummingbird vs Rust)
- Coordinates with other services (Ngrok, SessionMonitor)
- Provides unified API for UI layer
**Key Methods**:
```swift
func startServer(serverType: ServerType) async throws
func stopServer() async
func restartServer() async throws
func getServerURL() -> URL?
func isServerRunning() -> Bool
```
**State Management**:
- Uses Swift actors for thread-safe state updates
- Publishes state changes via Combine
- Maintains server configuration
### SessionMonitor
**Location**: `VibeTunnel/Core/Services/SessionMonitor.swift`
**Responsibilities**:
- Tracks active terminal sessions
- Monitors session lifecycle
- Collects session metrics
- Provides session listing API
**Key Features**:
- Real-time session tracking
- Session metadata management
- Automatic cleanup of terminated sessions
- Performance monitoring
### TerminalManager
**Location**: `VibeTunnel/Core/Services/TerminalManager.swift`
**Responsibilities**:
- Creates new terminal processes
- Manages PTY (pseudo-terminal) allocation
- Handles terminal I/O redirection
- Implements terminal control operations
**Terminal Operations**:
- Shell selection (bash, zsh, fish)
- Environment variable management
- Working directory configuration
- Terminal size handling
### NgrokService
**Location**: `VibeTunnel/Core/Services/NgrokService.swift`
**Responsibilities**:
- Manages ngrok tunnel lifecycle
- Provides secure public URLs
- Handles authentication
- Monitors tunnel status
**Configuration**:
- API key management via Keychain
- Custom domain support
- Region selection
- Protocol configuration
## Server Implementations
### Hummingbird Server (Swift)
**Location**: `VibeTunnel/Core/Services/HummingbirdServer.swift`
**Architecture**:
```swift
protocol ServerProtocol {
func start(port: Int) async throws
func stop() async
var isRunning: Bool { get }
var port: Int? { get }
}
```
**Features**:
- Native Swift implementation
- Async/await concurrency
- Built on SwiftNIO
- Direct macOS integration
**Endpoints**:
- `GET /` - Dashboard HTML
- `GET /api/sessions` - List active sessions
- `POST /api/sessions` - Create new session
- `GET /api/sessions/:id` - Session details
- `DELETE /api/sessions/:id` - Terminate session
- `WS /api/sessions/:id/stream` - Terminal WebSocket
**Middleware Stack**:
1. CORS handling
2. Basic authentication (optional)
3. Request logging
4. Error handling
5. Static file serving
### Rust Server (tty-fwd)
**Location**: Binary embedded in app bundle
**Features**:
- High-performance Rust implementation
- Native PTY handling
- Asciinema recording built-in
- Minimal memory footprint
**Command-Line Interface**:
```bash
tty-fwd --port 9700 \
--auth-mode basic \
--username user \
--password pass \
--allowed-origins "*"
```
**Advantages**:
- Better terminal compatibility
- Lower latency
- Efficient resource usage
- Battle-tested PTY handling
## Web Frontend
### Technology Stack
**Location**: `web/` directory
**Core Technologies**:
- TypeScript for type safety
- Vanilla JavaScript for performance
- Tailwind CSS for styling
- Asciinema player for terminal rendering
- WebSocket API for real-time updates
### Component Architecture
```
web/
├── src/
│ ├── components/
│ │ ├── Dashboard.ts
│ │ ├── SessionList.ts
│ │ ├── TerminalView.ts
│ │ └── SettingsPanel.ts
│ ├── services/
│ │ ├── ApiClient.ts
│ │ ├── WebSocketClient.ts
│ │ └── SessionManager.ts
│ ├── utils/
│ │ ├── Terminal.ts
│ │ └── Authentication.ts
│ └── styles/
│ └── main.css
├── public/
│ ├── index.html
│ └── assets/
└── build/
```
### Key Features
**Dashboard**:
- Real-time session listing
- One-click terminal creation
- Session metadata display
- Server status indicators
**Terminal Interface**:
- Full ANSI color support
- Copy/paste functionality
- Responsive terminal sizing
- Keyboard shortcut support
- Mobile-friendly design
**Performance Optimizations**:
- Lazy loading of terminal sessions
- WebSocket connection pooling
- Efficient DOM updates
- Asset bundling and minification
## Security Model
### Authentication
**Basic Authentication**:
- Username/password protection
- Credentials stored in macOS Keychain
- Secure credential transmission
- Session-based authentication
**Implementation**:
```swift
class LazyBasicAuthMiddleware: HTTPMiddleware {
func intercept(_ request: Request, next: Next) async throws -> Response {
guard requiresAuth(request) else {
return try await next(request)
}
guard let auth = request.headers["Authorization"].first,
validateCredentials(auth) else {
return Response(status: .unauthorized)
}
return try await next(request)
}
}
```
### Network Security
**Access Control**:
- Localhost-only mode by default
- CORS configuration
- IP whitelisting support
- Request rate limiting
**Secure Tunneling**:
- Tailscale integration for VPN access
- Ngrok support for secure public URLs
- TLS encryption for remote connections
- Certificate validation
### System Security
**Privileges**:
- No app sandbox (required for terminal access)
- Hardened runtime enabled
- Code signing with Developer ID
- Notarization for Gatekeeper
**Data Protection**:
- No persistent storage of terminal content
- Session data cleared on termination
- Secure credential storage in Keychain
- No telemetry or analytics
## Session Management
### Session Lifecycle
```
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Created │ --> │ Active │ --> │ Closing │ --> │ Closed │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
│ │
└─────────────── Errored ────────────────────────┘
```
### Session Model
```swift
struct TunnelSession: Identifiable, Codable {
let id: String
let name: String
let command: String
let createdAt: Date
let pid: Int32?
let recordingPath: String?
var status: SessionStatus
var lastActivity: Date
}
```
### Session Operations
**Creation**:
1. Generate unique session ID
2. Allocate PTY
3. Launch shell process
4. Initialize recording
5. Establish WebSocket
**Monitoring**:
- Process status checks
- I/O activity tracking
- Resource usage monitoring
- Automatic timeout handling
**Termination**:
- Graceful process shutdown
- PTY cleanup
- Recording finalization
- WebSocket closure
- Resource deallocation
## CLI Integration
### vt Command Wrapper
**Location**: `Resources/vt`
**Installation**:
```bash
# Automatic installation
/Applications/VibeTunnel.app/Contents/MacOS/VibeTunnel --install-cli
# Manual installation
ln -s /Applications/VibeTunnel.app/Contents/Resources/vt /usr/local/bin/vt
```
**Usage Patterns**:
```bash
# Basic usage
vt
# With custom command
vt -- npm run dev
# Claude integration
vt --claude
vt --claude-yolo
# Custom working directory
vt --cwd /path/to/project
```
### CLI Features
**Command Parsing**:
- Argument forwarding to shell
- Environment variable preservation
- Working directory handling
- Shell selection
**App Integration**:
- Launches VibeTunnel if not running
- Waits for server readiness
- Opens browser automatically
- Returns session URL
## API Specifications
### RESTful API
**Base URL**: `http://localhost:9700`
**Authentication**: Optional Basic Auth
#### Endpoints
**GET /api/sessions**
```json
{
"sessions": [
{
"id": "abc123",
"name": "Terminal 1",
"command": "/bin/zsh",
"createdAt": "2024-01-20T10:30:00Z",
"status": "active"
}
]
}
```
**POST /api/sessions**
```json
// Request
{
"command": "/bin/bash",
"args": ["-c", "echo hello"],
"cwd": "/Users/username",
"env": {
"CUSTOM_VAR": "value"
}
}
// Response
{
"id": "xyz789",
"url": "/sessions/xyz789",
"websocket": "/api/sessions/xyz789/stream"
}
```
**DELETE /api/sessions/:id**
```json
{
"status": "terminated"
}
```
### WebSocket Protocol
**Endpoint**: `/api/sessions/:id/stream`
**Message Format**:
```typescript
interface TerminalMessage {
type: 'data' | 'resize' | 'close';
data?: string; // Base64 encoded for binary safety
cols?: number;
rows?: number;
}
```
**Connection Flow**:
1. Client connects to WebSocket
2. Server sends initial terminal size
3. Bidirectional data flow begins
4. Client sends resize events
5. Server sends close event on termination
## User Interface
### Menu Bar Application
**Components**:
- Status icon with server state
- Quick access menu
- Session listing
- Settings access
- About/Help options
**State Indicators**:
- Gray: Server stopped
- Blue: Server running
- Red: Error state
- Animated: Starting/stopping
### Settings Window
**General Tab**:
- Server selection (Hummingbird/Rust)
- Port configuration
- Auto-start preferences
- Update channel selection
**Security Tab**:
- Authentication toggle
- Username/password fields
- Localhost-only mode
- Allowed origins configuration
**Advanced Tab**:
- Shell selection
- Environment variables
- Terminal preferences
- Debug logging
**Integrations Tab**:
- Ngrok configuration
- Tailscale settings
- CLI installation
- Browser selection
### Design Guidelines
**Visual Design**:
- Native macOS appearance
- System color scheme support
- Consistent spacing (8pt grid)
- SF Symbols for icons
**Interaction Patterns**:
- Immediate feedback for actions
- Confirmation for destructive operations
- Keyboard shortcuts support
- Accessibility compliance
## Configuration System
### User Defaults
**Storage**: `UserDefaults.standard`
**Key Structure**:
```swift
enum UserDefaultsKeys {
static let serverType = "serverType"
static let serverPort = "serverPort"
static let authEnabled = "authEnabled"
static let localhostOnly = "localhostOnly"
static let autoStart = "autoStart"
static let updateChannel = "updateChannel"
}
```
### Keychain Integration
**Secure Storage**:
- Authentication credentials
- Ngrok API tokens
- Session tokens
- Encryption keys
**Implementation**:
```swift
class KeychainService {
func store(_ data: Data, for key: String) throws
func retrieve(for key: String) throws -> Data?
func delete(for key: String) throws
}
```
### Configuration Migration
**Version Handling**:
- Configuration version tracking
- Automatic migration on upgrade
- Backup before migration
- Rollback capability
## Build and Release
### Build System
**Requirements**:
- Xcode 16.0+
- Swift 6.0+
- Rust 1.83.0+
- macOS 14.0+ SDK
**Build Script**: `scripts/build.sh`
```bash
./scripts/build.sh [debug|release] [sign] [notarize]
```
**Build Phases**:
1. Clean previous builds
2. Build Rust components
3. Build Swift application
4. Copy resources
5. Code signing
6. Notarization
7. DMG creation
### Code Signing
**Requirements**:
- Apple Developer ID certificate
- Hardened runtime enabled
- Entitlements configuration
- Notarization credentials
**Entitlements**:
```xml
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
```
### Distribution
**Channels**:
- Direct download from website
- GitHub releases
- Homebrew cask (planned)
- Mac App Store (future)
**Package Format**:
- Signed and notarized DMG
- Universal binary (Intel + Apple Silicon)
- Embedded update framework
- Version metadata
## Testing Strategy
### Unit Tests
**Coverage Areas**:
- Session management logic
- API endpoint handlers
- Configuration handling
- Utility functions
**Test Structure**:
```swift
class SessionManagerTests: XCTestCase {
func testSessionCreation() async throws
func testSessionTermination() async throws
func testConcurrentSessions() async throws
}
```
### Integration Tests
**Server Tests**:
- HTTP endpoint testing
- WebSocket communication
- Authentication flows
- Error scenarios
**Mock Infrastructure**:
```swift
class MockHTTPClient: HTTPClient {
var responses: [URL: Response] = [:]
func send(_ request: Request) async throws -> Response
}
```
### UI Tests
**Scenarios**:
- Menu bar interactions
- Settings window navigation
- Session creation flow
- Error state handling
### Performance Tests
**Metrics**:
- Server startup time < 1s
- Session creation < 100ms
- WebSocket latency < 10ms
- Memory usage < 50MB idle
## Performance Requirements
### Latency Targets
**Terminal I/O**:
- Keystroke to display: < 50ms
- Command execution: < 100ms
- Screen refresh: 60 FPS
**API Response Times**:
- Session list: < 50ms
- Session creation: < 200ms
- Static assets: < 100ms
### Resource Usage
**Memory**:
- Base application: < 50MB
- Per session: < 10MB
- WebSocket buffer: 64KB
**CPU**:
- Idle: < 1%
- Active session: < 5%
- Multiple sessions: Linear scaling
### Scalability
**Concurrent Sessions**:
- Target: 50 simultaneous sessions
- Graceful degradation beyond limit
- Resource pooling for efficiency
## Error Handling
### Error Categories
**User Errors**:
- Invalid configuration
- Authentication failures
- Network issues
- Permission denied
**System Errors**:
- Server startup failures
- PTY allocation errors
- Process spawn failures
- Resource exhaustion
**Recovery Strategies**:
- Automatic retry with backoff
- Graceful degradation
- User notification
- Error logging
### Error Reporting
**User Feedback**:
```swift
enum UserError: LocalizedError {
case serverStartFailed(String)
case authenticationFailed
case sessionCreationFailed(String)
var errorDescription: String? {
switch self {
case .serverStartFailed(let reason):
return "Failed to start server: \(reason)"
// ...
}
}
}
```
**Logging**:
- Structured logging with SwiftLog
- Log levels (debug, info, warning, error)
- Rotating log files
- Privacy-preserving logging
## Update System
### Sparkle Integration
**Configuration**:
```xml
<key>SUFeedURL</key>
<string>https://vibetunnel.sh/appcast.xml</string>
<key>SUEnableAutomaticChecks</key>
<true/>
<key>SUScheduledCheckInterval</key>
<integer>86400</integer>
```
**Update Channels**:
- Stable: Production releases
- Beta: Pre-release testing
- Edge: Nightly builds
### Update Process
**Flow**:
1. Check for updates (daily)
2. Download update in background
3. Verify signature
4. Prompt user for installation
5. Install and restart
**Rollback Support**:
- Previous version backup
- Automatic rollback on crash
- Manual downgrade option
## Platform Integration
### macOS Integration
**System Features**:
- Launch at login
- Dock/menu bar modes
- Notification Center
- Keyboard shortcuts
- Services menu
**Accessibility**:
- VoiceOver support
- Keyboard navigation
- High contrast mode
- Reduced motion
### Shell Integration
**Supported Shells**:
- bash
- zsh (default)
- fish
- sh
- Custom shells
**Environment Setup**:
- Path preservation
- Environment variable forwarding
- Shell configuration sourcing
- Terminal type setting
## Data Formats
### Asciinema Format
**Recording Structure**:
```json
{
"version": 2,
"width": 80,
"height": 24,
"timestamp": 1642694400,
"env": {
"SHELL": "/bin/zsh",
"TERM": "xterm-256color"
}
}
```
**Event Format**:
```json
[timestamp, "o", "output data"]
[timestamp, "i", "input data"]
```
### Session Metadata
**Storage Format**:
```json
{
"id": "session-uuid",
"created": "2024-01-20T10:30:00Z",
"command": "/bin/zsh",
"duration": 3600,
"size": {
"cols": 80,
"rows": 24
}
}
```
## Networking
### Protocol Support
**HTTP/HTTPS**:
- HTTP/1.1 for compatibility
- HTTP/2 support planned
- TLS 1.3 for secure connections
- Certificate pinning option
**WebSocket**:
- RFC 6455 compliant
- Binary frame support
- Ping/pong keepalive
- Automatic reconnection
### Network Configuration
**Firewall Rules**:
- Incoming connections prompt
- Automatic rule creation
- Port range restrictions
- Interface binding options
**Proxy Support**:
- System proxy settings
- Custom proxy configuration
- SOCKS5 support
- Authentication handling
## Future Roadmap
### Version 1.0 Goals
**Core Features**:
- ✅ Basic terminal forwarding
- ✅ Browser interface
- ✅ Session management
- ✅ Security options
- ⏳ Session persistence
- ⏳ Multi-user support
### Version 2.0 Plans
**Advanced Features**:
- Terminal multiplexing
- Session recording playback
- Collaborative sessions
- Terminal sharing
- Cloud synchronization
- Mobile app companion
### Long-term Vision
**Enterprise Features**:
- LDAP/AD integration
- Audit logging
- Compliance reporting
- Role-based access
- Session policies
- Integration APIs
**Platform Expansion**:
- Linux support
- Windows support (WSL)
- iOS/iPadOS app
- Web-based management
- Container deployment
### Technical Debt
**Planned Refactoring**:
- Modularize server implementations
- Extract shared protocol library
- Improve test coverage
- Performance optimizations
- Documentation improvements
## Conclusion
VibeTunnel represents a modern approach to terminal access, combining native macOS development with web technologies to create a seamless user experience. The architecture prioritizes security, performance, and ease of use while maintaining flexibility for future enhancements.
The dual-server implementation strategy provides both performance (Rust) and integration (Swift) options, while the clean architectural boundaries enable independent evolution of components. With careful attention to macOS platform conventions and user expectations, VibeTunnel delivers a professional-grade solution for terminal access needs.
This specification serves as the authoritative reference for understanding, maintaining, and extending the VibeTunnel project. As the project evolves, this document should be updated to reflect architectural decisions, implementation details, and future directions.