Skip to content

wakandan/aigo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

Quick Start

# Install dependencies
npm install

# Install globally (optional)
npm link

# 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 claude

Requirements

  • Node.js 18+
  • tmux installed and in PATH
  • Claude Code CLI installed (claude command) - for Claude Code support
  • Cursor Agent CLI installed (agent command) - 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 tmux

Installing ngrok

# macOS
brew install ngrok

# Or download from https://ngrok.com/download

# Then authenticate (required)
ngrok config add-authtoken YOUR_TOKEN

Installing 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_here

Usage

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 version

Examples

# 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 claude

How It Works

  1. aigo creates a tmux session and runs claude or agent inside it
  2. A local web server starts, serving an xterm.js terminal
  3. The server attaches to the tmux session via node-pty
  4. Your browser connects via WebSocket for real-time terminal streaming
  5. 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:

  1. URL Token - A random 4-character token in the URL path (/t/<token>)
  2. Password - A 6-character alphanumeric password (or custom password via -P)
  3. Brute-Force Protection - Progressive delays and lockout after failed attempts
  4. Session Lock - Screen locks after inactivity (disabled by default, enable with -T <mins>)
  5. 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 attempts

Recommendations:

  • 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:

  1. Opens a fullscreen modal overlay
  2. Captures the entire terminal scrollback buffer from tmux
  3. Displays the content in a scrollable view with ANSI codes stripped for readability
  4. 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-session

When 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 instead

This 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:

  1. Show a confirmation dialog
  2. Kill the PTY process
  3. Kill the tmux session
  4. Close all WebSocket connections
  5. Shut down the aigo server
  6. 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:

  1. The web server stops
  2. The tunnel closes (if running)
  3. The tmux session keeps running!
  4. 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-agent

Inactivity Timeout Exit

When the exit timeout is enabled and reached:

  1. Server detects no user activity for the configured duration
  2. Kills the tmux session
  3. Notifies all connected clients with "Session Expired" message
  4. Closes all WebSocket connections
  5. Shuts down the server
  6. 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 agent

Cursor 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-helper

Or reinstall dependencies:

rm -rf node_modules && npm install

ngrok 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 cursor

You 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 debug

WebSocket 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

# Run without installing globally
node bin/aigo.js claude
node bin/aigo.js cursor

# Watch for changes (requires nodemon)
npx nodemon bin/aigo.js claude

Publishing

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 publish

Each runs npm version minor or npm version patch (updates package.json and creates a git commit/tag) then npm publish.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published