Claude Code Remote Control: The Guide Anthropic's 404 Won't Give You
Anthropic's remote control docs page is a 404. Four developers independently built working setups this week. Here's what they made and how to replicate any of them.
The official Anthropic documentation page for Claude Code Remote Control returns a 404. The navigation still shows the link — "Continue local sessions from any device" — but click through and you hit a dead end. Meanwhile, at least four developers independently assembled working remote-control setups in the same week, each solving the same undocumented problem from scratch: a Telegram-wired tmux supervisor, a multi-machine orchestrator, an Android agent, and a Docker security wrapper. This guide consolidates what they built into a single reference covering every layer of the stack, from session persistence to mobile control.
TL;DR: Claude Code sessions die when your terminal closes because the OS sends
SIGHUPon disconnect. tmux is the fix for persistence. Tailscale provides encrypted remote access from any network. For mobile control, the community has built two proven patterns: a Telegram bot bridge (the Leo architecture) and a multi-machine session orchestrator (RCFlow). If you want a turn-key version of this entire stack without maintaining the individual pieces, Grass is the purpose-built alternative.
What Does "Claude Code Remote Control" Actually Mean?
Before setting anything up, it helps to separate remote control into three distinct problems — because each requires a different solution:
- Session persistence — keeping Claude Code running after your terminal or SSH session closes
- Remote network access — reaching that session from a different device or network
- Mobile interaction — approving tool calls, reading agent output, and redirecting the agent from your phone
The Claude Code overview docs describe Remote Control as: "Step away from your desk and keep working from your phone or any browser." The setup page behind that promise is currently gone. A thread in r/ClaudeCode on direct remote control experiences confirms this is a live gap — the 404 is not a caching artifact, and it is actively driving people to piece together their own setups.
This guide covers all three layers in sequence, then presents Grass as a turn-key path that replaces the manual assembly.
Prerequisites
Required:
- Claude Code CLI (
claude) installed and authenticated with your API key - A host machine (laptop, VPS, or cloud VM) where the agent will run
tmuxinstalled (brew install tmuxon macOS,apt install tmuxon Debian/Ubuntu)- Node.js 18+
Optional but recommended:
- Tailscale for encrypted cross-network access (free tier covers this)
- Grass (
npm install -g @grass-ai/ide) for mobile approval forwarding without terminal setup
The core pattern works on macOS, Linux, WSL, and any environment where tmux runs.
Step 1: How Do You Keep a Claude Code Session Alive After Closing Your Terminal?
Claude Code exits when you close your terminal because the OS sends SIGHUP — the "hangup" signal — to all foreground processes when a controlling terminal disconnects. This happens on explicit terminal close, SSH session end, and laptop sleep in some configurations.
tmux (terminal multiplexer) is the standard fix. It runs a server process that owns your shell sessions independently of any terminal. When your terminal closes, tmux intercepts SIGHUP and keeps the session alive.
# Create a named, detached session for a specific project
tmux new-session -d -s claude-myproject -c ~/projects/myproject
# Start Claude Code inside that session
tmux send-keys -t claude-myproject 'claude' Enter
# Close your terminal freely. The session persists.
# Later: list running sessions
tmux list-sessions
# Reattach to continue
tmux attach-session -t claude-myproject
The -d flag starts the session detached so you're not forced into it immediately. Named sessions (-s claude-myproject) let you run parallel projects without tracking session numbers. See how to run Claude Code with tmux for the full multi-window workflow including running parallel agents in separate panes.
One caveat: persistent sessions can outlive their usefulness. If you use --resume to reconnect to old sessions, check for zombie Claude Code processes that are still running and burning quota. Claude Code zombie sessions and the --resume flag covers how to find and kill them before they drain your budget.
Step 2: How Do You Access a Claude Code Session from a Different Network?
tmux keeps the session alive on your host machine. Reaching it from a different device or network requires secure tunneling. Tailscale is the cleanest option for most developers: it creates an encrypted mesh network between your machines with no port forwarding, no firewall rules, and no exposed SSH ports.
# On the host machine:
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh # Linux
brew install --cask tailscale # macOS
# Bring up Tailscale and enable its built-in SSH server
sudo tailscale up --ssh
# From any device on your Tailscale network:
ssh user@your-machine-name.tail1234.ts.net
# Reattach to the running session
tmux attach-session -t claude-myproject
Tailscale SSH authenticates via your Tailscale account instead of requiring manual SSH key management. The --ssh flag enables Tailscale's SSH server so sshd configuration is not required separately.
For a complete setup walkthrough including key-based auth fallbacks and connection troubleshooting, see how to use Tailscale with Claude Code for remote access.
Step 3: How Do You Control Claude Code from Your Phone Without a Terminal?
SSH + tmux works from a phone terminal app. It is not ergonomic for approving tool calls or reading structured agent output on a small screen. Two community-built patterns fill this gap.
The Leo Pattern: Telegram as a Control Plane
A developer described their architecture in a thread on keeping Claude Code sessions running 24/7: they built "Leo" — a tmux-backed process supervisor wired to a Telegram bot. The explicit motivation was that sessions were dying when the shell died, and the only mobile-accessible messaging system they already had was Telegram.
The architecture has three components:
- A tmux session per project running Claude Code
- A supervisor daemon that monitors session health and restarts Claude on exit
- A Telegram bot that bridges prompts in and output out
# Schematic: what a Leo-style supervisor does
while true; do
if ! tmux has-session -t "claude-${PROJECT}" 2>/dev/null; then
tmux new-session -d -s "claude-${PROJECT}" -c "${PROJECT_PATH}"
tmux send-keys -t "claude-${PROJECT}" 'claude' Enter
# notify via Telegram: session restarted
fi
sleep 10
done
The Telegram bot receives your prompt as a message, pipes it into the tmux session via tmux send-keys, and captures stdout back to Telegram. The auto-restart loop means if Claude Code exits unexpectedly — or if you deliberately stop it from Telegram — the supervisor brings it back up without you touching the host machine.
For a side-by-side comparison of Leo against three other community-built control layers (ADHDev, tmux-notify, AIPass), see Leo, ADHDev, tmux-notify, AIPass: 4 DIY Control Layers Compared.
The RCFlow Pattern: Orchestrating 8–10 Sessions Across Machines
For developers running many Claude Code sessions simultaneously, the problem shifts from "keep one session alive" to "don't lose visibility into any session." The RCFlow open-source orchestrator was built for exactly this: the author describes running 8–10 sessions simultaneously with the stated problem being that "important sessions fade out of attention."
RCFlow's architecture separates into server and client components:
Machine A (Linux) ←→
Machine B (macOS) ←→ RCFlow client (unified session dashboard)
Machine C (Windows) ←→
Android device ←→
The server component runs on each machine hosting Claude Code sessions. One client connects to all backends and presents a unified dashboard showing session state across all of them. The cross-platform support matrix — Linux, macOS, Windows, WSL, and Android — reflects the real distribution of machines developers are using as agent hosts.
The Android support is worth noting specifically. One developer took this further: they run Claude Code as a fully autonomous agent on an Android Pixel phone, not just using Android to monitor sessions elsewhere. Any device with compute is a potential Claude Code host, not just a client.
Step 4: What Are the Security Risks in Always-On Docker Setups?
Running Claude Code 24/7 in a Docker container introduces a specific network exposure that is easy to miss. A developer who ran always-on Claude Code containers with remote control for autonomous agents discovered that Docker bridge-networked containers can still reach LAN resources — including router admin interfaces — despite common assumptions about container isolation.
The developer's fix, named "hermit," is a security wrapper that enforces proper network isolation before the agent runs:
# Standard Docker bridge networking — NOT isolated from your LAN
docker run -d --name claude-agent my-claude-image
# The container above can curl http://192.168.1.1 (your router)
# Hermit pattern: use an isolated network with no host routing
docker network create \
--driver bridge \
--internal \
isolated-claude-net
docker run -d \
--name claude-agent \
--network isolated-claude-net \
my-claude-image
# Or: full network isolation if the agent doesn't need outbound internet
docker run -d \
--name claude-agent \
--network none \
my-claude-image
An autonomous agent with unexpected LAN reach is a real, reproducible risk: it can access internal services and administrative interfaces the agent was never meant to touch. If you are running Claude Code autonomously in Docker, verify container networking before deployment.
How Do You Verify Your Remote Setup Is Working?
Test each layer independently before relying on the whole stack.
Session persistence:
# Confirm the session exists
tmux list-sessions
# Expected output: claude-myproject: 1 windows (created Mon May 5 ...)
# Confirm Claude Code is running inside it
tmux attach -t claude-myproject
# You should see Claude's prompt or an active run
# Ctrl+B, D to detach without interrupting
Remote access:
# From a separate device on your Tailscale network
ssh user@your-machine.tail1234.ts.net "tmux list-sessions"
# Should list sessions without a password prompt
Telegram bridge: Send a test prompt to your bot. Expect the message to appear in the tmux session within a few seconds and a Claude response to arrive back in Telegram. If the round-trip fails, check whether the supervisor process itself has exited.
How Grass Makes This Workflow Better
The patterns above work. They are also fragile in specific ways: the Telegram supervisor needs its own process manager, tmux output piping breaks on terminal escape sequences in Claude's output, and Tailscale needs installing and authorizing on every new machine. The total surface area to maintain grows with each agent you add.
Grass is the turn-key version of the same workflow. grass start runs a local HTTP server that exposes Claude Code and OpenCode over a REST + SSE API, with a native mobile app for real-time interaction, structured permission forwarding, and diff review — without assembling the individual pieces.
# Install once
npm install -g @grass-ai/ide
# Start in any project directory
cd ~/projects/myproject
grass start
Starting grass server...
workspace: /Users/you/projects/myproject
port: 32100 (auto-selected from 32100–32199)
available agents: claude-code, opencode
Local Network http://192.168.1.42:32100
[QR code]
Scan to open on your phone
Scan the QR code with the Grass iOS app and you have a native mobile interface to your Claude Code session. The differences from the DIY path are architectural, not cosmetic.
Permission forwarding, not just output mirroring. The Leo/Telegram pattern captures text output from Claude and pipes it to your phone. Grass captures the structured permission_request event — the moment before a tool executes — and surfaces it as a native iOS modal with the exact command highlighted. You approve or deny before the action runs, not after you read about it in a chat message. See how to approve or deny a coding agent action from your phone for how the permission architecture works in practice.
Session persistence built in. Grass sessions survive browser and app disconnects via SSE stream replay using Last-Event-ID. Reconnecting after a WiFi drop replays buffered events from where the stream left off. You do not need to configure tmux separately — though running Claude Code inside a tmux session inside Grass is fine and adds another resilience layer.
Agent-agnostic by design. The same Grass server exposes Claude Code, OpenCode, and any agent added in the future as first-class options. Switching agents on a project is a picker selection, not a new infrastructure setup. The zebbern/claude-code-guide on GitHub catalogs many of the configuration patterns that serious Claude Code users reach for; Grass is the operational layer that keeps those sessions running and reachable.
BYOK. Your Anthropic API key never leaves your machine. Grass is a local HTTP server — there is no cloud relay, no token proxy, no intermediary. Authentication is the key already in your environment.
For cross-network access (reaching a Grass session from a different network, not just local WiFi), the Tailscale + Grass combination described in setting up Grass with a Daytona remote server gives you encrypted remote reach without exposing any ports. For an always-on setup where your laptop doesn't need to be running at all, the Grass cloud VM product at codeongrass.com provisions a persistent VM with Claude Code pre-loaded, accessible from day one — no tmux, no Tailscale, no Docker hardening required.
The best practices for Claude Code documentation covers session hygiene and tool configuration, but the operational question of "how do I keep this running when I'm not at my desk" is the gap that the community — and Grass — has built around.
Troubleshooting Common Issues
Claude Code exits inside tmux after SSH disconnect.
Verify you are running tmux on the remote host, not on your local machine before SSHing. Run echo $TMUX — it should be non-empty when you are inside a tmux session. If it is empty, you have SSHed into a shell that is not inside tmux. Run tmux attach after connecting.
Telegram bot stops receiving messages. The supervisor process itself has likely exited. The supervisor that monitors Claude Code needs its own process manager. Add a systemd service or launchd plist to keep the supervisor alive independently of your shell session — the same principles apply to the supervisor as apply to Claude Code.
RCFlow client cannot connect to a machine.
The RCFlow server component must be reachable on its configured port from the client device. If you are behind a firewall or NAT, bring Tailscale up first and configure RCFlow to bind to the Tailscale interface IP rather than localhost or 0.0.0.0.
Grass QR code connects but immediately disconnects.
Your phone and host machine are likely on different network segments — for example, the host is on a VPN that isolates it from the phone's LAN. Run grass start --network local and verify the IP in the QR code matches your host's LAN IP (e.g., 192.168.x.x), not a VPN tunnel address (e.g., 10.x.x.x).
Docker container reaching LAN resources unexpectedly.
Docker bridge networking does not isolate containers from the host LAN by default. Use --internal network flags or --network none to enforce isolation before running any autonomous agent workload in a container.
FAQ
How do I keep Claude Code running after I close my terminal?
Run Claude Code inside a tmux session. Create a detached session with tmux new-session -d -s claude-myproject, start Claude Code inside it with tmux send-keys -t claude-myproject 'claude' Enter, then close your terminal freely. tmux attach-session -t claude-myproject reconnects you to the live session later. Claude Code continues running regardless of whether any terminal is connected.
Why does Claude Code stop when I disconnect from SSH?
The OS sends SIGHUP (hangup signal) to all foreground processes when an SSH session ends. Claude Code treats this as a terminal disconnect and exits. Running Claude Code inside a tmux session prevents this — tmux owns the process and intercepts SIGHUP before it reaches Claude Code.
What is the Leo pattern for Claude Code remote control? Leo is a community-built setup that pairs tmux session management with a Telegram bot to create mobile-accessible, auto-restarting Claude Code sessions. A supervisor daemon watches for session exits and restarts Claude Code automatically; a Telegram bot bridges prompts from your phone into the tmux session and returns output. The original Leo architecture thread describes the motivation and implementation.
What is RCFlow and when should I use it? RCFlow is an open-source orchestrator for managing multiple Claude Code sessions across multiple machines from a single client interface. It was built by a developer running 8–10 parallel sessions who needed visibility across all of them without losing track of any. It supports Linux, macOS, Windows, WSL, and Android as both server and client targets. Use it when you have more concurrent sessions than you can track in separate terminals.
Is there a turn-key alternative to building a remote control setup from scratch?
Yes. Grass (npm install -g @grass-ai/ide) starts a local server that exposes Claude Code and OpenCode over a REST + SSE API with a native iOS app for mobile interaction, permission forwarding, and diff review. It replaces the tmux supervisor, the Telegram bot bridge, and the output-piping glue code with a single CLI command and a QR code scan.
Start with the minimum viable path: tmux new-session -d -s claude-test && tmux send-keys -t claude-test 'claude' Enter. Close your terminal. Reopen it and run tmux attach -t claude-test. If Claude is still running, your persistence layer works. Add Tailscale for remote access, Leo or RCFlow for mobile control, and Docker hardening if you are running containers — incrementally, one layer at a time.
For the zero-assembly path: install Grass with npm install -g @grass-ai/ide, run grass start in your project directory, and scan the QR code. You get session persistence, mobile permission forwarding, and diff review in under five minutes — without maintaining any of the pieces above yourself.