Multi-line, mode-switchable status line for Claude Code β written in Rust. Token cost tracking, prompt-cache TTL, hit rate, burn rate, Skill/MCP usage, daemon mode, all in one binary.
π Site: https://hankegui.github.io/cc-status
π Source: https://github.com/hankeGui/cc-status
π¦ npm: npm install -g @cc-status-line/cli
~/hanke-dev/cc-status main claude-opus-4-7 ctx 86% ββββββ 154.6k/950k
~/hanke-dev/cc-status main claude-opus-4-7 ctx 86% ββββββ 154.6k/950k
12m β154.6k β185 +687 π―99% last $0.012 sess $1.42 hit 96% π₯ 32.4k/min
skills: jiraΓ3 wikiΓ1 mcp: githubΓ2
Run
bash scripts/screenshots.sh(withfreezeon PATH) to regenerate the PNG/SVG screenshots embedded above.
Most Claude Code status lines stop at "model name + ctx percentage." That hides what actually drives cost and behavior:
- How many tokens did the last turn burn, and how many were a cache hit (10Γ cheaper)?
- Is the prompt cache about to expire (5-min TTL) β and how much will the next turn cost if it does?
- What's my session-wide hit rate β and how fast am I burning tokens?
- Which Skills / MCP servers has this session called?
- On a 1M-context model, is my percentage actually computed against 1M, or am I about to be auto-compacted at 200k?
- What did this session actually cost in USD β and how does today / this week compare?
cc-status answers all of these in three lines and lets you switch modes with a single command.
- 8 built-in modes (
balanced(default) /compact/minimal/detailed/cost/tokens/tools/debug) plus user-defined modes viaccs mode add/append/edit. - 18 segments ranging from
{dir}/{git}to{cost_today}/{burn}/{session_age}/{cache_ttl}. Plus{plugin:NAME}for your own. - Custom
{plugin:NAME}segments β drop an executable, scaffold viaccs plugin new, debug viaccs plugin run, health-check viaccs plugin doctor. 250 ms hard timeout, ANSI-aware sanitize, fault-isolated. - Drag-and-drop mode editor β
ccs config editopens a short-lived 127.0.0.1 page where you arrange segments visually; Save writesconfig.toml. Pure stdlib, no new deps. - Conversational helper skill β
ccs setupinstalls a Claude Code skill so you can just say "switch to detailed" or "build me a plugin that shows X" inside a Claude Code chat and have it done for you. - Three-stage model resolution: transcript
message.modelβ stdin β settings.json β proxies / Bedrock / Vertex can't lie about what model Claude Code actually called.[1m]tier preserved across stages. - Per-model USD pricing with built-in defaults for Opus / Sonnet / Haiku 4.x and a 1M-context tier multiplier. Override per model in
config.toml. ccs costprints a multi-day ASCII dashboard with per-day bars, per-model breakdowns, and--debugper-file reconciliation when numbers don't match another tool.ccs statusis a self-explanatory dashboard for the current session β every number labeled, every unit annotated, model line shows the data source.ccs setupwrites thestatusLineblock to~/.claude/settings.jsonfor you (with backup), so users don't have to hand-edit JSON.- Optional Unix-socket daemon for sub-millisecond renders on slow git repos.
ccs renderfalls back to inline rendering if the daemon isn't running. - Streaming-aware token accounting: matches
ccusageandcc-switch's(message.id, requestId)dedupe so we don't double-count partial / final stream events. - Local-time day buckets matching what the Anthropic console shows.
- Fault-isolated rendering: a panicking or stuck segment becomes empty space, never blanks the whole status line.
cc-status is a Rust binary, but you don't need a Rust toolchain β pick whichever channel suits your machine.
Heads-up:
npxis for trying it once. Don't usenpxto install β Claude Code'sstatusLineruns on every prompt refresh, so you want the binary on PATH. Usenpm install -g,curl, or Homebrew below.
You already have Node.js if you use Claude Code.
npm install -g @cc-status-line/cli
ccs --version
ccs setup # writes the statusLine block into ~/.claude/settings.json (with backup)In China? Use a faster mirror once:
npm install -g --registry=https://registry.npmmirror.com @cc-status-line/cli
ccs setupTo try it without installing (binary won't stay on PATH afterwards):
npx -y @cc-status-line/cli --versionThis is fine for kicking the tires, but for actual Claude Code use you want the global install above.
curl -fsSL https://raw.githubusercontent.com/hankeGui/cc-status/main/install.sh | sh
ccs setupInstalls to ~/.local/bin/ccs. Pass --bin-dir or --version to customize.
brew install hankeGui/tap/ccs
ccs setupPick a tarball from releases, unpack, drop ccs somewhere on PATH. Then ccs setup.
cargo install --git https://github.com/hankeGui/cc-status --lockedNote:
cargo installputs the binary at~/.cargo/bin/ccs. If~/.cargo/binis not on your PATH, add it (rustup's installer normally does this for you):export PATH="$HOME/.cargo/bin:$PATH"
ccs setupwrites an absolute path either way, so Claude Code finds it even if your shell doesn't.
Or clone and build:
git clone https://github.com/hankeGui/cc-status
cd cc-status
cargo build --release
cp target/release/ccs ~/.local/bin/ccs setupThis inspects ~/.claude/settings.json, shows the proposed statusLine change, prompts y/N, and writes a backup before saving. It also offers to install a conversational helper skill at ~/.claude/skills/cc-status/ β once installed, you can say things like "switch my status line to detailed", "add today's cost to my bar", or "build me a plugin that shows the unread issue count" inside any Claude Code conversation, and Claude will run the right ccs commands for you.
Pass --yes to skip the prompt or --check to inspect without modifying. Force or skip the skill with --with-skill / --no-skill. To remove everything later: ccs setup --uninstall (cleans up both settings and the skill).
If you'd rather edit by hand:
{
"statusLine": {
"type": "command",
"command": "/absolute/path/to/ccs render"
}
}Use absolute paths β Claude Code's status-line shell does not always inherit your login PATH.
Restart Claude Code and the bar appears at the top of every prompt.
cc-status follows a "passive bar + on-demand panel" design. You don't need to read every metric every turn.
The bar at the top of every Claude Code prompt. Choose a layout:
ccs mode compact # 1 line, the basics (default)
ccs mode minimal # 1 line, just dir + ctx
ccs mode detailed # 3 lines, all metrics
ccs mode cost # 2 lines focused on $ spent
ccs mode tokens # 3 lines focused on token flow
ccs mode tools # 3 lines focused on Skill / MCP usage
ccs mode debug # 8 lines, one metric per line with labelsOr build your own without rewriting:
ccs segments # see all segments
ccs mode append cost_today # append a new line to current mode
ccs mode append hit_rate burn # append several segments together
ccs mode append --line 1 git # append to an existing line
ccs mode append --mode detailed cost_today # target a specific mode
ccs mode edit # full edit in $EDITOR
ccs mode add mine -l "{dir} {git}" \
-l "{last_turn} {hit_rate}" # define a brand-new mode
ccs mode list # show all modes
ccs mode rm mine # delete onePrint a self-explanatory dashboard for the current session β every number labeled, every unit annotated:
ccs statusThe panel auto-locates the transcript by cwd, so it works from anywhere β even outside Claude Code's status-line invocation context.
Forgot what +865 or π―99% means?
ccs explainPrints a colored cheat-sheet of every segment, every color, every glyph.
| Token | Output | Meaning |
|---|---|---|
{dir} |
~/hanke-dev/cc-status |
Last 3 path components; HOME shown as ~. |
{git} |
wt:foo main β‘2β£1 [+!?] |
Git: worktree (in worktrees only), branch, β‘ahead / β£behind upstream, then + staged, ! modified, ? untracked. |
{model} |
claude-opus-4-7 [1m] |
Model id Claude Code is actually invoking. Resolved transcript β stdin β settings.json. [1m] = 1M-tier. Vendor prefixes (anthropic--, anthropic/) stripped; deployment prefixes (bedrock/, vertex_ai/) kept. |
{ctx} |
ctx 54% β°β°β°β°β°β±β±β±β±β± 504.1k/1.0M |
Battery bar of remaining capacity (β°=remaining, β±=used) + tokens used / capacity. Color: green β₯50%, yellow 20β50%, red <20%. Capacity is the auto-compact threshold (default 95% of physical window). |
{ctx_tokens} |
ctx-used 504.1k/1.0M |
Same numbers as {ctx}, no bar/percent. Use when {ctx} is too wide. |
{last_turn} |
β504.1k β618 cache+581 π―100% |
Most recent turn: β tokens sent (incl. cache hits + writes), β output, cache+N cache_creation, π― cache-hit rate of this turn alone. |
{cache_ttl} |
cache 4:42 |
Time left on the prompt-cache 5-min TTL. Red <1 min / expired = next turn pays full input price. |
{hit_rate} |
hit 96% |
Session-wide cumulative cache hit rate (every turn aggregated). Different from {last_turn}'s π― (this-turn-only). |
{burn} |
π₯ 32.4k tok/min |
Session-average token throughput (total tokens Γ· minutes since first turn). |
{session_age} |
1h23m |
Wall-clock duration since the first assistant turn (42s / 12m / 1h23m / 2d3h). |
{skills} |
skills: jiraΓ3 wikiΓ1 |
Top-4 Skill calls Γ count (sorted by count). Hidden when no skills called. |
{mcp} |
mcp: githubΓ2 |
MCP-server calls grouped by server name. Hidden when no MCP tool called. |
{cost_last} |
last $0.012 |
USD cost of the last turn (current model's prices, including cache discounts). |
{cost_session} |
sess $1.42 |
Cumulative USD cost of the current session. |
{cost_today} |
today $4.18 |
Cost across all sessions today (local-time day buckets), all models. |
{cost_week} |
7d $24.50 |
Cost over the last 7 days (rolling), all models. |
{cost} |
last $0.012 | today $4.18 |
Combo of cost_last and cost_today β the two you most often want together. |
{mode} |
[balanced] |
Current display-mode name in brackets. |
{plugin:NAME} |
(plugin's stdout) | Runs <config>/plugins/NAME, captures stdout. 250 ms hard timeout, 80-char cap, ANSI SGR allowed. See ccs plugin new. |
Need to know what a glyph means right now? Run
ccs explainfor an annotated legend, orccs statusfor the current values with full labels.
ccs setup offers to install a Claude Code skill at ~/.claude/skills/cc-status/. Once it's there, you don't have to remember any commands β just talk to Claude:
- "switch my status line to detailed"
- "add today's cost to my status bar"
- "build me a plugin that shows the unread issue count from
~/.todo" - "my status line is blank β figure out why"
- "what does the π― 99% mean?"
Claude reads the skill, runs the right ccs commands for you, shows you the rendered preview, and confirms before doing anything destructive. The skill ships with a driver.sh smoke script so Claude can sanity-check the install before driving it.
Force-install: ccs setup --with-skill. Skip: ccs setup --no-skill. Remove: ccs setup --uninstall.
When you'd rather see than type, ccs config edit opens a drag-and-drop editor in your browser:
ccs config editIt launches a short-lived 127.0.0.1 web server (random port + auth token in the URL), opens your default browser, and presents:
- Mode tabs at the top β click any to switch to it
- Lines with segment chips β drag chips between lines, drag back to the palette to delete, click
Γto remove - A palette below with every built-in segment plus your installed
{plugin:NAME}files - Live preview of what each line will render to (mock data, so you don't need a session yet)
- Save writes
config.tomland the server exits 5s later
No long-running daemon, no dependencies β pure stdlib HTTP, idle timeout 30 minutes. Great when you have lots of segments to rearrange or you forgot the segment names.
Limitation: literal text inside templates (e.g.
cache: {cache_ttl}in thedebugmode) is currently dropped on save. Useccs mode editfor those.
Need a metric cc-status doesn't ship? cc-status has a built-in scaffolder.
ccs plugin new hello # scaffold a sh template (recommended)
ccs plugin run hello # debug-run: stdout/stderr/exit/elapsed
ccs mode append plugin:hello # add to current modeOr start from a Python template:
ccs plugin new my-metric --lang pythonccs plugin list # what's installed (and is it executable?)
ccs plugin doctor # health-check all plugins (timing / orphans / chmod)
ccs plugin path # the plugins directory
ccs plugin run my-metric --warm # second-run timing (skip cold-start cost)
ccs plugin new my-metric --force # overwrite an existing plugin fileccs plugin doctor runs every installed plugin once warm and grades each on:
- β fail β not executable, exec error, empty file, or warm runtime > 250 ms (will time out at render time)
- β warn β no shebang, non-zero exit, empty stdout, or not referenced by any mode (orphan)
- β ok β passes every check
Use it after any non-trivial change to a plugin, or just to find files left behind from old experiments.
Plugins are plain executables under <config-dir>/plugins/<NAME> β any
shebanged script (sh, python, ruby, β¦) or compiled binary works. cc-status
runs them as subprocesses with this contract:
- The executable receives Claude Code's stdin JSON (same schema as
ccs render) on its stdin:{cwd, model.{id,display_name}, context_window.remaining_percentage, session_id, transcript_path}. - Its stdout is the segment value. Newlines/tabs collapse to single spaces, ANSI SGR colors are preserved, other control chars are stripped, output clipped to 80 chars.
- Hard 250 ms timeout β slower plugins are killed and render as empty. Use
ccs plugin run --warmto measure steady-state cost (macOS Gatekeeper adds 200ms+ to the first run). - Non-zero exit / empty stdout / missing file β segment renders as
""(the surrounding whitespace collapses). - Plugins inherit the user's
$PATHand environment.
| Runtime | Cold start | Warm | Verdict |
|---|---|---|---|
| native binary (Go / Rust) | <5 ms | <5 ms | best |
| sh / bash | 5β20 ms | 5β10 ms | great |
| python3 | 30β80 ms | ~30 ms | OK if logic is tight |
| node | 70β150 ms | ~70 ms | risky for complex logic |
| any network call | 100ms+ | 100ms+ | don't β almost always blows budget |
Plugins run on every status-line refresh, which means every prompt β keep them fast.
Lives at $XDG_CONFIG_HOME/cc-status/config.toml (macOS: ~/Library/Application Support/dev.hanke.cc-status/config.toml).
ccs init # write defaults if missing
ccs init --force # overwrite existing
ccs config-path # print resolved pathExample:
current_mode = "detailed"
[modes.compact]
lines = ["{dir} {git} {model} {ctx}"]
[modes.detailed]
lines = [
"{dir} {git} {model}",
"{ctx} {last_turn} {cache_ttl} {hit_rate} {burn}",
"{skills} {mcp}",
]
[theme]
ctx_low = 20 # red below this remaining %
ctx_med = 50 # yellow below thisAdd your own modes β any TOML key under [modes.X] becomes selectable via ccs mode X.
{ctx} reports used / capacity where:
physical_window = used_tokens / (1 - CC_remaining_percentage / 100)
capacity = physical_window Γ CLAUDE_AUTOCOMPACT_PCT_OVERRIDE / 100
In plain English: cc-status backsolves the real context window from CC's reported percentage, then applies your auto-compact threshold to show the usable capacity β i.e., the point at which Claude Code will trigger auto-compact.
Two relevant Claude Code env vars (set in ~/.claude/settings.json env block):
| Env var | Meaning | Default |
|---|---|---|
CLAUDE_CODE_AUTO_COMPACT_WINDOW |
Treat the window as N tokens (e.g. 1000000 for 1M-context models) |
model-detected |
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE |
Compact at N % of window | 95 |
cc-status reads CLAUDE_AUTOCOMPACT_PCT_OVERRIDE from the process env at render time, so the bar always matches Claude Code's actual compact behavior.
The cost* segments compute USD by multiplying per-model token counts
against built-in Anthropic prices (Opus, Sonnet, Haiku, with the 1M
context tier doubling input/output when the model name contains
[1m] / (1m)). Override or extend the table in your config:
[pricing.opus]
input = 12.00 # $/M tokens
output = 60.00
# Or pin an exact model id (substring match, case-insensitive)
[pricing."anthropic--claude-opus-latest"]
input = 13.00
output = 65.00{cost_today} and {cost_week} walk every transcript under
~/.claude/projects/, incrementally folded into a rollup at
$XDG_CACHE_HOME/cc-status/rollup.json. First scan touches every
file; subsequent renders only read newly-appended bytes.
Caveat: today/7d cost relies on the model id Claude Code writes into the transcript (
message.model), which is the canonical id likeclaude-opus-4-7without the[1m]suffix. If you run on a 1M-context tier, today/7d under-counts unless you add a matching[pricing.opus]override that bakes the doubled price in.
Numbers off vs ccusage / cc-switch / your Anthropic invoice? Run:
ccs cost --days 1 --debugIt prints every transcript file that contributed to the window, sorted by cost β with raw entry count β unique-after-dedupe count, % duplicated, date-window misses, the four token buckets, and the model. Lets you pinpoint exactly where the gap is in seconds.
- Render latency: ~20 ms inline (mostly forking
git); ~2 ms via the optional daemon. Well under Claude Code's 300 ms status-line timeout either way. - Transcript parsing: incremental β a per-session JSON cache stores the file offset and aggregated counters. First-run scan is the worst case; subsequent renders only read newly-appended bytes.
- Cross-session rollup:
~/Library/Caches/dev.hanke.cc-status/rollup.jsonholds per-day, per-model token totals + a per-message dedupe set. Loaded only when the active mode references{cost_today}/{cost_week}/{cost}. - Fault isolation: each segment is wrapped in
catch_unwind; the git helper has a 150 ms hard timeout. A bad segment becomes""; the rest of the line still renders.
- δΈζδ½Ώη¨θ―΄ζ
- Architecture
- Releasing β distribution setup (npm, brew, GitHub Releases)
- CLAUDE.md β project-level context for Claude Code agents
Done in 0.3.x:
- Daemon mode (Unix socket) for sub-ms cold start
- Cost segments (
{cost_last}/{cost_session}/{cost_today}/{cost_week}/{cost}) - Per-model pricing with built-in Opus / Sonnet / Haiku rates and 1M-tier multiplier
- Cross-session cost dashboard (
ccs cost --days N) -
ccs cost --debugper-file reconciliation - Streaming
(message.id, requestId)dedupe matching ccusage / cc-switch - Local-time day buckets
- Auto-update (
ccs upgrade) detecting npm / curl / brew / cargo install - Shell completions (
ccs completions <shell>) - Fault-isolated segment rendering + git timeout
-
ccs setupfor one-shot~/.claude/settings.jsonwiring - GitHub Pages site
- Plugin segments (
{plugin:NAME}runs an executable in<config>/plugins/) -
ccs plugin new/run/doctorworkflow - Conversational helper skill installed by
ccs setup(~/.claude/skills/cc-status/) - Drag-and-drop visual mode editor (
ccs config edit) - Three-stage
{model}resolution (transcript β stdin β settings) with[1m]tier preserved -
{session_age}segment
Still on the list:
- Re-enable Windows builds (rollup file-rotation detection needs a robust signal there)
- Per-session colors / titles for parallel CC instances
- Pace-aware quota burn warning
- Homebrew tap published
MIT β see LICENSE.