mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-03-25 09:25:50 +00:00
5.6 KiB
5.6 KiB
Development Guide
Setup
Prerequisites
- macOS 14.0+
- Xcode 16.0+
- Node.js 18+
- Bun 1.0+
Clone & Build
# Clone repository
git clone https://github.com/steipete/vibetunnel
cd vibetunnel
# Install dependencies
cd web && pnpm install && cd ..
# Build everything
./scripts/build-all.sh
# Or build individually
cd mac && ./scripts/build.sh
cd ios && xcodebuild
cd web && pnpm build
Project Structure
vibetunnel/
├── mac/ # macOS app
│ ├── VibeTunnel/ # Swift sources
│ │ ├── Core/ # Business logic
│ │ └── Presentation/ # UI layer
│ └── scripts/ # Build scripts
├── ios/ # iOS app
│ └── VibeTunnel/ # Swift sources
└── web/ # Server & frontend
├── src/
│ ├── server/ # Node.js server
│ └── client/ # Web UI
└── scripts/ # Utilities
Code Patterns
Swift (macOS/iOS)
Observable Pattern
// mac/VibeTunnel/Core/Services/ServerManager.swift
@MainActor
@Observable
class ServerManager {
private(set) var isRunning = false
private(set) var error: Error?
}
Protocol-Oriented Design
// mac/VibeTunnel/Core/Protocols/VibeTunnelServer.swift
@MainActor
protocol VibeTunnelServer: AnyObject {
var isRunning: Bool { get }
func start() async throws
func stop() async
}
Error Handling
enum ServerError: LocalizedError {
case portInUse(Int)
case binaryNotFound(String)
var errorDescription: String? {
switch self {
case .portInUse(let port):
return "Port \(port) is already in use"
case .binaryNotFound(let path):
return "Server binary not found at \(path)"
}
}
}
TypeScript (Web)
Service Classes
// web/src/server/services/terminal-manager.ts
export class TerminalManager {
private sessions = new Map<string, Session>();
async createSession(options: SessionOptions): Promise<Session> {
const session = new Session(options);
this.sessions.set(session.id, session);
return session;
}
}
Lit Components
// web/src/client/components/terminal-view.ts
@customElement('terminal-view')
export class TerminalView extends LitElement {
@property({ type: String }) sessionId = '';
@state() private connected = false;
createRenderRoot() {
return this; // No shadow DOM for Tailwind
}
}
Development Workflow
Hot Reload Setup
Web Development
# Terminal 1: Run dev server
cd web && pnpm dev
# Terminal 2: Enable in Mac app
# Settings → Debug → Use Development Server
Swift Development with Poltergeist
# Install Poltergeist if available
poltergeist
# Auto-rebuilds on file changes
# Check menu bar for build status
Testing
Unit Tests
# macOS
cd mac && xcodebuild test
# iOS
cd ios && ./scripts/test-with-coverage.sh
# Web
cd web && pnpm test
E2E Tests
cd web && pnpm test:e2e
Debugging
View Logs
./scripts/vtlog.sh -n 100 # Last 100 lines
./scripts/vtlog.sh -e # Errors only
./scripts/vtlog.sh -c Server # Component filter
Debug Server
# Run server directly
cd web && pnpm dev:server
# With inspector
node --inspect dist/server/server.js
Common Tasks
Add New API Endpoint
- Define in
web/src/server/routes/api.ts - Add types in
web/src/shared/types.ts - Update client in
web/src/client/services/api.ts - Add tests in
web/tests/api.test.ts
Add New Menu Item
- Update
mac/VibeTunnel/Presentation/MenuBarView.swift - Add action in
mac/VibeTunnel/Core/Actions/ - Update settings if needed
Modify Terminal Protocol
- Update
web/src/server/services/buffer-aggregator.ts - Modify
web/src/client/services/websocket.ts - Test with
web/tests/protocol.test.ts
Build System
macOS Build
cd mac
./scripts/build.sh # Release build
./scripts/build.sh --configuration Debug
./scripts/build.sh --sign # With signing
Web Build
cd web
pnpm build # Production build
pnpm build:server # Server only
pnpm build:client # Client only
Release Build
./scripts/release.sh 1.0.0 # Full release
Code Quality
Linting
# Swift
cd mac && ./scripts/lint.sh
# TypeScript
cd web && pnpm lint
cd web && pnpm check:fix
Formatting
# Swift (SwiftFormat)
swiftformat mac/ ios/
# TypeScript (Prettier)
cd web && pnpm format
Performance
Profiling
# Server performance
node --prof dist/server/server.js
node --prof-process isolate-*.log
# Client performance
# Use Chrome DevTools Performance tab
Optimization Tips
- Use binary protocol for terminal data
- Batch WebSocket messages (16ms intervals)
- Lazy load terminal sessions
- Cache static assets with service worker
Troubleshooting
| Issue | Solution |
|---|---|
| Port in use | lsof -i :4020 then kill process |
| Build fails | Clean: rm -rf node_modules dist |
| Tests fail | Check Node/Bun version |
| Hot reload broken | Restart dev server |
Contributing
- Fork repository
- Create feature branch
- Follow code style
- Add tests
- Update documentation
- Submit PR