Control Claude Code CLI from your phone browser, anywhere. Continue sessions seamlessly between Mac and phone.
Your Mac runs a Go server that wraps Claude Code in a pseudo-terminal. Your phone connects through Tailscale VPN and interacts via a mobile-optimized chat UI. Ask Claude to "handoff to phone" — scan QR to continue your session.
- Session handoff — ask Claude "handoff to phone", scan QR, continue on phone
- Two handoff modes — attach to running terminal (like tmux) or continue with full conversation history
- MCP integration — claude-remote runs as both web server and MCP server for Claude Code
- Folder picker — browse Desktop/Downloads/Documents, choose working directory
- Chat UI — native text input with IME support, colored terminal output with smooth native scrolling
- Quick actions — Enter, Accept (y), Reject (n), Esc, Ctrl+C buttons for Claude's prompts
- QR auth — scan once, JWT cookie lasts 90 days
- Tailscale HTTPS — encrypted VPN mesh, no port forwarding needed
- Auto-start — launchd keeps server running on Mac boot
# Prerequisites: Go 1.25+, Tailscale on Mac + phone
# Build
make build
# First-time setup
./claude-remote setup # generates QR code
./claude-remote serve # start server
# Scan QR with phone → open URL → pick folder → start Claude# Build binary
make build
# Copy to ~/bin (or /usr/local/bin with sudo)
mkdir -p ~/bin
cp claude-remote ~/bin/
cp -r static ~/bin/static
# Setup Tailscale HTTPS
sudo tailscale cert $(tailscale status --json | jq -r '.Self.DNSName' | sed 's/\.$//')
mkdir -p ~/.claude-remote
sudo cp ~/Desktop/*.crt ~/Desktop/*.key ~/.claude-remote/
sudo chown $(whoami) ~/.claude-remote/*.key ~/.claude-remote/*.crt
# Install launchd service (auto-start on boot)
# Edit the plist to point to your binary path, then:
mkdir -p ~/Library/LaunchAgents
cp launchd/com.claude-remote.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.claude-remote.plist
# Set absolute path to claude binary in config
cat ~/.claude-remote/config.json
# Ensure "claude_path" points to the full path, e.g.:
# "claude_path": "/Users/yourname/.local/bin/claude"
# Generate QR for first-time phone auth
claude-remote setup
# Register MCP with Claude Code (one-time, user scope)
claude mcp add --transport http -s user claude-remote http://127.0.0.1:8823/mcpThe launchd plist must include the directory containing the claude binary in its PATH. Example for ~/.local/bin/claude:
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/Users/yourname/.local/bin:/Users/yourname/bin:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
<key>HOME</key>
<string>/Users/yourname</string>
</dict>The killer feature: continue Claude Code sessions on your phone.
Mac (Claude Code) Phone (browser)
┌──────────────────────┐
│ > working on feature │
│ > "handoff to phone" │
│ │
│ ████████████████ │ Scan QR
│ ████████████████ │ ────────────► ┌──────────────────┐
│ ████████████████ │ │ Continue from │
│ │ │ computer │
│ Scan to continue │ │ │
│ on phone │ │ [🔗 Attach] │
└──────────────────────┘ │ [📋 Continue] │
│ [📁 New folder] │
└──────────────────┘
Attach — connect to the same running terminal. See live output, type into the same session. Like tmux attach.
Continue — start a new Claude session with --continue flag. Gets full conversation history from the previous session in the same directory.
- Ask Claude to "handoff to phone" (Claude calls the MCP
handofftool) - Claude generates a QR code with a one-time token (expires 15 min)
- Scan with phone camera
- Phone opens claude-remote web UI, auto-authenticates via token
- Choose mode: attach or continue
- Start working on phone
The MCP handoff tool is registered globally. In any Claude Code session (CLI, VS Code, Cursor), just ask:
- "handoff to phone"
- "generate QR for phone"
- "transfer session to phone"
Claude will call the handoff MCP tool and display the QR code.
In Claude Code CLI, the /handoff skill also works (requires the skill file in .claude/skills/ or ~/.claude/skills/).
Tailscale creates a private VPN mesh so your phone can reach your Mac from anywhere — no port forwarding, no public IP needed.
- Mac: Download from tailscale.com/download or
brew install tailscale - Phone (iOS): App Store → search "Tailscale"
- Phone (Android): Play Store → search "Tailscale"
Sign in with the same account on both devices.
Go to Tailscale admin console → enable MagicDNS. This gives your Mac a stable hostname like macbook-pro.tail1234.ts.net.
# Get your Mac's Tailscale hostname
tailscale status
# Generate TLS cert (requires sudo)
sudo tailscale cert <your-hostname>.ts.net
# Copy to config dir:
mkdir -p ~/.claude-remote
sudo cp ~/Desktop/<your-hostname>.ts.net.crt ~/.claude-remote/
sudo cp ~/Desktop/<your-hostname>.ts.net.key ~/.claude-remote/
sudo chown $(whoami) ~/.claude-remote/*.key ~/.claude-remote/*.crtOn your phone (connected to Tailscale):
- Open Safari/Chrome →
https://<your-hostname>.ts.net:8822/health - Should show
{"status":"ok","version":"0.1.0"}
Phone (chat UI)
↕ WebSocket over Tailscale HTTPS (:8822)
Mac (Go server)
↕ pseudo-terminal
Claude Code CLI
Claude Code (MCP client)
↕ JSON-RPC over HTTP (:8823, localhost only)
Mac (Go server /mcp endpoint)
→ generates QR + handoff token
Two listeners when TLS is active:
- Port 8822 (HTTPS, all interfaces) — web UI for phone, static files public, API/WS protected by JWT
- Port 8823 (HTTP, 127.0.0.1 only) — MCP endpoint for Claude Code
Without TLS certs, falls back to single HTTP listener on 8822.
| Command | Description |
|---|---|
setup |
Generate secret + QR code for first-time auth |
serve |
Start server (foreground) |
revoke |
Regenerate secret, invalidate all sessions |
install |
Install launchd plist + load |
uninstall |
Unload + remove launchd plist |
status |
Show running state |
Old cookie with invalid signature. Clear cookies for the site in phone browser settings, then scan a new QR code.
Claude process failed to start. Check:
~/.claude-remote/config.json—claude_pathmust be absolute (e.g.,/Users/you/.local/bin/claude)~/.claude-remote/server.log— look for "Claude start failed" or "claude process exited"claude auth status— verify Claude Code is authenticated
- Check Tailscale is connected on both devices:
tailscale status - Verify health:
https://<hostname>.ts.net:8822/health - Check server logs:
tail -f ~/.claude-remote/server.log
MCP uses HTTP on port 8823 (localhost only). Verify:
curl http://127.0.0.1:8823/health
# Should return {"status":"ok"}- Go — single binary, no runtime deps
- Tailscale — secure networking
- MCP — Streamable HTTP (JSON-RPC) for Claude Code integration
- xterm.js — ANSI processing (hidden, cell-by-cell rendering)
- Vanilla JS — no framework, no build step
If you find this useful, consider buying me a coffee: