A fuzzy window switcher for tmux (prefix + w), as a self-contained Go binary
distributed as a TPM plugin. It lists
every window across all sessions, previews their panes, and badges windows
running coding agents (claude / codex / pi) — with a busy spinner and the
agent's model — all detected natively, with no external tools beyond tmux
and fzf.
It is a Go port of a personal tmux_window_manager.sh script; the port drops the
script's jq / awk / fd / t2 dependencies in favor of native Go.
Responsive narrow layout with the pane preview hidden.
- Fuzzy picker across all sessions, grouped by session with a live preview of each window's panes.
- Event-driven agent status — agents push their lifecycle state into a small
SQLite DB via Claude Code / Codex hooks, so the picker badges each window as
working (
⟳), waiting on you (🔔, e.g. a permission prompt), or idle — no process polling or pane-scraping. Runtmux-window-manager install-hooksonce to wire it up. - Agent preview — model and latest message, captured at hook time from
Claude transcripts (
~/.claude/projects/**/*.jsonl) and the Codex notify payload. - Ctrl-N — create/attach a session in a directory you pick or type.
- Ctrl-Z / Ctrl-T — open Zed / Typora on the highlighted window's directory.
- Ctrl-R — reload the list (re-reads the latest status).
- Status-bar label —
tmux-window-manager label <pid> <fallback>prints a pane's agent name forwindow-status-format.
- tmux ≥ 3.2 (for
display-popup) - fzf — the picker UI
- Go ≥ 1.25 — the plugin builds its binary on install (the pure-Go SQLite driver requires it; still cgo-free, no C toolchain needed)
- macOS or Linux
Add to ~/.tmux.conf:
set -g @plugin 'thaodangspace/tmux-window-manager'Then press prefix + I. TPM clones the repo and the plugin's .tmux hook builds
the binary (go build) on first run, rebuilding automatically when the source
changes. Press prefix + w to open the picker.
Point tmux at a local checkout instead of cloning:
run-shell ~/code/tmux-window-manager/tmux-window-manager.tmuxThis runs the same build-on-install hook and key binding.
go build -o bin/tmux-window-manager ./cmd/tmux-window-managerThe full user guide is an Astro/Starlight site under docs/.
Run it locally or build its static output with:
make docs-dev
make docs-buildThe docs include picker controls, agent status setup, troubleshooting, and Cloudflare Pages deployment settings.
| Option | Default | Purpose |
|---|---|---|
@twm_key |
w |
Prefix key that opens the picker |
@twm_bin |
(auto) | Set by the plugin to the built binary path, so other config can call it |
Use @twm_bin to add the agent label to your status bar:
setw -g window-status-format "#I: #(basename '#{pane_current_path}')/#(#{@twm_bin} label #{pane_pid} #{pane_current_command})"The binary re-invokes itself for its internal modes; you normally only bind
run, but all subcommands are usable:
| Command | Purpose |
|---|---|
run [client] |
Open the picker popup and switch to the selection |
list |
Emit the window rows fzf consumes |
preview <target> |
Render a window's panes |
label <pid> [fallback] |
Print a pane's agent name (status bar) |
open-editor <zed|typora> <target> |
Open an editor on a window's path |
install-hooks [--claude] [--codex] [--dry-run] |
Wire status hooks into Claude Code / Codex |
hook [event] |
Record an agent lifecycle event (called from Claude/Codex hooks) |
status [--all] |
Dump the recorded agent status rows (debug) |
Run once to wire the hooks into Claude Code and print the Codex snippet:
tmux-window-manager install-hooksThis idempotently merges SessionStart / UserPromptSubmit / Notification /
Stop / SessionEnd hooks into ~/.claude/settings.json (preserving your own
hooks) and prints a notify = [...] line to add to ~/.codex/config.toml. From
then on, each agent reports its status as it works, and the picker reflects it.
- Status source. Agent presence, name, model, and status all come from the
status DB at
~/.local/state/tmux-window-manager/agents.db(override with$TWM_DB_PATH; honors$XDG_STATE_HOME). Rows are keyed by working directory and carry the agent PID, so a crashed agent's badge clears automatically (its process is gone) even if noSessionEndfired. An agent with no hooks installed simply shows no badge. SetTWM_HOOK_DEBUG=1to log redacted hook errors to$TMPDIR/twm_hook.log. - The directory picker (
Ctrl-N) does not honor.gitignore(the original relied onfdfor that); explicit excludes cover.git,node_modules,Library,.Trash.
MIT — see LICENSE.
