Tmux + Claude Code — Keep AI Working Even When SSH Drops
There is one problem you will inevitably hit when running Claude Code on a remote server over SSH. When the network drops, your Claude session dies with it.Close your laptop lid, lose Wi-Fi for a second, or accidentally close the Windows Terminal window — and everything you had in progress is gone. Re-launching resets the context from scratch. Adding tmux in between solves this entirely. The session lives on the server independent of the SSH connection, and when you reconnect you pick up exactly where you left off. This post shares the tmux configuration and automation scripts deployed across multiple production servers.
15
Servers deployed
tmux 3.4
Version used
3 panes
Max concurrent Claudes
0 lines
Work lost after reconnect
SSH Drop = Claude Session Gone
The traditional flow is straightforward.
Windows Terminal → SSH → claude → work
In this setup, the SSH connection is tightly coupled to the process lifecycle. The moment the SSH session drops, SIGHUP is sent to every process running inside it — including the claude process. Any in-progress file edits or analysis tasks are cut off mid-way.
Laptop lid closed → SSH drops → Claude session gone
Brief Wi-Fi interruption → SSH timeout → work in progress lost
Terminal window closed by mistake → context and all work reset
The longer the task and the more servers you operate, the more often this happens. For tasks that require Claude to process multiple files in sequence — such as large-scale refactoring or code analysis — an interruption means starting over with fresh instructions.
How tmux Solves This
tmux is a terminal multiplexer. The core idea is simple: it decouples the terminal process from the SSH connection.
Windows Terminal → SSH → tmux session → Claude
A tmux session lives as a server process, not as a child of your SSH connection. When SSH drops, the tmux session remains on the server. Reconnect via SSH and run tmux attach — Claude is right there, exactly where you left it.
tmux session lifecycle
tmux new -s session-name → runs as an independent server processCtrl+b → d or SSH drop → session stays alivetmux attach -t session-name → resume exactly where you left offexit or tmux kill-session → session deletedWhen to Use tmux vs. Not
tmux is not always necessary. Use it based on the nature of the task.
| Mode | Use case | Examples |
|---|---|---|
| Direct run (instant) | Quick one-off tasks | Edit a single file, short question |
| tmux session | Continuous or long-running work | Refactoring, deploy automation, complex analysis |
| tmux multi-pane | Parallel independent tasks | Multiple Claude instances each working on separate tasks |
Separate aliases are used for each mode. c runs Claude Code immediately, cc is for reviewing conversation history.
alias c="command claude --dangerously-skip-permissions" alias cc="claude-history"
Full .tmux.conf Configuration
Below is the full ~/.tmux.conf deployed across all servers. Every option has a reason. In particular, escape-time is covered in detail in the troubleshooting section below.
set -g default-terminal "xterm-256color" set -sg escape-time 50 set -g history-limit 100000 set -g set-clipboard on set -g allow-passthrough off set -g base-index 1 setw -g pane-base-index 1 set -g renumber-windows on set -g mouse on set -g status-left '[#S] ' set -g status-right '%H:%M %Y-%m-%d' set -g status-style 'bg=colour235,fg=colour250' setw -g monitor-activity on set -g visual-activity off
Key option explanations
escape-time 50Time for tmux to process OSC response sequences. Setting to 0 causes color code strings to appear as raw text in the terminal when used with Windows Terminal.allow-passthrough offBlocks terminal passthrough. Prevents escape sequence noise from OSC 11.history-limit 100000Large scrollback buffer so you can review long Claude output.mouse onMouse support for resizing panes and scrolling.base-index 1Windows start numbering from 1 instead of 0 — aligns naturally with number keys.tmux-claude Automation Script
Manually creating a session, launching Claude, and splitting panes every time is tedious. Place the script below at /usr/local/bin/tmux-claudeto get your full environment with a single command. The path /usr/local/bin/ is chosen because it is on the system PATH and available even when .bashrc is not sourced during SSH non-interactive execution. (See troubleshooting below.)
#!/bin/bash
SESSION="${1:-ai}"
DIR="${2:-~/ai}"
PANES="${3:-1}"
if tmux has-session -t "$SESSION" 2>/dev/null; then
tmux attach -t "$SESSION"
else
tmux new -s "$SESSION" -d -c "$DIR"
tmux send-keys -t "$SESSION" 'c' Enter
for ((i=2; i<=PANES; i++)); do
tmux split-window -h -t "$SESSION" -c "$DIR"
tmux send-keys -t "$SESSION" 'c' Enter
tmux select-layout -t "$SESSION" even-horizontal
done
tmux attach -t "$SESSION"
fiHow it works
Usage examples
# Default (session name: ai, working dir: ~/ai, 1 pane) tmux-claude # Custom session name and directory tmux-claude dev ~/project # 3-pane split (3 Claude instances simultaneously) tmux-claude ai ~/ai 3
One-Click Launch from Windows
A batch file in Windows Terminal can handle SSH connection + tmux session entry in one step. Create a bat file per server and double-clicking the icon opens the Claude environment instantly.
Single pane
@echo off wt nt cmd /k ssh -t main-server "tmux-claude ai ~/ai"
3-pane split (3 Claude instances)
@echo off wt nt cmd /k ssh -t main-server "tmux-claude ai ~/ai 3"
Note: The -t flag in the SSH command is required. tmux needs a TTY (pseudo-terminal), but SSH commands run in non-interactive mode by default. Without -t, tmux fails to start properly.
Essential Commands Reference
Session management
| Command | Description |
|---|---|
| tmux new -s name | Create a new session |
| tmux attach -t name | Reattach to session (after reconnect) |
| tmux ls | List all active sessions |
| tmux kill-session -t name | Kill session including its processes |
| tmux detach | Detach from session (session stays alive) |
Inside a session (press Ctrl+b, release, then the key)
| Key | Action |
|---|---|
| d | Detach — exit session (session stays alive) |
| c | Create a new window |
| n / p | Next / previous window |
| % | Vertical split (left/right) |
| " | Horizontal split (top/bottom) |
| Arrow keys | Move between panes |
exit vs. detach — the most important distinction
- exit: Kills the session. Claude and everything inside is deleted. There is no going back.
- Ctrl+b → d: Detaches. The session stays alive on the server. You can reattach later.
Troubleshooting Notes
Issues encountered during setup are documented here. Most are combination-specific problems that are not easily found by searching, so the root cause can take time to identify.
1. OSC color code strings printed to terminal
Symptom: Entering tmux prints strings like ^[]11;rgb:0c0c/0c0c/0c0c to the terminal
Cause: Windows Terminal responds to background color queries (OSC 11), and tmux displays that response as raw text on screen
Approaches that failed
# Attempt 1: screen-256color + terminal-overrides Tc → failed set -g default-terminal "screen-256color" # Attempt 2: tmux-256color + removing focus-events → failed set -g default-terminal "tmux-256color" # Attempt 3: removing all terminal-overrides → failed
Final fix
set -g default-terminal "xterm-256color" set -sg escape-time 50 # critical: must not be 0 set -g allow-passthrough off # block passthrough
Root cause: With escape-time 0, tmux has no time to process the OSC response sequence before printing it to screen. Setting it to 50ms gives tmux enough time to absorb the sequence without exposing it. Many guides recommend escape-time 0 for responsiveness, but it breaks when combined with Windows Terminal.
2. Claude Code install script: sh vs. bash
Symptom: curl ... | sh errors with Syntax error: (( unexpected
Cause: Ubuntu's /bin/sh is dash, but the Claude Code install script uses bash-specific syntax (((, etc.)
# This fails curl -fsSL https://claude.ai/install.sh | sh # Must specify bash explicitly curl -fsSL https://claude.ai/install.sh | bash
3. Command not found in SSH non-interactive mode
Symptom: ssh server "tmux-claude ..." returns "command not found"
Cause: Running a command directly over SSH opens a non-interactive, non-login shell where .bashrc is not sourced. User PATH entries like ~/.local/bin are missing.
Fix: Place the script in /usr/local/bin/. It is on the system's default PATH and always reachable.
4. Changes to tmux.conf have no effect
Symptom: Editing ~/.tmux.conf does not change tmux behavior
Cause: The existing tmux server process is still running and has not reloaded the config
Fix: Run tmux kill-server to fully stop the server and restart. tmux source-file ~/.tmux.conf only reloads some settings.
5. Old Claude version running after native install
Symptom: Old Claude version runs even after a native install
Cause: A symlink from an npm install (/usr/bin/claude) has higher PATH priority than the native install path (/usr/local/bin/claude)
Fix: Remove or re-point the /usr/bin/claude symlink
6. Session names with special characters
Symptom: tmux new -s my-session-한글 errors
Fix: Use only alphanumeric characters, hyphens (-), and underscores (_) in session names. Keep them short and clear: ai1, dev-01.
Mass Deployment to Multiple Servers
When managing many servers, connecting to each one individually to configure tmux is inefficient. Using scp and ssh inside a loop with background parallel execution completes the full deployment in seconds.
Deploy .tmux.conf
for server in server1 server2 server3; do
scp -q ~/.tmux.conf ${server}:~/.tmux.conf &
done
waitDeploy tmux-claude script
for server in server1 server2 server3; do
scp -q /usr/local/bin/tmux-claude ${server}:/tmp/tmux-claude
ssh ${server} "sudo cp /tmp/tmux-claude /usr/local/bin/tmux-claude && sudo chmod +x /usr/local/bin/tmux-claude" &
done
waitEach command is backgrounded with & and wait blocks until all finish. With many servers, the total time is equal to the slowest server because they run in parallel. After deployment, run tmux kill-server on each server to apply the new config.
Wrap-up
The tmux + Claude Code combination is simple to set up and immediately effective. You can hand off long tasks without worrying about SSH drops, and running multiple Claude instances in parallel panes for independent tasks is straightforward.
The most important configuration detail is escape-time. Many guides suggest setting it to 0 for responsiveness, but combining that with Windows Terminal causes OSC response strings to appear as raw text in the terminal. 50ms is the right value.
The biggest change tmux brought is the absence of urgency — there is no pressure to finish right now. When it is time to step away, Ctrl+b → d gets you out. When you return, Claude is waiting in the same place.
Related posts
- Why One Terminal Is Enough When Using Claude Code — Full terminal-based Claude Code workflow
- Linux Server Initial Setup Checklist: 8 Steps — Server initial environment setup including tmux
Comments
(4)Log in to leave a comment.
Lost Claude sessions multiple times working in unstable SSH environments without tmux. The attach-if-exists logic in tmux-claude is clean.
Had no idea escape-time 0 was causing OSC response corruption. Spent a lot of time on that issue — 50ms was the key.
Never thought about running 3 Claude instances in a split pane. Processing independent tasks in parallel should make things noticeably faster.
Related Posts
© 2026 TreeRU. All rights reserved.
All content is copyrighted by TreeRU. Unauthorized reproduction without attribution is prohibited.