Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

claude-tmux

A tmux session manager for Claude Code agents. Switch between multiple Claude sessions like you switch between tmux sessions.

Features

  • 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-message on Linux.
  • Devcontainer Support — Tracks Claude sessions running inside Docker devcontainers. Sessions show a [D] indicator and summaries are read from inside the container.

Prerequisites

Installation

Quick install (pre-built binary)

curl -sfL https://github.com/jhob/claude-tmux/releases/latest/download/install.sh | bash

Or download manually from the releases page.

From source

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 install

After installing the binary

Run the embedded installer to create directories and print hook configuration:

claude-tmux install

Then 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"

Usage

Commands

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

Session Switcher

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

Session States

Icon State Description
running Claude is processing
waiting Claude is waiting for input
finished Session completed normally
dead Process no longer running

State Transitions

SessionStart     → running
UserPromptSubmit → running   (resumes from waiting)
Notification     → waiting   (Claude needs input)
Stop             → finished
SessionEnd       → finished

Docker Devcontainer Support

claude-tmux tracks Claude sessions running inside Docker devcontainers. Docker sessions show a [D] indicator in the session list.

How It Works

  1. Scandocker ps finds running devcontainers (identified by the devcontainer.local_folder label)
  2. Detectdocker exec ... ps finds Claude processes inside each container
  3. Map — Traces the host-side docker exec process up to its tmux pane ancestor
  4. 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.

Real-time Hooks from Inside Containers (optional)

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.

Notification Delivery for Docker Sessions

Hooks inside containers write breadcrumb files; the host delivers them. Use a crontab:

crontab -e
# Add:
* * * * * ~/.local/bin/claude-tmux deliver-notifications 2>/dev/null

Or 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.

How It Works

  1. Hooks — Claude Code lifecycle hooks call claude-tmux hook <name> when sessions change state
  2. State Files — Session state is stored in ~/.claude-tmux/sessions/ as KEY=VALUE files
  3. Summaries — Fetched from Claude Code's sessions-index.json, with fallback to transcript parsing and optional LLM generation
  4. FZF Popup — Interactive selection with state file preview

Configuration

Session State Files

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

Environment Variables

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

AI-Generated Summaries

Set ANTHROPIC_API_KEY (already set if you use Claude Code) and run:

claude-tmux generate-summaries

Debug Log

Hook execution is logged to ~/.claude-tmux/hook.log.

Platform Notes

macOS

  • iTerm2 notifications via OSC escape sequences (requires set -g allow-passthrough on in ~/.tmux.conf)
  • Uses lsof for process working directory discovery (ships by default)

Linux

  • Uses /proc for process introspection — no lsof required
  • Notifications fall back to tmux display-message (no iTerm2 support)

Troubleshooting

Sessions not being tracked

  1. Check hooks are configured in ~/.claude/settings.json
  2. Check the hook log: tail -f ~/.claude-tmux/hook.log
  3. Run claude-tmux scan-processes to 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.

Contributing

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.

License

MIT

About

tmux claude session switcher

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages