Show HN: Tmux tab markers for Claude Code, Grok, and pi sessions Developer jhickner released a tmux plugin that displays status indicators for AI coding agents Claude Code, Grok, and pi in the tab bar, showing spinners during work and markers when attention is needed. The plugin also provides a hotkey to jump to tabs requiring attention and optional quota usage displays. Coding-agent status in your tmux tab bar. Think of it like a very lightweight cmux https://cmux.com , which is what inspired it. Also adds a hotkey to jump to the next tab that needs attention, and an optional usage module that shows quota usage for claude and grok, with the next reset time. ⠙ my-project ● other-tab ? needs-you plain-shell ✻ 73% ⟳ 1h42m 𝕏 2% ⟳ 3d20h Supports claude, grok build, and pi at the moment. When a session is working you get a spinner. When it needs you, you get ? or e or an unread ● . Live Claude / pi / Grok tabs: spinner while working, ● when a background tab finishes, ? when Grok is waiting on a question. Re-record with demo/record.sh needs VHS https://github.com/charmbracelet/vhs , plus the three agents on PATH . Add to your tmux config ~/.config/tmux/tmux.conf or ~/.tmux.conf : set -g @plugin 'jhickner/tmux-agent-tabs' or a local checkout: set -g @plugin '/path/to/tmux-agent-tabs' Then put the placeholders in your format strings — the plugin only substitutes them in place: set -g window-status-format ' {agent tab icon} {window name} default ' set -g window-status-current-format ' {agent tab icon} {window name} F default ' set -g status-right ' {agent usage} ' Reload prefix + I to install, then reload the config . The plugin sets status-interval 1 so the spinner animates opt out with @agent tabs status interval 'off' . | Option | Default | Meaning | |---|---|---| @agent tabs next key | M-a | Jump to next window wanting attention ● / ? / e . Set off to disable. | @agent tabs next prefix | unset | Set to on to require the tmux prefix for that key. | @agent tabs status interval | on | Set to off to leave status-interval alone. | @agent tabs color working | 3d8fd1 | Spinner / working marker color. | @agent tabs color needs permission | c94922 | ? marker color. | @agent tabs color errored | c94922 | e marker color. | @agent tabs color unread | ac9739 | Unread ● marker color. | @agent tabs dir | state dir | Where the once-a-second status cache, lock and bell list live. | Set @agent tabs dir if your tmux config tree is cloud-synced. The status cache is rewritten every second and lives next to your tmux config by default. If ~/.config is a symlink into iCloud/Dropbox/Syncthing — a common dotfiles layout — every tick becomes a sync round, which on macOS cost ~10% of a core in fileproviderd and ~6% in bird , continuously: set -g @agent tabs dir '~/.agent-tabs' Any non-synced path works. Avoid $TMPDIR on macOS: dirhelper reaps files untouched for 3 days, and the refresher's lock is written once at claim, so a session older than that would lose a live lock. Color values are anything tmux accepts in fg=... rrggbb , colour114 , red , … . Env vars also work and win if both are set : TABICON COLOR WORKING , TABICON COLOR NEEDS PERMISSION , TABICON COLOR ERRORED , TABICON COLOR UNREAD . set -g @agent tabs color working ' 7aa2f7' set -g @agent tabs color needs permission ' f7768e' set -g @agent tabs color errored ' ff9e64' set -g @agent tabs color unread ' e0af68' set-environment -g TABICON SPINNER quad claude | braille | quad | quad-heavy | ascii When a background tab finishes a turn, scripts/tink plays a short system sound macOS Tink, or a freedesktop chime on Linux . Override or silence: set-environment -g AGENT TINK PLAYER true silence set-environment -g AGENT TINK SOUND /path/to.aiff set-environment -g AGENT TINK PLAYER afplay set -g status-interval 1 set -g window-status-format ' /path/to/tmux-agent-tabs/scripts/tab-icon {window id} {window name} default ' set -g window-status-current-format ' /path/to/tmux-agent-tabs/scripts/tab-icon {window id} {window name} F default ' set -g status-right ' /path/to/tmux-agent-tabs/scripts/usage ' bind -n M-a run-shell '/path/to/tmux-agent-tabs/scripts/next-dot' | Marker | Meaning | |---|---| | spinner | working | ? | needs permission / waiting on you | e | errored | ● | finished while you were away unread | | none | finished and seen, or not an agent window | Default colors: blue working tint, red for ? / e , gold for the unread dot overridable — see Options . The fg style is left open through {window name} — put default after the span you want colored. Under the hood a single background refresher rebuilds a shared cache once a second; each tab is a pure cache read. Architecture details live in the header of scripts/tab-icon . Claude Code — joins ~/.claude/sessions/ .json with refined status from the lifecycle hook below . Handles Claude's background-spare turn handoff so the tab keeps spinning while a spare works. pi — no registry of its own; install hooks/pi-hook.ts as a pi extension so each session writes a self-contained status file. Same tab markers no needs-permission — pi doesn't expose that signal . Grok Build — reads ~/.grok/active sessions.json and derives status from session events.jsonl needs jq for the roster; soft-skips if missing . Also treats open plan-approval / question waits as ? . {agent usage} prints each provider's mark — ✻ for Claude, 𝕏 for Grok — with its percent and reset countdown, for each provider that currently has an open session: ✻ 73% ⟳ 1h42m 𝕏 2% ⟳ 3d20h | Provider | Shown when | Metric | Auth | |---|---|---|---| | Claude | live pid in ~/.claude/sessions/ | 5-hour window same as Claude /usage | Keychain Claude Code-credentials or ~/.claude/.credentials.json | | Grok | live pid in ~/.grok/active sessions.json | weekly credits pool creditUsagePercent | ~/.grok/auth.json OIDC token | If only one agent is open, only that label appears. Free / API-key Claude auth hides Claude; missing Grok login hides Grok. Polls are timid: never on startup startup delay first , only while some session is working and that provider has an open session, at most every few minutes, with independent exponential backoff per provider. Tab icons work for Grok with no install. Claude and pi need a small hook so refined status reaches the plugin. Point each lifecycle event at the plugin hook paths via the TPM install or your checkout : "hooks": { "SessionStart": { "hooks": { "type": "command", "command": "python3 ~/.config/tmux/plugins/tmux-agent-tabs/hooks/hook.py" } } , "Notification": { "matcher": "", "hooks": { "type": "command", "command": "python3 ~/.config/tmux/plugins/tmux-agent-tabs/hooks/hook.py" } } , "Stop": { "hooks": { "type": "command", "command": "python3 ~/.config/tmux/plugins/tmux-agent-tabs/hooks/hook.py" } } , "StopFailure": { "hooks": { "type": "command", "command": "python3 ~/.config/tmux/plugins/tmux-agent-tabs/hooks/hook.py" } } , "SessionEnd": { "hooks": { "type": "command", "command": "python3 ~/.config/tmux/plugins/tmux-agent-tabs/hooks/hook.py" } } } Stdlib only; always exits 0 so it never disrupts a turn. Writes