Preserve Claude Code sessions across tmux restarts. When tmux is killed and restored, Claude panes reopen with --resume <sessionId> so conversations continue exactly where you left off.
- How It Works
- Requirements
- Installation
- Critical Configuration
- Configuration Options
- Usage
- Session ID Resolution
- Troubleshooting
- Known Limitations
- License
The plugin detects which mode to use automatically at load time.
When tmux-resurrect is installed, tmux-claude hooks into its @resurrect-hook-post-save-all callback. After every resurrect save, the plugin:
- Finds all running
claudeprocesses and maps each one to its tmux pane via TTY. - Resolves the correct session ID using a 3-strategy approach.
- Patches the resurrect save file in-place, rewriting the stored command for each Claude pane to include
--resume <sessionId>.
When resurrect restores the session, it runs the patched command and Claude resumes the correct conversation. No extra keystrokes required.
When tmux-resurrect is not installed, the plugin binds save and restore keys:
- Save scans all tmux panes for running Claude processes, resolves their session IDs, and writes resume commands to
~/.tmux/claude-sessions/claude_save.txt. - Restore reads that file and opens a new tmux window for each saved session, running the resume command in the correct working directory.
Standalone mode restores Claude sessions only. It does not preserve pane layout.
- tmux >= 3.0
- bash >= 3.2 (works with macOS default bash)
- jq
- Claude Code CLI (
claudeon$PATH) - tmux-resurrect (recommended)
- tmux-continuum (optional, for automatic periodic saves)
Add to your ~/.tmux.conf:
set -g @plugin 'floatas/tmux-claude'Then press prefix + I to install.
git clone https://github.com/floatas/tmux-claude ~/.tmux/plugins/tmux-claudeAdd to your ~/.tmux.conf:
run '~/.tmux/plugins/tmux-claude/claude.tmux'If you cloned the repo to a custom location:
run '/path/to/tmux-claude/claude.tmux'You must add this to your ~/.tmux.conf:
set -g @resurrect-processes '~claude'Without this line, tmux-resurrect will not restore Claude processes at all. Resurrect maintains a whitelist of programs it will save and restore, and claude is not in the default list. The ~ prefix tells resurrect to restore the process with its full command line arguments, which is essential for the --resume flag to be passed through.
If you already have a custom @resurrect-processes value, append ~claude to it:
set -g @resurrect-processes '~claude ~vim ~ssh'All options are set in ~/.tmux.conf before the TPM initialization line.
| Option | Default | Description |
|---|---|---|
@claude-save-key |
C-s |
Key binding for standalone save (prefix + key) |
@claude-restore-key |
C-r |
Key binding for standalone restore (prefix + key) |
@claude-log-level |
info |
Log verbosity: debug, info, warn, error |
Example:
set -g @claude-save-key 'S'
set -g @claude-restore-key 'R'
set -g @claude-log-level 'debug'Save with tmux-resurrect as normal (prefix + C-s). The plugin automatically patches the save file with resume commands. When you restore (prefix + C-r), Claude sessions resume where they left off.
- Save sessions:
prefix + C-s - Restore sessions:
prefix + C-r
After a tmux restart, press the restore key. Each saved Claude session opens in a new window and resumes automatically.
When Claude Code is resumed via its session picker, the PID session file (~/.claude/sessions/<pid>.json) records a "wrapper" session ID that differs from the actual conversation ID. To reliably find the correct session, the plugin uses a 3-strategy approach, from most to least reliable:
-
Command line extraction -- Parse
--resume <uuid>from the running process's command line. This is the most reliable source because it reflects the session Claude is actively using, even after resuming a different session via the picker. -
PID session file -- Read
~/.claude/sessions/<pid>.jsonand extract thesessionIdfield. The plugin then verifies the session has actual conversation data by checking for a corresponding.jsonlfile in the project directory (~/.claude/projects/<project-key>/<sessionId>.jsonl). This works well for fresh sessions that were started without--resume. -
Most recent
.jsonlfallback -- If neither of the above succeeds, find the most recently modified.jsonlfile in the project directory and use its filename as the session ID. This covers edge cases where the session file has not been written yet.
Check the log:
tail -f /tmp/tmux-claude.logEnable debug logging by adding this to ~/.tmux.conf and reloading:
set -g @claude-log-level 'debug'Then trigger a save and inspect the log for per-pane resolution details.
jq not found: Install with brew install jq (macOS) or apt install jq (Debian/Ubuntu). The plugin displays a tmux message and exits without modifying anything if jq is missing.
Integrated mode not activating: The plugin detects tmux-resurrect by checking ~/.tmux/plugins/, ~/.config/tmux/plugins/, and XDG config paths. It also checks the @resurrect-save-script-path tmux option as a fallback. Make sure the run line for tmux-claude comes after tmux-resurrect is initialized.
pane_command shows a version number instead of "claude": This is normal behavior in some environments. The plugin matches Claude processes by looking at the full command field from ps, not the tmux pane_command value.
- Standalone mode does not preserve pane layout. Each restored session opens in a new window; the original pane arrangement is not recreated. Use tmux-resurrect for full layout preservation.
- Very new sessions may be skipped. If Claude was just launched and has not yet had any conversation activity, there may be no
.jsonlfile to resolve a session ID from. The session will be picked up on the next save. - Fallback strategy ambiguity. The most-recent-
.jsonlfallback can pick the wrong session if multiple fresh Claude instances share the same working directory. In practice this is rare, and the correct session will be identified on subsequent saves once--resumeappears in the command line.