which-claude-code
Auto-generated session titles + per-session colors in the Claude Code statusline.
If you run several Claude Code sessions in parallel terminals, you've probably
asked yourself: which tab was the one fixing the auth bug? which was the one
writing tests? This plugin answers that question automatically, without you
having to name anything.
After every prompt you submit, a tiny background Haiku call distills your
intent into a 3-6 word title. It shows up in the statusline, tinted with a
color uniquely hashed from the session ID. Same session = same color, forever.
Different sessions = visually distinct at a glance.
● Fix Autopublish Double-Publish Bug · Opus 4.7 · opt/vanio-gtm (main) · ctx:12% · 5h:34% · 7d:8%
● Refactor Dashboard Credits Panel · Opus 4.7 · opt/vanio-gtm (dash-credits) · ctx:42% · 5h:34% · 7d:8%
● Ship WhatsApp Alert Routing · Opus 4.7 · opt/vanio-gtm (wa-routing) · ctx:7% · 5h:34% · 7d:8%
The trailing ctx: / 5h: / 7d: segments show current context-window,
five-hour, and seven-day usage. Each segment renders only when Claude Code
provides the corresponding field, so older builds are unaffected. A
freshly-reset window shows <1% instead of 0% — Claude Code pre-rounds
used_percentage to an integer, so any real usage below 0.5% arrives as 0
and <1% is the honest render.
Install
Three steps, with a Claude Code restart after each of the first two.
1. Add the marketplace and install the plugin:
/plugin marketplace add jbarbier/which-claude-code
/plugin install which-claude-code@jbarbier
2. Quit and relaunch Claude Code. This lets the plugin's slash commands
register. Then wire up the statusline:
/which-claude-code:setup
3. Quit and relaunch Claude Code once more. The statusline config
is only read at startup, so a final restart is what makes it appear.
The statusline shows · · · until your first prompt; after that every
prompt refreshes the title.
Why the setup step?
Claude Code plugins can contribute hooks, commands, agents, and skills —
but not a statusLine. The setup command writes a statusLine block
into ~/.claude/settings.json pointing at a small dispatcher at
~/.claude/which-claude-code/statusline.sh. The dispatcher reads
installed_plugins.json on every render and execs whichever plugin
version is currently installed — so /plugin update doesn't leave
settings.json pointing at a deleted cache path. You only need to re-run
setup if this dispatcher itself gets an upgrade.
If you already have a statusLine configured, it's backed up and
restored automatically on uninstall.
Updating
/plugin marketplace update jbarbier
/plugin update which-claude-code@jbarbier
Then restart Claude Code once for the new statusline to take effect.
A note on the UI: after /plugin update, Claude Code drops you onto
the Discover tab with a list of every available plugin. That's
CC's default — there's no "updated X → Y" confirmation. Your success
signal is the Errors tab showing no count (just "Errors", not
"Errors (1)"). The update itself worked; the UI just isn't telling you.
You don't need to re-run /which-claude-code:setup after an update —
the dispatcher installed on first setup handles version routing
automatically.
How it works
Two moving parts, both pure shell:
-
UserPromptSubmit hook (bin/update-session-title.sh) — on every
prompt you submit, forks a background process that appends a sanitized copy
of your prompt to a tiny per-session history file (capped at 5 lines × 200
chars), asks Haiku for a concise title, and atomically writes it to
~/.claude/which-claude-code/titles/<session_id>.txt. The hook itself
returns in ~10ms so your prompt is never delayed.
-
Statusline (bin/statusline.sh) — reads that file on every render,
printing ● <title> · <model> · <cwd> (<branch>). The title is colored from a
20-color palette, indexed by cksum(session_id), so the mapping is stable
for the life of the session.
State lives under ~/.claude/which-claude-code/ (overridable via
$WHICH_CLAUDE_CODE_STATE_DIR). Nothing else is touched.
Defensive note for maintainers — recursive Claude subprocess calls
If you fork this plugin or write a similar one: read this.
Any hook that shells out to claude -p (or any Claude Code subprocess) can
trigger unbounded recursion. The child claude -p inherits the user's
~/.claude/settings.json and enabled plugins, so its own UserPromptSubmit
event fires — re-invoking the same hook, which spawns another claude -p,
and so on. Detached and disowned, the chain survives the user closing the
UI. In the wild this has been observed to produce: