Keep Claude Code Running After SSH Disconnects (tmux Guide)
Claude Code exits when you close your terminal because it receives SIGHUP. tmux is the fix — here's how to set it up, detach, and reconnect, with screen and nohup as alternatives.
Claude Code exits when you close your SSH session or terminal because closing the connection sends a SIGHUP signal to every process in the terminal's process group — and Claude Code, like any foreground terminal process, exits on SIGHUP. The fix is tmux (terminal multiplexer), which keeps a session running on the server even after the SSH client disconnects. This guide covers the complete reliability stack: sleep prevention for local machines, tmux for SSH sessions, Daytona cloud VMs for always-on requirements, and Grass for monitoring long-running agents from your phone.
TL;DR:
tmux new -s claude, start Claude Code inside, thenCtrl+B Dto detach. Your session survives SSH disconnects. For Dynamic Workflows or multi-hour orchestrations that cannot tolerate a sleeping laptop, run on a Daytona cloud VM instead — it never disconnects, never sleeps, and never closes a lid.
Why This Problem Got Mission-Critical in 2026
In 2025, losing a Claude Code session was annoying. In 2026, it can mean losing hours of orchestrated work. Claude Code Dynamic Workflows, launched May 28, 2026, let a single prompt fan out to hundreds of parallel subagents — each reading files, running tools, and verifying findings. Anthropic described workflows as built for work that "extends into hours and days, doing the most complex engineering work that previously would have taken weeks." Jarred Sumner's Bun Zig→Rust rewrite used an overnight workflow phase to process 750,000 lines across 11 days.
All of that state is session-scoped. If the host Claude Code process exits partway through, orchestration progress is lost. The 99.9th percentile Claude Code turn duration already exceeded 45 minutes as of early 2026. A multi-hour Dynamic Workflow on a laptop that sleeps partway through means you restart the entire orchestration from zero.
This is why "keep it alive" moved from a personal workflow preference to infrastructure. The guide is organized as a four-layer stack — fix the problem at whichever layer makes sense for your setup.
What Actually Causes Claude Code to Stop?
Claude Code, Codex CLI, and Grok Build all die on SSH disconnect for the same reason: they are foreground terminal processes. When an SSH connection drops, the kernel sends SIGHUP (signal 1 — "hangup") to the controlling terminal's entire process group. Foreground processes that don't explicitly handle SIGHUP exit immediately. This is correct POSIX behavior, not a Claude Code bug.
Three distinct events trigger SIGHUP:
- SSH disconnect — network drops, client closes,
Connection reset by peer - Terminal window closed — closing iTerm, Terminal.app, or any terminal emulator
- SSH timeout — server-side
ClientAliveInterval/ClientAliveCountMaxsettings
On a local machine (not SSH), there are two additional failure modes:
- macOS lid-close — the system suspends processes before network drops
- macOS idle sleep — after idle timeout, the CPU suspends and network is lost
Each failure mode needs a different fix.
The Four-Layer Reliability Stack
| Layer | Problem Solved | Tool | When to Use |
|---|---|---|---|
| 1 | Mac lid-close / idle sleep | caffeinate or Claude Code hooks |
Local machine only |
| 2 | SSH disconnect / terminal close | tmux | Any SSH session |
| 3 | Process crash / OOM | PM2 or systemd | Headless servers |
| 4 | Eliminate the laptop entirely | Daytona cloud VM | Dynamic Workflows, overnight runs |
Most guides stop at Layer 2. For Dynamic Workflows that run for hours, Layer 4 is the right answer.
Layer 1: How Do You Prevent macOS from Sleeping During Claude Code Sessions?
If you run Claude Code locally (not over SSH), the caffeinate system tool prevents macOS from sleeping. The most precise way to apply it is via Claude Code's hook system, so sleep prevention activates exactly when the agent is active.
Add to your ~/.claude/settings.json:
{
"hooks": {
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "caffeinate -dis &"
}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "pkill caffeinate"
}
]
}
]
}
}
caffeinate -dis prevents display sleep (-d), idle sleep (-i), and system sleep (-s). The & runs it in the background so the hook does not block. The Stop hook kills it when the session ends. This is more precise than running caffeinate manually — it does not prevent sleep during the gaps between Claude sessions.
For remote servers or always-on setups, skip this layer and go to Layer 2 or Layer 4.
Layer 2: How Do You Set Up tmux to Keep Claude Code Running After SSH Disconnects?
tmux is a terminal multiplexer that runs a persistent server process on the remote host. Your SSH client connects to that server, but the sessions it manages are independent of the SSH connection. If the SSH client disconnects, tmux keeps running; reconnecting re-attaches to the existing session. As one guide puts it: "Plain SSH is live broadcast. If you leave the room, you miss it. If the cable goes out, the show is gone. tmux is recording. The show keeps running on the box at home. When you come back, you reconnect and pick up exactly where you left off."
Prerequisites
- tmux installed on the server (
sudo apt install tmuxorbrew install tmux) - Claude Code authenticated on the server (
claude auth login)
Step 1: Create a Named tmux Session
tmux new -s claude-work
The -s claude-work flag gives the session a name you can reconnect to by name. Without a name, tmux assigns an integer ID that is harder to track across sessions.
Step 2: Start Claude Code Inside tmux
cd ~/your-project
claude
Everything from here runs inside the tmux session, not your SSH connection. You can now close your laptop.
Step 3: Detach Without Killing the Session
Press Ctrl+B then D. The terminal returns to your SSH shell and prints:
[detached (from session claude-work)]
Claude Code continues running. The session persists until you explicitly kill it or the server restarts.
Step 4: Reconnect to a Running Session
tmux attach -t claude-work
If you're switching from one device to another (phone SSH app to laptop, for example), add -d to detach any other client first:
tmux attach -d -t claude-work
Without -d, multiple clients attach to the same session, which can cause rendering issues.
Step 5: List Active Sessions
tmux ls
Output:
claude-work: 1 windows (created Mon Jun 2 18:04:12 2026) [220x50] (attached)
Running Multiple Agents in Parallel with tmux
For parallel repos or parallel agents, use separate windows within one session:
# Create new window: Ctrl+B C
# Name it: Ctrl+B , then type a name
# Switch windows: Ctrl+B N (next) or Ctrl+B P (previous)
# List windows: Ctrl+B W
Or use separate named sessions per project:
tmux new -s api-rewrite # session for repo 1
tmux new -s frontend-audit # session for repo 2
For more detail on multi-agent tmux workflows, see How to Run Claude Code with tmux on a VPS.
Layer 3: Process Recovery with PM2 or systemd
tmux handles SSH disconnects but not process crashes. If Claude Code exits due to an OOM kill or an unhandled error, the tmux session stays alive but the process is dead. For unattended overnight runs, combine tmux with a process supervisor.
PM2 (Node.js-based, cross-platform):
npm install -g pm2
pm2 start "claude --dangerously-skip-permissions" --name claude-agent
pm2 save
pm2 startup # configure auto-restart on reboot
systemd (Linux servers, persistent after logout):
# ~/.config/systemd/user/claude-agent.service
[Unit]
Description=Claude Code Agent
[Service]
ExecStart=/usr/local/bin/claude --dangerously-skip-permissions
Restart=on-failure
RestartSec=10
[Install]
WantedBy=default.target
loginctl enable-linger $USER # allow user services to survive logout
systemctl --user enable --now claude-agent
--dangerously-skip-permissions is appropriate for unattended automation with pre-approved tooling. For interactive sessions where the agent needs to ask before writing files or running commands, leave it off and handle permission gates via Grass (covered in the next section).
Layer 4: How Do You Run Claude Code on an Always-On Cloud VM?
Daytona cloud VMs eliminate the root cause rather than patching around it. A cloud VM never sleeps, never closes a lid, and never loses power — so there is no SIGHUP to survive. For Dynamic Workflows that run for hours or days, this is the correct infrastructure choice. Daytona workspaces come with Claude Code pre-configured; you do not spend a weekend setting up your stack.
"The 99.9th percentile Claude Code turn duration exceeded 45 minutes as of early 2026 — drain battery and tie up a machine. Daytona workspaces are transient dev servers: cloud VMs that run independently of your local hardware. The agent runs there; your laptop is irrelevant."
Setting Up Claude Code on Daytona
For a complete walkthrough, see How to Set Up Claude Code on Daytona. The short version:
- Create a Daytona workspace (Daytona Cloud or self-hosted)
- SSH into the workspace:
daytona ssh <workspace-name> - Authenticate Claude Code:
claude auth login(use device auth flow for headless environments) - Start tmux + Claude Code:
tmux new -s main && claude
The workspace runs continuously even when you are not connected. You can fire off a Dynamic Workflow, close your laptop, and the orchestration continues. Reconnect at any time via daytona ssh.
Recommended specs: 16GB+ RAM. One community report found that 8GB VMs OOM-killed Claude Code under heavy orchestration load, taking down the tmux session with it. For Dynamic Workflows with many parallel subagents, 32GB+ is safer.
Daytona vs. DIY VPS
| Daytona | Self-managed VPS (Hetzner / DigitalOcean) | |
|---|---|---|
| Setup time | Minutes (pre-configured) | Hours (provision, install, harden) |
| Claude Code pre-installed | Yes | No |
| Per-workspace isolation | Yes | Manual |
| Cost | Usage-based | ~$5–20/month fixed |
| Best for | Dynamic Workflows, clean-room isolation | Long-term always-on setups |
How to Monitor Long-Running Sessions Without Staying at Your Terminal
For Dynamic Workflows or overnight runs, the monitoring problem is distinct from the persistence problem. The session stays alive — but you cannot babysit a terminal for 11 days. You need a way to check progress, handle permission gates, and intervene when the agent gets stuck, from wherever you are.
Grass is a machine built for AI coding agents that solves the monitoring layer. It streams Claude Code's output via SSE to a native mobile app, surfaces permission requests as native modals (one tap to approve or deny), and keeps running even if you force-quit the app. The Grass server process is independent of the mobile client — closing the app only drops the SSE stream; the agent continues working, permission gates queue on the server side, and everything replays when you reconnect.
Your tmux session or Daytona VM
└── Claude Code running
└── Grass server (grass start)
├── SSE stream → phone app (real-time output)
└── Permission queue → native modals on phone
Setting Up Grass for a Remote Server or Daytona VM
For remote access, use Tailscale to make the Grass server reachable outside your local network:
# On the server or Daytona workspace
npm install -g @grass-ai/ide
grass start --network tailscale
The --network tailscale flag injects the Tailscale IP into the QR code. Scan it on your phone to get live streaming output, permission approval modals, and a diff viewer — no terminal required. For a step-by-step setup, see How to Monitor a Long-Running Coding Agent Overnight.
Permission gates do not block the session when using Grass — they queue on the server side and notify your phone. You handle them whenever you pick up your phone; the agent resumes immediately after you respond.
Troubleshooting
"tmux: no server running on /tmp/tmux-*/default"
The tmux server is not running, typically because the server rebooted. Start a new session: tmux new -s main.
"sessions should be nested with care"
You are inside a tmux session trying to start another. Press Ctrl+B D to detach first, then attach to the target session.
Claude Code exits immediately after reconnecting
Check if Claude Code errored before you detached: tmux capture-pane -p -t claude-work | tail -20. Also confirm the project directory exists and authentication has not expired: claude auth status.
Claude Code OOM-killed in the VM
Increase VM RAM to 16GB+. Run free -h to confirm available memory. Claude Code can consume significant memory during large file reads and parallel orchestration.
tmux session exists but Claude Code has stopped
Attach to the session and check the output. If Claude Code shows a recovery prompt, type resume. If the process exited entirely, restart it inside the existing tmux session: claude (in the same directory, Claude Code will offer to resume the last session).
SSH disconnects still happening even with tmux
The session is safe in tmux, but the reconnect is annoying. Consider mosh instead of ssh — mosh sessions survive network changes and tunnel transitions without needing to re-attach. Harper Reed described riding a train through a tunnel: "My ssh (really mosh) session just paused for a moment, and then BAM! Was back."
FAQ
How do I keep Claude Code running after I close my terminal?
Use tmux. Run tmux new -s claude, start Claude Code inside, then press Ctrl+B D to detach. Your session continues running on the server. Reconnect anytime with tmux attach -t claude.
Why does Claude Code stop when SSH disconnects?
SSH disconnect sends SIGHUP to foreground processes in the terminal's process group. Claude Code exits on SIGHUP unless it is inside a tmux or screen session. tmux intercepts the disconnect and keeps the session running independently of the SSH connection.
How do I run Claude Code Dynamic Workflows overnight without losing progress?
Dynamic Workflows need the host Claude Code process alive for the entire duration — if it exits, the workflow restarts from scratch. The two reliable options: run in a tmux session on a remote server or cloud VM that never sleeps, or use a Daytona workspace, which is pre-configured for Claude Code and always on. Pair either option with Grass for mobile monitoring and permission handling.
Does tmux help if my Mac sleeps?
If you are running Claude Code on a remote server over SSH, yes — the Mac sleeping drops the SSH connection, but tmux keeps the session alive on the server. If you are running Claude Code locally (not over SSH), tmux does not help with sleep. Use caffeinate or Claude Code's hook system for local sleep prevention.
What happens to a Grass monitoring session if I close the app?
The Claude Code session keeps running. The Grass server process runs independently of the mobile app. Closing the app drops the SSE stream but the agent continues working. When you reopen the app and reconnect, everything replays from where you left off via SSE Last-Event-ID resumption.
How much RAM does a cloud VM need to run Claude Code reliably?
16GB minimum for standard use; 32GB+ for Dynamic Workflows with many parallel subagents. One developer found that 8GB VMs OOM-killed Claude Code under heavy orchestration, taking down the entire tmux session with it.
Next Steps
For SSH-only setups, the tmux steps above are everything you need. For Dynamic Workflows or overnight orchestrations that genuinely need always-on infrastructure:
- Set up a Daytona workspace → How to Set Up Claude Code on Daytona
- Add mobile monitoring → How to Monitor a Long-Running Coding Agent Overnight
- Set up a self-managed VPS → How to Authenticate Claude Code and Codex on a Headless VPS
The tactical fix is tmux. The strategic fix is infrastructure that never has a terminal to close in the first place.