aigo
v1.2.3
Published
Stream Claude Code to the web - run Claude remotely from any device
Maintainers
Readme
aigo
Stream AI coding assistants to the web - run Claude Code or Cursor Agent remotely from any device.
aigo wraps Claude Code or Cursor Agent in a tmux session and streams it to your browser via WebSocket, letting you access your AI coding sessions from your phone, tablet, or any browser.
Installation
Install aigo from npm:
# Install globally
npm install -g aigo
# Or use npx (no installation required)
npx aigo claudePackage: npmjs.com/package/aigo
Quick Start
# Start Claude Code with web access (ngrok tunnel enabled by default)
aigo claude
# Or start Cursor Agent
aigo cursor
# Local only (no tunnel)
aigo --tunnel none claudeRequirements
- Node.js 18+
- tmux installed and in PATH
- Claude Code CLI installed (
claudecommand) - for Claude Code support - Cursor Agent CLI installed (
agentcommand) - for Cursor support - ngrok (default for remote access) - sign up at ngrok.com
- cloudflared (alternative to ngrok) - free, no signup required
Installing tmux
# macOS
brew install tmux
# Ubuntu/Debian
sudo apt install tmux
# Arch Linux
sudo pacman -S tmuxInstalling ngrok
# macOS
brew install ngrok
# Or download from https://ngrok.com/download
# Then authenticate (required)
ngrok config add-authtoken YOUR_TOKENInstalling cloudflared
cloudflared is a free alternative to ngrok that doesn't require signup:
# macOS
brew install cloudflared
# Ubuntu/Debian
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
# Or download from https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/No authentication required for quick tunnels (trycloudflare.com).
Installing Cursor Agent CLI
# Install Cursor CLI
curl https://cursor.com/install -fsS | bash
# Authenticate (required before first use)
agent login
# Or use API key for headless/automation
export CURSOR_API_KEY=your_api_key_hereUsage
aigo [options] claude [claude-args]
aigo [options] cursor [cursor-args]
aigo [options] agent [agent-args]
aigo [options] --attach <session>
Tools:
claude Use Claude Code CLI
cursor, agent Use Cursor Agent CLI
Options:
--port, -p <port> Web server port (default: 3000, auto-selects if busy)
--session, -s <name> tmux session name (default: claude-code or cursor-agent)
--tunnel, -t <type> Tunnel: ngrok, cloudflared, none (default: ngrok)
--attach, -a <session> Attach to existing tmux session
--password, -P <pass> Custom password (default: auto-generated 6-char)
--timeout, -T <mins> Lock screen after inactivity (default: 0=disabled)
--exit-timeout, -E <mins> Exit session after inactivity (default: 0=disabled)
--help, -h Show help
--version, -v Show versionExamples
# Claude Code Examples (ngrok tunnel by default)
aigo claude # Start Claude with ngrok tunnel
aigo --tunnel none claude # Local only (no tunnel)
aigo -p 8080 -s myproject claude # Custom port and session
aigo claude --model sonnet # Pass args to Claude
# Cursor Agent Examples
aigo cursor # Start Cursor Agent with ngrok tunnel
aigo --tunnel cloudflared cursor # Use cloudflared instead of ngrok
aigo -p 8080 -s myproject cursor # Custom port and session
aigo cursor --model gpt-5 # Pass args to Cursor Agent
# General Examples
aigo --attach myproject # Attach to existing tmux session
aigo -P mypass123 claude # Custom password
aigo -T 15 -E 30 cursor # 15min lock, 30min exit timeout
aigo -T 0 -E 0 claude # Disable timeouts (default behavior)
# Run multiple sessions (ports auto-selected)
aigo -s project-a claude # Gets port 3000
aigo -s project-b cursor # Gets port 3001 (auto)Configuration
All defaults can be customized by editing lib/config.js:
export const config = {
// Server Settings
defaultPort: 3000,
defaultTunnel: 'ngrok', // 'ngrok', 'cloudflared', or 'none'
// Session Timeouts (minutes, 0 = disabled)
lockTimeout: 0, // Lock screen after inactivity (default: disabled)
exitTimeout: 0, // Exit session after inactivity (default: disabled)
// Tool Settings
defaultTool: 'claude', // 'claude' or 'cursor'
// Security Settings
passwordLength: 6,
tokenBytes: 2, // URL token length (hex = 2x chars)
// ... more options
};Tunnel Options
aigo supports two tunnel providers for remote access:
| Feature | ngrok | cloudflared |
|---------|-------|-------------|
| Signup required | Yes | No |
| Free tier limits | 1 tunnel, rate limits | Unlimited quick tunnels |
| Custom domains | Paid plans | Requires Cloudflare account |
| URL format | *.ngrok-free.app | *.trycloudflare.com |
| Authentication | Required (authtoken) | Not required |
Recommendation: Use cloudflared for quick testing (no signup needed). Use ngrok if you need stable URLs or have an existing account.
# Use cloudflared (no signup required)
aigo --tunnel cloudflared claude
# Use ngrok (default, requires signup)
aigo claude
# Local only (no tunnel)
aigo --tunnel none claudeHow It Works
- aigo creates a tmux session and runs
claudeoragentinside it - A local web server starts, serving an xterm.js terminal
- The server attaches to the tmux session via node-pty
- Your browser connects via WebSocket for real-time terminal streaming
- A tunnel (ngrok or cloudflared) creates a public HTTPS URL for remote access
┌────────────────────────────────────────┐
│ aigo - Claude Code Web Terminal │
├────────────────────────────────────────┤
│ Session: claude-code │
│ Local: http://localhost:3000 │
│ Tunnel: https://abc123.ngrok.io │
│ Password: Xk7mNp │
│ Timeout: lock:off exit:off │
└────────────────────────────────────────┘
Access URL:
https://abc123.ngrok.io/t/a1b2c3d4...Cursor vs Claude Code
| Feature | Claude Code | Cursor Agent |
|---------|-------------|--------------|
| Command | aigo claude | aigo cursor |
| CLI Binary | claude | agent |
| Authentication | Claude API key / OAuth | Browser login or CURSOR_API_KEY |
| Models | Claude models | Multiple (GPT-5, Claude, etc.) via subscription |
| Session Default | claude-code | cursor-agent |
When to use Cursor: If you have a Cursor subscription but don't have direct Claude API access, Cursor Agent provides an alternative way to access AI coding assistance remotely.
Security
aigo uses multiple layers of security:
- URL Token - A random 4-character token in the URL path (
/t/<token>) - Password - A 6-character alphanumeric password (or custom password via
-P) - Brute-Force Protection - Progressive delays and lockout after failed attempts
- Session Lock - Screen locks after inactivity (disabled by default, enable with
-T <mins>) - Auto Exit - Session terminates after inactivity (disabled by default, enable with
-E <mins>)
Security features:
- Token required in URL (403 Forbidden without it)
- Password required before terminal access
- Password uses unambiguous characters (no 0/O, 1/l/I)
- Brute-force protection with progressive delays (see below)
- Lock screen requires re-entering password after inactivity (when enabled)
- Session auto-terminates and kills tmux after extended inactivity (when enabled)
- HTTPS via tunnel (encrypted in transit)
Brute-Force Protection
aigo automatically protects against password brute-force attacks with:
- Progressive delays after 5 failed attempts
- IP-based tracking that persists across page refreshes
- 15-minute lockout after 10 failed attempts
| Attempt | Behavior | |---------|----------| | 1-4 | Instant response | | 5 | 1 second wait (input disabled, countdown shown) | | 6 | 2 second wait | | 7 | 4 second wait | | 8 | 8 second wait | | 9 | 16 second wait | | 10+ | IP locked out for 15 minutes |
After 5 failed attempts, the password input is disabled and a countdown timer shows the remaining wait time. After 10 failed attempts, the IP address is locked out for 15 minutes - refreshing the page won't reset the counter.
Configure in lib/config.js:
maxAuthAttempts: 10, // Lock out IP after this many failures
authDelayThreshold: 5, // Start delays after this many failures
authBaseDelayMs: 1000, // Base delay (doubles each attempt)
authLockoutMins: 15, // Lockout duration after max attemptsRecommendations:
- Use HTTPS (both ngrok and cloudflared provide this automatically)
- Don't share your access URL or password publicly
- Use strong custom passwords for sensitive sessions
- Enable timeouts (
-T 15 -E 30) for shared or sensitive environments
Session Timeouts
aigo has two optional timeout mechanisms (both disabled by default for persistent sessions):
Lock Timeout (default: disabled)
When enabled with -T <minutes>, the session locks after the specified period of no interaction (mouse movement, typing, etc.) and requires password re-entry. The WebSocket connection stays open, so you don't lose any terminal state.
Exit Timeout (default: disabled)
When enabled with -E <minutes>, the session completely terminates after the specified period of total inactivity (no user login or interaction):
- The tmux session is killed
- Claude Code / Cursor Agent is stopped
- The server exits
Enable timeouts for security in shared environments: aigo -T 15 -E 30 claude
Browser Notifications
aigo can send browser notifications when:
- The AI assistant is waiting for input
- The WebSocket connection is lost
Notifications are only sent when the browser tab is not active. Allow notifications when prompted for the best experience.
Mobile Controls
When accessing aigo from a mobile device (phone or tablet), control buttons appear at the bottom of the screen:
| Button | Action | Description |
|--------|--------|-------------|
| History | View Buffer | Opens a fullscreen modal showing the terminal scrollback buffer (useful when TUI scrolling doesn't work on mobile) |
| Mode | Shift+Tab | Toggle between chat/edit modes in Claude Code or switch modes in Cursor Agent |
| Enter | Enter | Send Enter key to confirm prompts or submit input |
| Stop | Ctrl+C | Interrupt the current operation (stop running commands or cancel AI responses) |
These buttons are useful because mobile keyboards don't easily support modifier key combinations like Ctrl+C or Shift+Tab.
History Button
The History button is particularly useful on mobile devices where terminal scrolling often doesn't work properly with TUI applications like Claude Code or Cursor Agent. When pressed:
- Opens a fullscreen modal overlay
- Captures the entire terminal scrollback buffer from tmux
- Displays the content in a scrollable view with ANSI codes stripped for readability
- Press Close or the ESC key to return to the terminal
This provides an alternative way to review previous AI responses and conversation history without relying on terminal scrolling.
The buttons are automatically shown based on:
- Touch screen capability
- Mobile user agent detection
- Screen width (768px or less)
- Coarse pointer media query (touch screens)
Running Persistently
To keep aigo running indefinitely (even after closing your terminal), run it inside tmux or use a process manager:
# Run aigo inside its own tmux session
tmux new-session -d -s aigo-server 'aigo claude'
# Attach to check status
tmux attach -t aigo-server
# Or use pm2 for auto-restart on crash
pm2 start "aigo claude" --name aigo-sessionWhen the aigo server stays running, your tunnel URL remains stable and you can return to the same URL anytime. Note: cloudflared quick tunnel URLs change on restart, while ngrok URLs persist within a session.
Auto Port Selection
If the default port (3000) or your specified port is already in use, aigo automatically finds the next available port:
⚠ Port 3000 in use, using port 3001 insteadThis allows running multiple aigo sessions simultaneously without manual port management.
Exiting and Cleanup
aigo provides different exit behaviors depending on how you terminate the session:
Exit Behavior Summary
| Action | tmux Session | Server | Web Clients | |--------|-------------|--------|-------------| | Web Exit button | Killed | Stopped | Shows "Session Ended" | | Console Ctrl+C | Persists | Stopped | Disconnected | | Inactivity timeout | Killed | Stopped | Shows "Session Expired" |
Full Cleanup (from web interface)
Click the Exit button in the top-right corner of the web interface to:
- Show a confirmation dialog
- Kill the PTY process
- Kill the tmux session
- Close all WebSocket connections
- Shut down the aigo server
- Exit the process
Result: Everything is cleaned up - tmux session, server, and process all terminate. The web client shows a "Session Ended" message.
This is useful when you're completely done with a session and want to free all resources.
Session Persistence (Ctrl+C on console)
When you press Ctrl+C on the terminal running aigo:
- The web server stops
- The tunnel closes (if running)
- The tmux session keeps running!
- Connected web clients are disconnected
Result: Server stops but the tmux session persists. This is useful when you want to temporarily stop web access but keep the AI session alive.
Re-attach later:
# Via aigo (starts new web server for existing session)
aigo --attach claude-code
aigo --attach cursor-agent
# Or directly with tmux (local terminal only)
tmux attach -t claude-code
tmux attach -t cursor-agentInactivity Timeout Exit
When the exit timeout is enabled and reached:
- Server detects no user activity for the configured duration
- Kills the tmux session
- Notifies all connected clients with "Session Expired" message
- Closes all WebSocket connections
- Shuts down the server
- Exits the process
Result: Full cleanup, similar to web exit. Web clients see a "Session Expired" overlay.
Note: Exit timeout is disabled by default. Enable with --exit-timeout <mins> or -E <mins> for security in shared environments.
Troubleshooting
"tmux: command not found"
Install tmux (see Requirements section above).
"claude: command not found"
Make sure Claude Code CLI is installed and in your PATH:
# Check if claude is available
which claude"agent: command not found" (Cursor)
Install the Cursor Agent CLI:
# Install
curl https://cursor.com/install -fsS | bash
# Verify installation
which agentCursor authentication issues
Make sure you're authenticated:
# Interactive login (opens browser)
agent login
# Check status
agent status
# Or use API key
export CURSOR_API_KEY=your_api_key_here"posix_spawnp failed" error
This can happen if node-pty's spawn-helper isn't executable. Fix with:
chmod +x node_modules/node-pty/prebuilds/darwin-*/spawn-helperOr reinstall dependencies:
rm -rf node_modules && npm installngrok authentication error
Sign up at ngrok.com and authenticate:
ngrok config add-authtoken YOUR_TOKEN"ngrok already running" / simultaneous session error
Free ngrok accounts are limited to 1 simultaneous tunnel. If you see this error, it means an ngrok process from a previous session is still running.
aigo will detect this and show you the command to kill it:
Error: An ngrok process is already running.
Free ngrok accounts only allow 1 simultaneous tunnel.
To kill the existing ngrok process, run:
kill 12345
Or to run without a tunnel:
aigo --tunnel none cursorYou can also find and kill ngrok manually:
# Find ngrok processes
pgrep -f "ngrok http"
# Kill by PID
kill <pid>
# Or kill all ngrok processes
pkill -f "ngrok http"cloudflared connection issues
If cloudflared fails to connect:
# Check if cloudflared is installed
which cloudflared
# Test a quick tunnel manually
cloudflared tunnel --url http://localhost:3000
# Check for firewall issues (verbose output)
cloudflared tunnel --url http://localhost:3000 --loglevel debugWebSocket connection fails
- Check that the server is running
- Ensure the URL includes the correct token
- If using a tunnel, make sure it's still active
Terminal looks broken / garbled
Try resizing your browser window to trigger a terminal resize.
Development
# Clone the repository
git clone <repository-url>
cd aigo
# Install dependencies
npm install
# Run without installing globally
node bin/vigo.js claude
node bin/vigo.js cursor
# Watch for changes (requires nodemon)
npx nodemon bin/vigo.js claudePublishing
Bump the minor version and publish to npm:
make publish-minor # bump minor (e.g. 1.0.1 → 1.1.0), then publish
make publish-patch # bump patch (e.g. 1.0.1 → 1.0.2), then publishEach runs npm version minor or npm version patch (updates package.json and creates a git commit/tag) then npm publish.
License
MIT
