cd /news/developer-tools/show-hn-tmux-tab-markers-for-claude-… · home topics developer-tools article
[ARTICLE · art-62349] src=github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

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.

read6 min views1 publishedJul 16, 2026
Show HN: Tmux tab markers for Claude Code, Grok, and pi sessions
Image: source

Coding-agent status in your tmux tab bar. Think of it like a very lightweight cmux, 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, 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'

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 -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 <state_dir>/state/<sessionId>.json

.

cp hooks/pi-hook.ts ~/.pi/agent/extensions/   # or symlink

pi auto-discovers *.ts

there. Writes <state_dir>/agents/<pid>.json

.

Plugin-owned runtime data lives under your tmux config tree:

Preference Path
override $AGENT_TABS_STATE_DIR
if ~/.config/tmux exists
~/.config/tmux/tmux-agent-tabs/
else if ~/.tmux exists
~/.tmux/tmux-agent-tabs/
else ~/.config/tmux/tmux-agent-tabs/

Contents: state/

, agents/

, tabicons.cache

, usage.cache

, grok-usage.cache

, locks.

External inputs (not moved): Claude's ~/.claude/sessions/

, Grok under ~/.grok/

(including active_sessions.json

and auth.json

), Claude OAuth credentials.

  • tmux
  • bash curl

(usage bar only)jq

(Grok roster only; optional)- Python 3 (Claude hook only)

  • Node (pi runtime; pi-hook is TypeScript for pi's )

MIT — see LICENSE.md.

── more in #developer-tools 4 stories · sorted by recency
── more on @jhickner 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/show-hn-tmux-tab-mar…] indexed:0 read:6min 2026-07-16 ·