Turn any browser into your terminal. VibeTunnel proxies your terminals right into the browser, so you can vibe-code anywhere from any device.
Ever wanted to check on your AI agents while you're away? Need to monitor that long-running build from your phone? Want to share a terminal session with a colleague without complex SSH setups? VibeTunnel makes it happen with zero friction.
VibeTunnel works on both macOS and Linux systems:
- macOS: Requires Apple Silicon Mac (M1+). Intel Macs are not supported.
- Linux: Ubuntu 20.04+, Fedora 35+, Arch Linux, or similar distributions
Download VibeTunnel and drag it to your Applications folder.
VibeTunnel lives in your menu bar. Click the icon to start the server.
# Run any command in the browser
vt pnpm run dev
# Monitor AI agents (with automatic activity tracking)
vt claude --dangerously-skip-permissions
# Control terminal titles
vt --title-mode static npm run dev # Shows path and command
vt --title-mode dynamic python app.py # Shows path, command, and activity
vt --title-mode filter vim # Blocks vim from changing title
# Shell aliases work automatically!
vt claude-danger # Your custom aliases are resolved
# Open an interactive shell
vt --shellVisit http://localhost:4020 to see all your terminal sessions.
- Linux Distribution: Ubuntu 20.04+, Fedora 35+, Arch Linux, or similar
- Node.js: Version 18 or higher
- pnpm: Package manager
- System packages:
curl,jq(for CLI functionality)
# Clone the repository
git clone https://github.com/amantus-ai/vibetunnel.git
cd vibetunnel
# Install dependencies
sudo apt update
sudo apt install nodejs npm curl jq build-essential libpam0g-dev # Ubuntu/Debian
# OR
sudo dnf install nodejs npm curl jq gcc-c++ make pam-devel # Fedora
# OR
sudo pacman -S nodejs npm curl jq base-devel pam # Arch Linux
# Install pnpm
npm install -g pnpm
# Optional: Install Bun for better performance
curl -fsSL https://bun.sh/install | bash
# Build for Linux
cd linux
./build-linux.sh
# Install
cd dist
sudo ./install.sh # System-wide install
# OR
./install.sh # User install to ~/.local# Install system dependencies
sudo apt install nodejs npm curl jq libpam0g-dev # Ubuntu/Debian
# Install pnpm and build web components
npm install -g pnpm
cd web
pnpm install
pnpm run build
# Use development launcher
cd ../linux
./vibetunnel-linux start# Start VibeTunnel server
vibetunnel-linux start # With authentication (secure)
vibetunnel-linux --no-auth start # Without authentication (development)
# Check status
vibetunnel-linux status
# Stop server
vibetunnel-linux stop
# Restart server
vibetunnel-linux restart
# View logs
vibetunnel-linux logs # Recent logs
vibetunnel-linux logs -f # Follow logs in real-time# Interactive shell
vt --shell
# Run specific commands
vt npm run dev # Run development server
vt python app.py # Run Python application
vt htop # System monitor
vt --title-mode static vim file.txt # Edit file with static title
# Control terminal titles (same as macOS)
vt --title-mode dynamic python app.py # Shows path, command, and activity
vt --title-mode static npm run dev # Shows path and command only
vt --title-mode filter vim # Blocks application title changes# Install systemd service
vibetunnel-linux install-service
# Enable auto-start on boot
systemctl --user enable vibetunnel.service
# Start service immediately
systemctl --user start vibetunnel.service
# Check service status
systemctl --user status vibetunnel.service
# View service logs
journalctl --user -u vibetunnel.service -f
# Stop service
systemctl --user stop vibetunnel.service
# Disable auto-start
systemctl --user disable vibetunnel.service# View current configuration
vibetunnel-linux config
# Or use the config manager directly
./config-manager.js show
# Change settings
./config-manager.js set port 8080
./config-manager.js set auth.type password
# Manage encrypted secrets
./config-manager.js set-secret dashboardPassword mypassword
./config-manager.js set-secret ngrokAuthToken your-token
# Reset configuration
./config-manager.js reset
./config-manager.js initSystem Authentication (Default - Recommended):
vibetunnel-linux start
# Uses your Linux username/password via PAMNo Authentication (Development/Testing):
vibetunnel-linux --no-auth start
# Anyone on localhost can access (NOT for production)Dashboard Password:
./config-manager.js set auth.type password
./config-manager.js set-secret dashboardPassword your-secure-password
vibetunnel-linux restartSSH Key Authentication:
./config-manager.js set auth.type ssh-key
vibetunnel-linux restart
# Uses your ~/.ssh/authorized_keysVisit http://localhost:4020 to access your terminal sessions.
- With Authentication: Login with your credentials
- Without Authentication (
--no-auth): Direct access
- 🌐 Browser-Based Access - Control your terminal from any device with a web browser
- 🚀 Zero Configuration - No SSH keys, no port forwarding, no complexity
- 🤖 AI Agent Friendly - Perfect for monitoring Claude Code, ChatGPT, or any terminal-based AI tools
- 📊 Dynamic Terminal Titles - Real-time activity tracking shows what's happening in each session
- 🔒 Secure by Design - Multiple authentication options: PAM, SSH keys, passwords, or no-auth for development
- 📱 Mobile Ready - Native iOS app and responsive web interface for phones and tablets
- 🎬 Session Recording - All sessions recorded in asciinema format for later playback
- ⚡ High Performance - Powered by Bun runtime for blazing-fast JavaScript execution
- 🍎 Apple Silicon Native - Optimized for M1/M2/M3 Macs with ARM64-only binaries
- 🐧 Linux Support - Full Linux port with systemd integration and CLI management
- 🐚 Shell Alias Support - Your custom aliases and shell functions work automatically
- 🔄 Cross-Platform - Same core functionality across macOS and Linux
Note: The iOS app and Tauri-based components are still work in progress and not recommended for production use yet.
VibeTunnel is designed as a cross-platform system with shared core components:
- Node.js/Bun Server - High-performance TypeScript server handling terminal sessions
- Web Frontend - Modern web interface using Lit components and xterm.js
- Terminal Engine - PTY management and session multiplexing
- macOS: Native Swift menu bar application (
mac/) - Linux: CLI launcher with systemd integration (
linux/)
The server runs as a standalone executable with embedded Node.js modules, providing excellent performance and minimal resource usage across both platforms.
All remote access options work on both macOS and Linux systems.
Tailscale creates a secure peer-to-peer VPN network between your devices. It's the most secure option as traffic stays within your private network without exposing VibeTunnel to the public internet.
How it works: Tailscale creates an encrypted WireGuard tunnel between your devices, allowing them to communicate as if they were on the same local network, regardless of their physical location.
Setup Guide:
- Install Tailscale on your server machine:
- macOS: Download from Mac App Store or Direct Download
- Linux:
curl -fsSL https://tailscale.com/install.sh | sh && sudo tailscale up
- Install Tailscale on your remote device:
- iOS: Download from App Store
- Android: Download from Google Play
- Other platforms: All Downloads
- Sign in to both devices with the same account
- Find your server's Tailscale hostname:
- macOS: Check the Tailscale menu bar app
- Linux: Run
tailscale ip -4or checktailscale status
- Access VibeTunnel at
http://[your-tailscale-hostname]:4020
Benefits:
- End-to-end encrypted traffic
- No public internet exposure
- Works behind NAT and firewalls
- Zero configuration after initial setup
ngrok creates secure tunnels to your localhost, making VibeTunnel accessible via a public URL. Perfect for quick sharing or temporary access.
How it works: ngrok establishes a secure tunnel from a public endpoint to your local VibeTunnel server, handling SSL/TLS encryption and providing a unique URL for access.
Setup Guide:
- Create a free ngrok account: Sign up for ngrok
- Copy your auth token from the ngrok dashboard
- Configure the token in VibeTunnel:
- macOS: Add in VibeTunnel settings (Settings → Remote Access → ngrok)
- Linux:
./config-manager.js set-secret ngrokAuthToken your-token
- Enable ngrok tunneling:
- macOS: Toggle in VibeTunnel settings
- Linux:
./config-manager.js set tunneling.ngrok.enabled true
- Restart VibeTunnel to get your
https://[random].ngrok-free.appURL
Benefits:
- Public HTTPS URL with SSL certificate
- No firewall configuration needed
- Built-in request inspection and replay
- Custom domains available (paid plans)
Note: Free ngrok URLs change each time you restart the tunnel. Consider a paid plan for persistent URLs.
- Set a dashboard password:
- macOS: Configure in VibeTunnel settings
- Linux:
./config-manager.js set-secret dashboardPassword yourpassword
- Enable network access:
- macOS: Switch to "Network" mode in settings
- Linux:
./config-manager.js set host 0.0.0.0
- Access via
http://[your-server-ip]:4020
- Install cloudflared
- Run
cloudflared tunnel --url http://localhost:4020 - Access via the generated
*.trycloudflare.comURL
VibeTunnel provides intelligent terminal title management to help you track what's happening in each session:
-
Dynamic Mode (default for web UI): Shows working directory, command, and real-time activity
- Generic activity:
~/projects — npm — • - Claude status:
~/projects — claude — ✻ Crafting (45s, ↑2.1k)
- Generic activity:
-
Static Mode: Shows working directory and command
- Example:
~/projects/app — npm run dev
- Example:
-
Filter Mode: Blocks all title changes from applications
- Useful when you have your own terminal management system
-
None Mode: No title management - applications control their own titles
Dynamic mode includes real-time activity detection:
- Shows
•when there's terminal output within 5 seconds - Claude commands show specific status (Crafting, Transitioning, etc.)
- Extensible system for future app-specific detectors
VibeTunnel's Linux port provides equivalent functionality to the macOS version with Linux-native integrations:
| Feature | macOS | Linux |
|---|---|---|
| GUI | Native SwiftUI menu bar app | CLI-based launcher |
| Authentication | Keychain + PAM | PAM + SSH keys + encrypted file storage |
| Auto-start | LaunchAgent | systemd user service |
| Configuration | macOS preferences | JSON files in ~/.config/vibetunnel/ |
| System Integration | Menu bar, notifications | Command-line interface |
| Process Management | macOS APIs | systemd integration |
| Remote Access | ✅ Tailscale, ngrok, local network | ✅ Tailscale, ngrok, local network |
| Terminal Engine | ✅ Same Node.js/Bun server | ✅ Same Node.js/Bun server |
| Web Interface | ✅ Identical browser experience | ✅ Identical browser experience |
~/.config/vibetunnel/ # User configuration
├── config.json # Main configuration
├── secrets.json # Encrypted secrets (passwords, tokens)
├── vibetunnel.log # Server logs
└── recordings/ # Session recordings
/opt/vibetunnel/ # System installation (optional)
├── vibetunnel-server # Server executable wrapper
├── vibetunnel-linux # Linux launcher
├── vt # VT command
├── config-manager.js # Configuration manager
└── public/ # Web frontend assets
-
System PAM Authentication (Default - Most Secure)
- Uses your Linux user account credentials
- Integrates with system authentication (LDAP, Active Directory, etc.)
- Works with existing user management
-
SSH Key Authentication
- Uses your
~/.ssh/authorized_keys - Perfect for teams with existing SSH key infrastructure
- No password required
- Uses your
-
Dashboard Password
- Simple password-based authentication
- Stored encrypted in
secrets.json - Good for shared systems
-
No Authentication (Development only)
- Use
--no-authflag for testing - Warning: Never use in production or on networks
- Use
Common Issues:
# Port already in use
sudo netstat -tlnp | grep 4020
vibetunnel-linux config set port 8080
# Permission denied
chmod 700 ~/.config/vibetunnel/
chmod 600 ~/.config/vibetunnel/*.json
# Authentication not working
pamtester login $(whoami) authenticate # Test PAM
cat ~/.ssh/authorized_keys # Check SSH keys
# Native modules missing
sudo apt install build-essential python3-dev libpam0g-dev
cd web && pnpm run postinstall
# Reset configuration
./config-manager.js reset
./config-manager.js initDebug Mode:
export VIBETUNNEL_DEBUG=1
vibetunnel-linux start
tail -f ~/.config/vibetunnel/vibetunnel.logFor macOS:
- macOS 14.0+ (Sonoma) on Apple Silicon (M1/M2/M3)
- Xcode 16.0+
- Node.js 20+
- Bun runtime
For Linux:
- Ubuntu 20.04+, Fedora 35+, Arch Linux, or similar
- Node.js 18+
- pnpm package manager
- Build tools:
build-essential,libpam0g-dev
# Clone the repository
git clone https://github.com/amantus-ai/vibetunnel.git
cd vibetunnel
# Build the web server (required for both platforms)
cd web
pnpm install
pnpm run build
cd ..# Set up code signing (required for macOS/iOS development)
# Create Local.xcconfig files with your Apple Developer Team ID
cat > mac/VibeTunnel/Local.xcconfig << EOF
// Local Development Configuration
// DO NOT commit this file to version control
DEVELOPMENT_TEAM = YOUR_TEAM_ID
CODE_SIGN_STYLE = Automatic
EOF
cat > ios/VibeTunnel/Local.xcconfig << EOF
// Local Development Configuration
// DO NOT commit this file to version control
DEVELOPMENT_TEAM = YOUR_TEAM_ID
CODE_SIGN_STYLE = Automatic
EOF
# Build the macOS app
cd mac
./scripts/build.sh --configuration Release# Install Linux dependencies
sudo apt install build-essential libpam0g-dev # Ubuntu/Debian
# OR
sudo dnf install gcc-c++ make pam-devel # Fedora
# OR
sudo pacman -S base-devel pam # Arch Linux
# Build Linux package
cd linux
./build-linux.sh
# Install
cd dist
sudo ./install.sh # System-wide install
# OR
./install.sh # User install to ~/.localVibeTunnel supports building with a custom Node.js for a 46% smaller executable (61MB vs 107MB):
# Build custom Node.js (one-time, ~20 minutes)
node build-custom-node.js
# Use environment variable for all builds
export VIBETUNNEL_USE_CUSTOM_NODE=YES
# Or use in Xcode Build Settings
# Add User-Defined Setting: VIBETUNNEL_USE_CUSTOM_NODE = YESSee Custom Node Build Flags for detailed optimization information.
For development setup and contribution guidelines, see CONTRIBUTING.md.
- macOS App:
mac/VibeTunnel/VibeTunnelApp.swift - Linux Launcher:
linux/vibetunnel-linux - Linux VT Command:
linux/vt - Linux Config Manager:
linux/config-manager.js - Server:
web/src/server/(TypeScript/Node.js) - Web UI:
web/src/client/(Lit/TypeScript) - iOS App:
ios/VibeTunnel/
VibeTunnel has comprehensive test suites with code coverage enabled for all projects:
# Run all tests with coverage
./scripts/test-all-coverage.sh
# macOS tests with coverage (Swift Testing)
cd mac && swift test --enable-code-coverage
# iOS tests with coverage (using xcodebuild)
cd ios && ./scripts/test-with-coverage.sh
# Web tests with coverage (Vitest)
cd web && ./scripts/coverage-report.shCoverage Requirements:
- macOS/iOS: 75% minimum (enforced in CI)
- Web: 80% minimum for lines, functions, branches, and statements
Enable debug logging for troubleshooting:
# Enable debug mode
export VIBETUNNEL_DEBUG=1
# Or use inline
VIBETUNNEL_DEBUG=1 vt your-commandDebug logs are written to ~/.vibetunnel/log.txt.
- Technical Specification - Detailed architecture and implementation
- Contributing Guide - Development setup and guidelines
- Architecture - System design overview
- Build System - Build process details
- Push Notifications - How web push notifications work
- Linux README - Comprehensive Linux-specific documentation
macOS is finicky when it comes to permissions. The system will only remember the first path from where an app requests permissions. If subsequently the app starts somewhere else, it will silently fail. Fix: Delete the entry and restart settings, restart app and next time the permission is requested, there should be an entry in Settings again.
Important: You need to set your Developer ID in Local.xcconfig. If apps are signed Ad-Hoc, each new signing will count as a new app for macOS and the permissions have to be (deleted and) requested again.
Debug vs Release Bundle IDs: The Debug configuration uses a different bundle identifier (sh.vibetunnel.vibetunnel.debug) than Release (sh.vibetunnel.vibetunnel). This allows you to have both versions installed simultaneously, but macOS treats them as separate apps for permissions. You'll need to grant permissions separately for each version.
If that fails, use the terminal to reset:
# This removes Accessibility permission for a specific bundle ID:
sudo tccutil reset Accessibility sh.vibetunnel.vibetunnel
sudo tccutil reset Accessibility sh.vibetunnel.vibetunnel.debug # For debug builds
sudo tccutil reset ScreenCapture sh.vibetunnel.vibetunnel
sudo tccutil reset ScreenCapture sh.vibetunnel.vibetunnel.debug # For debug builds
# This removes all Automation permissions system-wide (cannot target specific apps):
sudo tccutil reset AppleEvents
Love VibeTunnel? Help us keep the terminal vibes flowing! Your support helps us buy pizza and drinks while we keep hacking on your favorite AI agent orchestration platform.
All donations go directly to the development team. Choose your own amount - one-time or monthly! Visit our Polar page to support us.
Created with ❤️ by:
- @badlogic - Mario Zechner
- @mitsuhiko - Armin Ronacher
- @steipete - Peter Steinberger
- @hjanuschka - Helmut Januschka
- @manuelmaly - Manuel Maly
VibeTunnel is open source software licensed under the MIT License. See LICENSE for details.
Ready to vibe?
- macOS: Download VibeTunnel and start tunneling!
- Linux: Clone the repo and run
./linux/build-linux.shto get started!
