tmux-claude-session-manager
Run many Claude Code sessions across your projects, each in its own tmux session — then list them, see which are done v…
git clone https://github.com/craftzdog/tmux-claude-session-manager.gitcraftzdog/tmux-claude-session-managertmux-claude-session-manager
Run many Claude Code sessions across your projects, each in its own tmux session — then list them, see which are done vs. still working, and jump to one from a single popup.
If you launch Claude per-directory (one nested session per project), you quickly end up with a dozen of them and no way to tell which are finished without opening each one. This plugin gives you:
- 🔢 A central picker (
prefix+u) listing every running Claude agent — several in one project, and any running loose in an ordinary pane. - 🟢 Live status per agent —
working/waiting/idle— read straight fromclaude agents --json, so you instantly see which need you. No setup. - 👁️ A live preview of each agent's screen right in the picker.
- 🎯 Smart jump — selecting an agent switches your client to the window it was launched from, then resumes it in a popup over it.
- 🚀 A launcher (
prefix+y) that opens/attaches a Claude session for the current directory. - ❌ Quick kill (
ctrl-x) of a finished agent from the picker.
Status needs no configuration. Claude Code publishes each agent's own state and the picker reads it — there are no hooks to install.
Prerequisites
- tmux ≥ 3.2 (for
display-popup) - fzf — the picker UI
- jq — parses
claude agents --json - Claude Code ≥ 2.1.139 — for the
claude agentscommand (claude --versionto check) - bash; macOS or Linux
Install (tpm)
Add to ~/.tmux.conf (or ~/.config/tmux/tmux.conf):
set -g @plugin 'craftzdog/tmux-claude-session-manager'
Then hit prefix + I to install.
Keybinding note: by default the plugin binds
prefix+y(launch) andprefix+u(list). If your config binds those elsewhere, either change the options below, or make sure the plugin loads after your own bindings (putrun '~/.tmux/plugins/tpm/tpm'after them) so the one you want wins.
Manual install
git clone https://github.com/craftzdog/tmux-claude-session-manager ~/clone/path
Add to ~/.tmux.conf, then reload (prefix + r or tmux source ~/.tmux.conf):
run-shell ~/clone/path/claude_session_manager.tmux
Usage
| Key | Action |
|---|---|
prefix + y |
Launch (or re-attach to) a Claude session for the current directory, in a popup |
prefix + u |
Open the agent picker |
Inside the picker:
| Key | Action |
|---|---|
enter |
Jump to the agent (see How it works) |
ctrl-x |
Kill the highlighted agent |
↑ / ↓, type to filter |
fzf navigation |
Agents needing your attention (waiting, idle) sort to the top.
Every running Claude gets its own row — the picker identifies each by its process, not by its tmux session. So several agents in one project all show up separately, as does a Claude you started by hand in an ordinary pane.
Options
Set any of these before the plugin loads (defaults shown):
set -g @claude_launch_key 'y' # prefix key: launch/open for current dir set -g @claude_list_key 'u' # prefix key: open the picker set -g @claude_command 'claude' # command run in new sessions set -g @claude_args '' # extra args appended to the command set -g @claude_session_prefix 'claude-' # tmux session name prefix set -g @claude_popup_width '90%' # popup width set -g @claude_popup_height '90%' # popup height set -g @claude_fzf_options '' # extra options passed to the fzf picker
For example, to skip permission prompts in launched sessions:
set -g @claude_args '--dangerously-skip-permissions'
Customizing the fzf picker
@claude_fzf_options is passed straight to fzf, so you can add your own bindings.
Here is a vim keybinding example:
set -g @claude_fzf_options "\
--prompt 'nav> ' \
--bind 'j:down' \
--bind 'k:up' \
--bind 'q:abort' \
--bind 'x:execute-silent(kill {3})+reload(sleep 0.3; \$CLAUDE_PICKER --list)' \
--bind 'i:unbind(j,k,q,i,a,x)+change-prompt(filter> )' \
--bind 'a:unbind(j,k,q,i,a,x)+change-prompt(filter> )' \
--bind 'esc:rebind(j,k,q,i,a,x)+change-prompt(nav> )'"
The picker opens in nav mode:
| Key | Action |
|---|---|
j / k |
move down / up |
i / a |
switch to filter mode — type to fuzzy-match |
x |
kill the highlighted agent (like the built-in ctrl-x) |
q |
close the picker |
enter |
jump to the agent (both modes) |
esc |
filter mode → back to nav |
Only the bound keys are special in nav mode; any other key still filters as you
type. x reloads the list through $CLAUDE_PICKER, a path the picker exports for
exactly this — write it as \$CLAUDE_PICKER inside the double-quoted value above
so tmux stores a literal $ (in a single-quoted value, use a bare
$CLAUDE_PICKER).
How it works
- The launcher creates a detached
claude-<hash-of-dir>tmux session runningclaude, records the window it came from in@claude_origin, and attaches to it in a popup. claude agents --jsonis the source of truth for what is running and how it is doing. Each Claude session self-reports its state (busy/waiting/idle) to a supervisor daemon, which that command publishes. Nothing here scans processes for aclaudecommand name — on macOS a pane reports its parent shell, never theclaudechild running inside it.agents.shpairs each running Claude with the tmux pane it occupies by joiningpid→tty→ pane. That join is why identity is the Claude process rather than the tmux session, and therefore why several agents in one project each get their own row. It costs three subprocesses per render, whatever the number of sessions or panes.- The age column is the mtime of the agent's transcript — its last sign of
life.
claude agents --jsonreports onlystartedAt, never a last-activity time. A brand-new agent that has yet to take a turn shows-. - The picker renders those rows with a live
capture-panepreview. Onentera dedicated agent (in aclaude-*session) resumes in the popup over the window it was launched from, while a loose one (any other pane) is focused in place.ctrl-xkills the Claude process itself: a dedicated session dies with its last window, and a loose pane keeps the shell that hosted it. - Pressing
prefix+ufrom inside a session popup detaches that popup first (closing it), then reopens the picker full-size on the outer host client — so you never end up with a cramped popup-in-popup.
License
MIT © Takuya Matsuyama
more like this
agentlytics
Comprehensive analytics dashboard for AI coding agents — Cursor, Windsurf, Claude Code, VS Code Copilot, Zed, Antigravi…
veille-techno
Skill Claude Code de veille tech francophone. Agrège les flux RSS (Journal du Hacker, Human Coders News…) et produit un…
xylocopa
A to-do list that runs your Claude Code agents — capture anywhere, dispatch in parallel, review from your phone.
