A tmux session manager for Claude Code agents. Switch between multiple Claude sessions like you switch between tmux sessions.
- Session Switching — FZF-powered popup lists all Claude sessions with state, summary, and a live pane preview. Jump between projects without losing context.
- Notifications — Get notified when Claude is waiting for input. Delivered via iTerm2 OSC sequences on macOS or
tmux display-messageon Linux. - Devcontainer Support — Tracks Claude sessions running inside Docker devcontainers. Sessions show a
[D]indicator and summaries are read from inside the container.
- tmux 3.2+
- Claude Code CLI
- fzf for interactive selection
curl -sfL https://github.com/jhob/claude-tmux/releases/latest/download/install.sh | bashOr download manually from the releases page.
git clone https://github.com/jhob/claude-tmux.git
cd claude-tmux
CGO_ENABLED=0 go build -o ~/.local/bin/claude-tmux ./cmd/claude-tmux/
claude-tmux installRun the embedded installer to create directories and print hook configuration:
claude-tmux installThen configure Claude Code hooks in ~/.claude/settings.json:
{
"hooks": {
"SessionStart": [{"hooks": [{"type": "command", "command": "claude-tmux hook on-start"}]}],
"UserPromptSubmit": [{"hooks": [{"type": "command", "command": "claude-tmux hook on-prompt"}]}],
"Stop": [{"hooks": [{"type": "command", "command": "claude-tmux hook on-stop"}]}],
"Notification": [{"hooks": [{"type": "command", "command": "claude-tmux hook on-notification"}]}],
"SessionEnd": [{"hooks": [{"type": "command", "command": "claude-tmux hook on-session-end"}]}]
}
}Optional: Add tmux keybindings in ~/.tmux.conf:
# Enable iTerm2 notification passthrough (macOS + iTerm2)
set -g allow-passthrough on
# Claude session switcher (prefix + C)
bind C display-popup -E -w 90% -h 80% "claude-tmux switch"
# Jump to waiting session (prefix + W)
bind W run-shell "claude-tmux goto-waiting"
claude-tmux switch # Open interactive session switcher (fzf)
claude-tmux update # Clean + scan + refresh (all-in-one)
claude-tmux list # List all sessions (human-readable)
claude-tmux list fzf # List in fzf pipe-delimited format
claude-tmux goto-waiting # Jump to first session waiting for input
# Maintenance
claude-tmux remove-dead # Remove dead/stale sessions
claude-tmux scan-processes # Scan tmux panes for Claude processes
claude-tmux update-summaries # Refresh summaries from transcripts
claude-tmux generate-summaries # Generate AI summaries via Claude API (-f to force all)
claude-tmux find-by-pid <pid> # Find session by process ID
claude-tmux register-current # Register current session manually
claude-tmux setup-hooks # Print hooks configuration instructions
claude-tmux deliver-notifications # Send pending Docker container notifications
# Hooks (called by Claude Code, not directly)
claude-tmux hook on-start
claude-tmux hook on-prompt
claude-tmux hook on-stop
claude-tmux hook on-notification
claude-tmux hook on-session-end
claude-tmux switch opens an fzf popup with all sessions. Inside the popup:
| Key | Action |
|---|---|
Enter |
Switch to selected session |
u |
Run update (clean + scan + refresh) |
g |
Run generate-summaries |
d |
Run remove-dead |
r |
Reload list |
| Icon | State | Description |
|---|---|---|
| ▶ | running | Claude is processing |
| ⏸ | waiting | Claude is waiting for input |
| ✓ | finished | Session completed normally |
| ✗ | dead | Process no longer running |
SessionStart → running
UserPromptSubmit → running (resumes from waiting)
Notification → waiting (Claude needs input)
Stop → finished
SessionEnd → finished
claude-tmux tracks Claude sessions running inside Docker devcontainers. Docker sessions show a [D] indicator in the session list.
- Scan —
docker psfinds running devcontainers (identified by thedevcontainer.local_folderlabel) - Detect —
docker exec ... psfinds Claude processes inside each container - Map — Traces the host-side
docker execprocess up to its tmux pane ancestor - Read — Session data (transcripts, summaries) is read from inside the container via
docker exec cat
Docker scanning is automatic when Docker is available. Disable with CLAUDE_TMUX_DOCKER=0.
Mount ~/.claude-tmux/ into devcontainers so hooks can write state files directly:
{
"mounts": [
"source=${localEnv:HOME}/.claude-tmux,target=${containerEnv:HOME}/.claude-tmux,type=bind"
]
}Without this mount, sessions are discovered only during claude-tmux update / scan-processes.
Hooks inside containers write breadcrumb files; the host delivers them. Use a crontab:
crontab -e
# Add:
* * * * * ~/.local/bin/claude-tmux deliver-notifications 2>/dev/nullOr poll from ~/.tmux.conf (if not using a powerline plugin):
set -g status-interval 5
set -ag status-right '#(claude-tmux deliver-notifications 2>/dev/null)'
Notifications are also delivered automatically during claude-tmux update.
- Hooks — Claude Code lifecycle hooks call
claude-tmux hook <name>when sessions change state - State Files — Session state is stored in
~/.claude-tmux/sessions/asKEY=VALUEfiles - Summaries — Fetched from Claude Code's
sessions-index.json, with fallback to transcript parsing and optional LLM generation - FZF Popup — Interactive selection with state file preview
Located at ~/.claude-tmux/sessions/<session-id>.state:
TMUX_SESSION=main
TMUX_WINDOW=2
TMUX_PANE=0
PROJECT=/path/to/project
STATE=running
SUMMARY="Your session summary"
LAST_ACTIVITY=1234567890
GIT_BRANCH=main
PID=12345
Docker sessions include additional fields:
DOCKER_CONTAINER=7c0a4608d68a
DOCKER_CONTAINER_NAME=relaxed_mahavira
CONTAINER_PROJECT=/workspace
CONTAINER_CONFIG_DIR=/home/vscode/.claude
HOST_PROJECT=/Users/you/Development/myproject
| Variable | Default | Description |
|---|---|---|
CLAUDE_TMUX_DOCKER |
auto | Set to 0 to disable Docker scanning |
ANTHROPIC_API_KEY |
— | API key for generate-summaries (also accepts ANTHROPIC_AUTH_TOKEN) |
ANTHROPIC_BASE_URL |
https://api.anthropic.com |
API endpoint for generate-summaries |
Set ANTHROPIC_API_KEY (already set if you use Claude Code) and run:
claude-tmux generate-summariesHook execution is logged to ~/.claude-tmux/hook.log.
- iTerm2 notifications via OSC escape sequences (requires
set -g allow-passthrough onin~/.tmux.conf) - Uses
lsoffor process working directory discovery (ships by default)
- Uses
/procfor process introspection — nolsofrequired - Notifications fall back to
tmux display-message(no iTerm2 support)
Sessions not being tracked
- Check hooks are configured in
~/.claude/settings.json - Check the hook log:
tail -f ~/.claude-tmux/hook.log - Run
claude-tmux scan-processesto discover already-running sessions
Summaries showing "Loading..."
Run claude-tmux update-summaries to refresh from transcripts.
Switch not focusing the correct pane Ensure tmux 3.2+ is installed for proper pane targeting.
Sessions from before hook installation
Run claude-tmux register-current from within a Claude session, or claude-tmux scan-processes to discover running sessions automatically.
Pull requests welcome. The project is written in Go — run CGO_ENABLED=0 go build ./... to verify your changes compile on both Linux and macOS.
MIT