Releases: educlopez/ccvitals
v1.12.0
Added
module_orderconfig key — optional JSON array of module names controlling the left-to-right display order of segments (e.g.["cost","git","context","model","directory"]). Enabled modules not listed are appended after the listed ones in the default order. Unknown names are silently ignored (forward-compatible). When absent, behavior is byte-identical to previous versions. Works with powerline mode andmodules_line2routing (order is independent of line assignment). Config values are validated against the known module list — never evaluated or executed.module_orderadded to per-project config supported-keys list.- 7 new tests in
test/statusline.batscovering: default order unchanged when key absent, custom order respected, unknown names ignored, unlisted enabled modules appended, per-project config override, powerline + module_order, and modules_line2 routing preserved with custom order. - Hooks-as-state-writers infrastructure —
ccvitals-hook.sh: a new script registered in Claude Code'shooksconfig that writes per-session state to~/.claude/.ccvitals-state/<session_id>.jsonon every event (SessionStart,MessageDisplay,TaskCreated,PostCompact,Stop). Trackslast_event,last_event_at,session_title,message_count, andtasks_created. Atomic writes (tmp + mv). Stale files (>48h) cleaned up onSessionStart. Always exits 0, never writes stdout — safe to run on every message. Pure bash 3.2 + jq. sessionmodule (mod_session, default off) — shows session title written by the hook script (e.g.§ my-refactor); hidden when hooks not installed, state file absent, or no title set. With"session_turns": trueconfig key also shows turn counter frommessage_count(e.g.§ my-refactor ·12). Single state-file read shared between title and turns.--hooksflag forinstall.sh— registersccvitals-hook.shin~/.claude/settings.jsonunderhooksfor all five events. Merges into existing hook arrays without clobbering user-defined hooks; idempotent (no duplicate entries on re-run). Interactive installer asks whether to wire hooks after the module menu. Backs upsettings.jsonbefore modifying.TOTAL_STEPSadjusted accordingly.uninstall.shhooks cleanup — removes only the ccvitals-specific hook entries (matched byccvitals-hook.shpath) from all event arrays insettings.json; empties arrays are pruned; user hooks are preserved. Also removes the~/.claude/.ccvitals-state/directory.session_turnsconfig key — whentrue, thesessionmodule appends·Nturn counter to the title; defaultfalse.sessionadded to_KNOWN_MODULES,_DEFAULT_MODULE_ORDER, responsive-width drop order, and smart-visibility section instatusline.sh; module count updated to 29;install.shinteractive menu extended to 29 entries.- 38 new tests in
test/hooks.batscovering: hook exits/no-stdout on all five events, malformed JSON, empty stdin, state file creation and fields,message_countandtasks_createdcounter increments,session_titlecapture from bothsession.titleandhookSpecificOutput.sessionTitle, title preservation across events, atomic write (valid JSON + no stray tmp files), session_id sanitisation; session module with/without state file, title display,session_turnssub-option, zero-turns suppression, malformed state file graceful;install --hookswires all events, merges without clobbering, idempotent;uninstallremoves only ccvitals entries and preserves user hooks, removes state dir.
v1.11.0
Added
-
Skill names in
toolsmodule — when aSkilltool invocation is in flight, thetoolsmodule now shows the skill's name from.input.skill(e.g.⚒ deploy-to-vercel) in YELLOW instead of the genericSkilllabel. Falls back toSkillwhen.input.skillis absent. Controlled by thetools_skill_namesconfig key (default:true; set tofalseto restore the previous generic label in CYAN). -
MCP tool name compaction in
toolsmodule —mcp__server__toolnames are compacted toserver:toolformat (e.g.mcp__codegraph__codegraph_search→codegraph:codegraph_search), keeping the statusline readable even with many MCP tools installed. -
workflowsmodule (mod_workflows, default off) — detects runningWorkflowtool-use entries in the transcript (tool_use named"Workflow"with no matchingtool_resultyet) and shows⟳ N wf(e.g.⟳ 1 wf); hidden when none pending. Integrates into the existing singletail -n 300+ onejqpass shared bytools/agents/todos— zero additional transcript reads.Workflowentries are excluded from thetoolsmodule count. -
ICON_WORKFLOWS(⟳) added to all three icon sets (unicode,ascii→wf:,nerd);workflowsadded to responsive-mode drop order (betweentodosandgit) -
workflowsadded to--allmodule list,KNOWN_MODULES, interactive menu, and--helpininstall.sh; module count updated from 27 to 28 -
11 new tests in
test/statusline.batscovering: Skill name display, Skill fallback, YELLOW color for Skill,tools_skill_names=falsedisables name, MCP compaction, workflow count display, workflow hidden when completed, multiple workflows count, workflow hidden without transcript, workflow hidden with no Workflow tool, Workflow excluded from tools module -
thinkingmodule (mod_thinking, default off) — displays reasoning effort level with a✦icon (e.g.✦ xhigh); reads.effort.levelfrom stdin with.thinking_effortas a fallback field; color: CYAN forxhigh/xlarge, MAGENTA forhigh/large, GRAY otherwise; hidden when field absent; smart-mode suppresseslow/medium -
mcpmodule (mod_mcp, default off) — shows configured MCP server count (e.g.⬡ 4); aggregates servers from.mcp.jsonin the workspace root (flat{name:…}and{mcpServers:{…}}formats),~/.claude.json, and~/.claude/settings.json; hidden when count is zero; mtime-based file cache keeps every render at constant cost (count-only — noclaude mcp listcall on the render path) -
git_operationconfig key (defaultfalse) — prepends a RED operation banner when.git/MERGE_HEAD,rebase-merge/,rebase-apply/,CHERRY_PICK_HEAD, orBISECT_LOGare present (e.g.MERGE (main …)) -
git_status_splitconfig key (defaultfalse) — replaces theN filesaggregate with staged/unstaged/untracked counts (e.g.+2 ~3 ?1); reuses the existinggit status --porcelainpass, no extra subprocess -
git_shaconfig key (defaultfalse) — appends short commit SHA (GRAY) to the git segment -
git_stashconfig key (defaultfalse) — appends stash count as≡N(GRAY) when stash is non-empty; hidden when empty -
git_ageconfig key (defaultfalse) — appends time since last commit in compact format:5m,2h,3d,4w(GRAY) -
ICON_THINKING(✦) andICON_MCP(⬡) added to all three icon sets (unicode,ascii,nerd) -
thinkingandmcpadded to responsive-mode drop order (dropped beforecodegraph) -
thinkingandmcpadded to smart-visibility suppression logic;git_operation/git_status_split/git_sha/git_stash/git_agekeys documented in per-project config supported-keys list -
install.sh:
thinkingandmcpadded to--allmodule list andKNOWN_MODULES; count updated from 24 to 26 -
Session budget cap (
session_budget, number, USD) — new config key for thecostmodule. When set, displays$1.50/$5.00(current / cap) with color: GRAY <50%, YELLOW 50–79%, RED ≥80%. When unset, the module behaves exactly as before. Supports per-project override via.ccvitals.json. -
spendmodule (mod_spend, default off) — 7-day and 30-day historical spend aggregated from the per-day ledger that thedailymodule writes to~/.claude/.ccvitals-daily/YYYY-MM-DD.json. Displays7d $12.40 · 30d $48(compact, same money format as other modules). Config keyspend_windows(array, default["7d","30d"]) selects which windows appear. Accumulation starts from whendailywas first enabled; no backfill of pre-install transcripts. Reads only today-relative day-files from disk with a pure-awk date-diff (no external calls); hidden when ledger dir absent. -
spendadded to--allmodule list andKNOWN_MODULESininstall.sh; responsive drop order updated to includespend(betweendailyandtokens);session_budgetandspend_windowsadded to per-project config supported-keys lists -
test/cost_guardrails.bats: 19 new tests covering session budget (no-budget baseline, denominator display, color thresholds at 50%/80%, zero budget, per-project override) and spend module (hidden by default, missing dir, populated ledger, multi-window, separator dot,spend_windowsconfig, zero spend, malformed file, crash guard)
v1.10.1
v1.10.0
Added
- Homebrew tap —
brew install educlopez/tap/ccvitals; theccvitalswrapper runs the bundled installer (ccvitals --all,ccvitals uninstall) - Per-project config (
.ccvitals.json) — place a.ccvitals.jsonat any workspace root to deep-override the global config for that project. Any key present in the project file wins; absent keys keep their global values. Merge is done withjq -s '.[0] * .[1]'into a singleeffective_configvariable; all config reads now use that variable (refactor eliminates all scatteredjq ... "$statusline_config"calls). Values are only consumed as JSON data, never executed. - Smart visibility (
"smart": true, defaultfalse) — modules only appear when their value is notable:costwhen ≥ $1.00;cachewhen remaining < 60s or cold;pace(delta mode) when delta < 0;contextwhen ≥ 50%;durationwhen ≥ 1h. All other modules unaffected.falsebehavior is byte-identical to before. - Icon set (
"icons":"unicode"/"ascii"/"nerd") — all icon glyphs are resolved into variables at startup.unicode(default) is byte-identical to the previous behavior.asciireplaces unicode glyphs with plain-ASCII equivalents (⚒→T:, ◉→A:, ☑→[x], ⌛→eta, ⇅→io, ↯→cmp, ⚡→!, ⚠→(!), █░→#-).nerduses Nerd Font icons. - Responsive width (
"responsive": true, defaultfalse) — whenCOLUMNSis set and numeric, ccvitals drops lowest-priority modules from line 1 until the visible length fits. Priority: codegraph, rtk, lines, duration, cost, speed, vim, weekly, daily, tokens, compactions, pr, agent, mode, cache, pace, tools, agents, todos, git, usage, context, model, directory. Only applies to line 1 in non-powerline mode; powerline + responsive is silently skipped. test/statusline.bats: 17 new tests covering per-project override, merge semantics, invalid project JSON, smart hide/show for cost/context, icons ascii rendering, responsive no-crash, and COLUMNS-generous survival
Fixed
- Smart visibility: the cache-hide pattern matched the "2m" inside ANSI color codes (e.g.
\033[0;32m), blanking the cache module unconditionally — now matches on ANSI-stripped text - Responsive width: visible length now counts characters (
wc -m) instead of bytes — multi-byte bar glyphs (█) were over-counted 3×, dropping modules far too aggressively - A project-only
.ccvitals.jsonnow works even when no global config exists - Invalid JSON in the global config prints a one-line stderr warning instead of silently disabling all configuration
usagereset timestamp: ISO date strings (which also start with a digit) were matched by the epoch branch and fed into integer arithmetic, printing avalue too great for baseerror to stderr — the case now matches on any-non-digit first- Responsive recompose uses bash indirect expansion (
${!var}) instead ofeval
v1.9.0
Added
-
Subagent rows (
subagent-statusline.sh) — per-sub-agent row renderer for the Claude Code agent panel. Replaces the defaultname · description · tokensrow with a theme-aware line: status icon (◐CYAN running /✓GREEN completed /✗RED stopped /·GRAY unknown), label/name, description truncated to fit terminal width, k/M token count, and cwd basename. Readscolumnsandtasks[]from thesubagentStatusLinestdin contract; emits one compact JSON line per task. Handles unknown statuses and all edge cases (empty tasks, malformed stdin) gracefully with zero output and exit 0. Theme-aware: reads~/.claude/.statusline-config.jsonand applies the same color presets as the main statusline. -
install.sh: symlinkssubagent-statusline.shinto the config dir and writes thesubagentStatusLinekey tosettings.jsonalongsidestatusLine(both--forceand fresh installs) -
uninstall.sh: removes thesubagent-statusline.shsymlink and deletes thesubagentStatusLinekey fromsettings.json -
commands/setup.md: Step 7 now writes bothstatusLineandsubagentStatusLinekeys -
README.md: new "Subagent rows" section (after Powerline) describing the row format and how to disable -
test/subagent.bats: 19 new tests covering JSON contract, icon/color per status, description truncation, k/M token formatting, label-over-name preference, cwd basename, theme presets, and all edge cases -
Quota forecast —
pacemodule gains a newpace_display: "eta"config key. ETA mode computes the burn rate from elapsed time and used percentage, then projects when the 5h quota will exhaust. If exhaustion is before the reset:⌛ ~17:40(RED if within 1h, YELLOW otherwise). If quota will outlast the reset:⌛ ok(GREEN). The existing"delta"mode is the default and unchanged. -
Daily budget module (
daily, opt-in) — cross-session spend for the current day. Stores per-session costs in~/.claude/.ccvitals-daily/YYYY-MM-DD.json, sums all sessions, and displaysΣ $4.20. Optionaldaily_budgetconfig key (number, USD) adds a budget denominator and colors: GREEN <50%, YELLOW <80%, MAGENTA <100%, RED ≥100%. Day-files older than 7 days are pruned automatically. Hidden when no session_id or no cost in stdin. -
Weekly per-model split —
weeklymodule gainsweekly_split: trueconfig key. When the OAuth usage cache hasseven_day_opus/seven_day_sonnetutilization, renders7d O:42% S:18%(colored per standard thresholds) instead of the single progress bar. Falls back to the bar when per-model keys are absent or the cache is missing. -
Compactions module (
compactions, opt-in) — counts{"type":"system","subtype":"compact_boundary"}entries in the transcript using a fastgrep -con the full file. Displays↯ 2(GRAY). Hidden when count is 0 or transcript is absent. -
Session tokens module (
tokens, opt-in) — cumulative session input/output token counts using an incremental cache keyed by session_id (~/.claude/.ccvitals-tokens/<id>.txt). On each render only new transcript lines are processed; totals accumulate. Displays⇅ 1.2M/45k(in/out, k/M formatted). Resets on transcript shrink (compact). Hidden when transcript is absent. -
install.sh: menu extended to 24 entries (22=daily, 23=compactions, 24=tokens);--allnow includes all 24 modules;KNOWN_MODULESupdated -
commands/setup.mdandcommands/configure.md: new modules added to optional lists;pace_display,daily_budget,weekly_splitdocumented
v1.8.1
Fixed
- OSC 8 hyperlinks leaked literal escape text — the ST terminator (
\033\\) written inside double quotes collapsed its backslashes at assignment time, soecho -epaired the orphan backslash with the next color code's backslash and rendered visible033[0;33mgarbage after the branch/PR link. All OSC 8 sequences now use the BEL terminator (\007), which avoids the backslash ambiguity entirely and is equally supported by terminals - Regression test: visible output (real ESC bytes stripped) must never contain literal
033[text; OSC 8 must be BEL-framed
v1.8.0
Added
- Powerline mode — set
"powerline": truein.statusline-config.jsonto render each module as a background-shaded segment separated by the Nerd Font U+E0B0 (``) glyph; segments alternate between two per-theme background shades; a final trailing arrow resets to the terminal default background - Per-theme powerline background pairs: truecolor (
48;2;R;G;B) for pastel, tokyo-night, catppuccin, dracula, and nord; 256-color fallback (48;5;236/48;5;238) for mono and default "powerline_separator"config key to override the glyph with any string (ASCII fallback for terminals without a Nerd Font)- Internal
\033[0mresets inside segments are automatically followed by the segment's background code so colors persist throughout each segment - Two-line layout: each line restarts the alternating segment index and gets its own trailing separator
- No behavior change when
"powerline"is absent orfalse— output is byte-identical to the previous render path commands/configure.md: new step 5c asking about powerline mode with Nerd Font note and custom separator promptREADME.md: new "Powerline mode" section after Themes with config example, Nerd Font requirement, and custom separator usage
v1.7.0
Added
- Tools module (
tools, opt-in) — shows tool_use entries currently in flight (no matching tool_result yet):⚒ Bash(one pending) or⚒ Bash +2(first tool + overflow count); Task tool excluded (covered byagents); hidden when none pending - Agents module (
agents, opt-in) — shows Task tool_use entries without a matching result:◉ code-reviewer(one, using subagent_type or first 20 chars of description) or◉ 3 agents(multiple); hidden when none active - Todos module (
todos, opt-in) — shows progress from the last TodoWrite in the transcript window:☑ 3/7; GREEN when all completed, CYAN otherwise; hidden when no TodoWrite found or todos array empty - All three transcript modules share one
tail -n 300+ onejqinvocation per render; gated as a block when all three are disabled; transcript absent/missing → all hidden; malformed trailing lines handled gracefully (jq nonzero exit → all hidden) install.shmenu extended to 21 entries (19=tools, 20=agents, 21=todos);--allnow includes all 21 modules;KNOWN_MODULESvalidation updatedcommands/setup.mdandcommands/configure.md: tools/agents/todos added to optional module lists; Everything preset updated to 21 modules
v1.6.0
Added
- Pastel theme (
pastel) — soft lavender/cyan palette - Per-theme static preview images in the README (
assets/themes/*.png), regenerable withassets/generate-theme-previews.sh - Git ahead/behind — after the branch name, appends
↑N ↓Mwhen upstream diverges (GREEN ahead, YELLOW behind); both omitted when 0 - OSC 8 clickable branch —
gitmodule wraps the branch name in a terminal hyperlink (ESC]8;;URL\ESC\\) for GitHub/GitLab remotes; handles bothgit@host:owner/repo.gitandhttps://host/owner/repo.gitforms - OSC 8 clickable PR —
prmodule wrapsPR #Nin an OSC 8 hyperlink whenpr.urlis present in stdin - Pace module (
pace, opt-in) — burn-rate vs 5h quota window: computes how far ahead/behind the expected consumption rate you are; GREEN ≥0%, YELLOW -10%–0%, RED <-10%; hidden whenrate_limits.five_hourabsent or window invalid - Cache module (
cache, opt-in) — Anthropic prompt-cache TTL countdown (300s from last transcript entry):cache 4m12s(GREEN/YELLOW/RED by urgency) orcache cold; readstranscript_pathfrom stdin, hidden when absent - Context display modes — new optional config key
context_display:"percent"(default),"tokens"(e.g.45.2k/200k), or"both"(e.g.45.2k/200k 23%)
v1.5.0
Added
- Theming system — set
"theme"in~/.claude/.statusline-config.jsonto switch color presets without touching any code - Built-in presets:
default(legacy 16-color ANSI, backward compatible),tokyo-night,catppuccin,dracula,nord,mono(bold/white, no color) - Custom colors — set
"theme": "custom"with a"colors"object containing any of the 7 color keys (red,green,blue,yellow,cyan,gray,magenta) as#RRGGBBhex strings; missing keys fall back to defaults - Truecolor support — preset/custom colors use
\033[38;2;R;G;BmSGR sequences;defaultandmonocontinue to use the classic 16-color codes hex_to_ansihelper — bash-3.2-compatible hex-to-truecolor conversion (no associative arrays)- Theme selection added to
/ccvitals:setup(step 5) and/ccvitals:configure(step 5) - Theme showcase scene in the demo GIF (
assets/demo.tape+assets/demo.sh)
Fixed
- The
usagemodule now renders directly from stdinrate_limitswithout requiring a successful OAuth fetch first — previously the stdin preference only applied after a cache file existed, so the module stayed empty when API credentials were unavailable or the API was rate-limiting - The plan badge is omitted (instead of rendering an empty gray gap) when the subscription type is unknown