cc-statusline
Health Uyari
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Basarisiz
- rm -rf — Recursive force deletion command in codex-usage-fetch.sh
- rm -rf — Recursive force deletion command in install.sh
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Two-line ANSI statusline for Claude Code: git + k8s context, rate-limit bars, service health, AI session topics
cc-statusline
A two-line, ANSI-colored statusline for Claude Code with project-aware colors, git status, Kubernetes context, rate-limit bars, Claude service health, and the session's name and title.

Design notes, screenshots, and the story behind the script: Custom Claude Code Status Line on hai.wxs.ro
Features
- Selectable themes with adaptive two-line layouts; Tokyo Auto follows OS appearance, and Classic preserves the original look
- Per-project colors in Classic and Hue Dark (12-color palette, hashed from session/cwd, manually overridable)
- Git info: branch, staged/modified/untracked counts
- Kubernetes context: current
kubectlcontext (with timeout to avoid exec-auth hangs) - Session metrics: model name, effort level (low/medium/high/xhigh/max, the live session value Claude Code reports), elapsed time, Claude session cost in USD, or a GPT-5.6 Sol ChatGPT credit-equivalent estimate (
211.29 cr, compacted to2.07k crat four digits) - Context window: colored bar and percentage; on GPT sessions a transient all-zero usage report re-shows the last valid percentage in dim gray (see GPT/Codex plan usage)
- Cache hit rate: prompt-cache efficiency of the last API call (green when most of the context is cached, coral when cold); off by default, enable with
STATUSLINE_CACHE=1(hidden anyway before the first call and after/compact) - Prompt-cache timer: how long until the main conversation's prompt cache goes cold, after the hit rate on line 2: a fire icon and the minutes left (
42m,<1min the last minute; green, then gold, then a coral fire-alert icon in the last 20% of the TTL, with a dim·5mtag when the cache TTL is 5 minutes), then a snowflake and the tokens your next message re-caches (184k) once cold. Read from Claude Code's.prompt_cache(v2.1.251+); hidden on older versions, when caching is off, and on OpenAI-backed (GPT) panes, whose cache lifetime Claude Code cannot report. On by default, hide withSTATUSLINE_CACHE_TIMER=0 - Context fill on phone: the phone/slim layout shows
ctx NN%(context-window usage, same color thresholds as the rate limits) before the 5h/7d windows; on by default, hide withSTATUSLINE_CTX=0. The wide layout already shows context asNN% of NNNk. - Rate limits: 5h and 7d bars with reset countdowns, progressively compacted to fit available width; Claude limits are shared across sessions, while opt-in GPT limits come from the official Codex CLI and can render a single available window
- Pace arrows: optional
↑/→after a rate-limit % projecting whether you'll exhaust the window before it resets (coral = will overshoot, gold = on pace, nothing = safe); GPT projections use each Codex window's reported duration - Provider service status: line 2 follows the active model, using Claude's status by default or the exact OpenAI
Codex APIcomponent for opt-in GPT sessions; auto-refreshed every 60s into separate caches - GitHub service status: line-1 icon (same glyphs/colors as the provider one), shown on repos with a
github.comremote; on by default, disable withSTATUSLINE_GITHUB_STATUS=0 - Clickable status icons: both service-status icons are OSC 8 hyperlinks (GitHub icon to
githubstatus.com, provider icon tostatus.claude.comorstatus.openai.com), so Cmd+click (macOS) / Ctrl+click opens the status page in a supporting terminal; on by default, disable withSTATUSLINE_HYPERLINKS=0 - Update indicator: a gold
⇡ X.Y.Zat the right edge of line 1 when a newer cc-statusline release exists (checked hourly against GitHub, hyperlinked to the release page); hidden entirely when you are current, disable withSTATUSLINE_UPDATE_CHECK=0 - Sessions in this repo: after the
@handleon line 1 when another Claude Code session works in the same repository, a repo-wide count of every session by state (⚙busy,◷background shells running,?waiting on your answer,○idle), with the count your own session belongs to bracketed; disable withSTATUSLINE_PEERS=0 - Session name (
@handle): the addressable name other Claude sessions use to message this one (Claude Code's per-session registry), shown first on line 1; on by default, hide withSTATUSLINE_SESSION_NAME=0 - Session title: Claude Code's auto-generated description, remembered across a user rename and hidden when it duplicates the visible handle; hide with
STATUSLINE_TOPIC=0 - Tab title: sets the terminal tab title from the session title or directory; disable with
STATUSLINE_TAB_TITLE=0 - Width-aware truncation: K8s context, branch, title, and name shrink first to keep line 1 under the soft limit before Claude Code's
cli-truncatedrops line 2
Requirements
- macOS or Linux
bash3.2 or newerjqperl(for ANSI-aware width measurement)curl(for service status)- GNU
timeout(coreutils; not stock on macOS) - Optional:
fzffor the interactive theme picker with live previews - Optional: a recent official
codexCLI logged in with ChatGPT forSTATUSLINE_GPT_LIMITS=1 - A Nerd Font in your terminal for the icons
Per-OS dependency install
| OS | Command |
|---|---|
| macOS (Homebrew) | brew install bash jq perl curl coreutils |
| Debian/Ubuntu | sudo apt install bash jq perl curl |
| Fedora/RHEL | sudo dnf install bash jq perl curl |
| Arch | sudo pacman -S bash jq perl curl |
| Alpine | apk add bash jq perl curl coreutils |
The Homebrew install below pulls these in automatically, except bash (your system's copy works; the scripts avoid bash-4-only features) and the font.
Install
Homebrew (recommended)
brew tap vtmocanu/tap
brew trust vtmocanu/tap # Homebrew 6.0+ requires trusting third-party taps
brew install cc-statusline
On Homebrew older than 6.0 the brew trust line doesn't exist; skip it (brew install vtmocanu/tap/cc-statusline also works there as a one-liner). If you'd rather not trust the whole tap, brew trust --formula vtmocanu/tap/cc-statusline scopes it to this formula.
The install puts cc-statusline on your PATH, declares the dependencies, and prints the settings.json snippets to paste (also shown by brew info cc-statusline). Point Claude Code at it:
{
"statusLine": {
"type": "command",
"command": "cc-statusline",
"refreshInterval": 60
}
}
Choose a theme with cc-statusline-theme (see Themes). The chooser is included in the install.
Upgrades are just brew upgrade cc-statusline; no settings change across versions.
Hacking on a clone while keeping the brew setup? The wrapper reads a working-tree path from ${XDG_CONFIG_HOME:-$HOME/.config}/cc-statusline/dev-dir; delete that file to return to the installed copy:
D="${XDG_CONFIG_HOME:-$HOME/.config}/cc-statusline"
mkdir -p "$D"
printf '%s\n' ~/src/cc-statusline > "$D/dev-dir"
install.sh (any platform, no Homebrew)
git clone https://github.com/vtmocanu/cc-statusline.git
cd cc-statusline
./install.sh
The installer extracts the chosen ref via git archive (so it never mutates your working tree), copies the scripts into ~/.local/share/cc-statusline/, and prints the JSON snippets you need to paste into ~/.claude/settings.json.
Choose a theme with ~/.local/share/cc-statusline/cc-statusline-theme, or the same filename under your custom install prefix (see Themes).
To pin a specific release:
./install.sh --version v2.1.0
To uninstall:
./install.sh --uninstall
To install into a custom prefix:
CC_STATUSLINE_PREFIX=/opt/cc-statusline ./install.sh
Manual install
If you'd rather skip install.sh, point statusLine.command directly at your clone:
{
"statusLine": {
"type": "command",
"command": "bash /absolute/path/to/cc-statusline/statusline.sh",
"refreshInterval": 60
}
}
refreshInterval (seconds) re-runs the statusline on a timer in addition to activity-driven updates, so idle sessions keep fresh rate-limit reset times, service health, and usage bars. It requires a recent Claude Code version; remove the line to update only on activity. Rate-limit bars specifically stay fresh across all your sessions, not just the one being refreshed: each render shares the freshest known account-wide values with the others via a small per-user cache (STATUSLINE_RL_SHARE=0 to disable). The cache is keyed per account: sessions launched with CLAUDE_CODE_OAUTH_TOKEN=... claude get their own cache file (keyed by a hash of the token, never the token itself), so different accounts never see each other's bars.
The clone also includes the chooser: bash /absolute/path/to/cc-statusline/cc-statusline-theme.
No hook is needed for the session name or title: line 1 reads both from Claude Code directly (the @handle from its per-session registry, the descriptive title from the .session_name payload field).
Configuration
Color overrides
classic and hue-dark give each project a hashed color from a 12-color palette. To pin a project to a specific color, create ~/.claude/statusline-color-overrides.json:
{
"/Users/me/code/important-project": 3,
"/Users/me/code/other-project": 7
}
The key is the project root (resolved via git rev-parse --show-toplevel); the value is a palette index 0-11. See examples/statusline-color-overrides.json for the full palette mapping.
Environment variables
| Variable | Default | Purpose |
|---|---|---|
STATUSLINE_THEME |
tokyo-auto |
Select a built-in theme (see Themes below). Overrides the saved theme file; unknown or empty values use tokyo-auto. default is an alias for tokyo-auto. |
CC_STATUSLINE_APPEARANCE |
auto | Force dark or light for Tokyo Auto, useful for previews and tests. |
CC_STATUSLINE_APPEARANCE_CACHE |
private state dir | Override the appearance cache path for tests or integrations. |
STATUSLINE_WIDTH |
110 |
Maximum visible columns per line, and a hard cap: when Claude Code reports a narrower viewport (see below), the render follows the viewport instead. Lower this if you see line 2 disappearing. |
STATUSLINE_LAYOUT |
auto |
phone or wide forces a layout; auto picks from the reported viewport width. |
STATUSLINE_PHONE_COLS |
60 |
Viewport width below which auto always selects the phone layout. Above it, auto still falls back to phone when the wide line 2 measurably does not fit (see below). |
STATUSLINE_CACHE |
0 |
Set to 1 to show the prompt-cache hit-rate readout (⚡ NN%) on line 2 (off by default). |
STATUSLINE_CACHE_TIMER |
1 |
Set to 0 to hide the prompt-cache cooldown timer on line 2 (fire + minutes left while warm, snowflake + tokens to re-cache once cold), independent of STATUSLINE_CACHE. When line 2 is short on room it keeps the timer and drops the hit rate first. Claude Code redraws when the cache expires, but the minutes only count down while idle with refreshInterval set. Hidden on GPT panes. |
STATUSLINE_CTX |
1 |
Set to 0 to hide the context-fill segment (ctx NN%) on the phone/slim layout's line 2. Shown before the rate limits with the same color thresholds; the first line-2 segment to shed as the viewport tightens. The wide layout's context readout is unaffected. |
STATUSLINE_SESSION_NAME |
1 |
Set to 0 to hide the @handle (the addressable session name peers message, read from Claude Code's per-session registry) at the start of line 1. |
STATUSLINE_PEERS |
1 |
Set to 0 to hide the repo-wide session counts after the @handle on line 1 (see Sessions in this repo). |
STATUSLINE_TAB_TITLE |
1 |
Set to 0 to skip the terminal tab-title write to /dev/tty. |
STATUSLINE_TOPIC |
1 |
Set to 0 to hide the auto description on line 1, remembered across a user rename. |
STATUSLINE_GITHUB_STATUS |
1 |
Set to 0 to hide the GitHub service-status icon on line 1 after the branch (same glyphs/colors as the Claude icon). Shown only when the current repo has a github.com remote; polls githubstatus.com every 60s in the background. |
STATUSLINE_HYPERLINKS |
1 |
Set to 0 to disable the OSC 8 hyperlinks on the service-status icons (GitHub plus the active Claude/OpenAI provider). Needs a terminal that supports OSC 8 (Ghostty, iTerm2, Kitty, WezTerm); elsewhere the escape is swallowed and the icon shows as plain text. |
STATUSLINE_UPDATE_CHECK |
1 |
Set to 0 to disable the update indicator (the gold ⇡ X.Y.Z right-aligned on line 1 when a newer cc-statusline release exists). Polls the GitHub "latest release" endpoint once an hour in the background; shown only when the release is newer than the installed VERSION, never when current. |
STATUSLINE_PACE |
1 |
Set to 0 to hide the rate-limit pace arrows (↑/→) on line 2. |
STATUSLINE_COST |
1 |
Set to 0 to hide the Claude session-cost readout (· $N.NN, sub-cent shown as $<0.01). It does not control GPT credits. |
STATUSLINE_GPT_CREDITS |
1 with GPT limits |
Set to 0 to hide the transcript-derived GPT-5.6 Sol ChatGPT credit-equivalent estimate. The public feature remains off until STATUSLINE_GPT_LIMITS=1. |
STATUSLINE_GPT_CREDITS_TTL |
300 |
Maximum age in seconds for a displayed GPT credit estimate; refresh attempts are throttled to 60 seconds per session. |
STATUSLINE_RL_SHARE |
1 |
Set to 0 to disable the shared per-user rate-limits cache (no read, no write). |
STATUSLINE_RL_FETCH |
1 |
Set to 0 to disable the background per-account usage fetcher (claude-usage-fetch.sh), which asks api.anthropic.com/api/oauth/usage with the session's own credential so multi-account machines show each account's true bars instead of Claude Code's shared (account-agnostic) numbers. |
STATUSLINE_RL_AUTH_TTL |
300 |
Seconds a fetched usage snapshot stays authoritative (displayed over the stdin rate_limits). |
STATUSLINE_RL_BACKOFF |
300 |
Seconds to stop fetching for an account after the usage endpoint returns an HTTP error (e.g. 429) with no usable fallback. |
STATUSLINE_RL_PROBE |
1 |
Set to 0 to disable the Messages-API header probe used when the usage endpoint refuses the credential (the probe costs a token or two of quota). |
STATUSLINE_GPT_LIMITS |
0 |
Set to 1 to replace Claude rate limits with the logged-in Codex CLI account's ChatGPT plan limits when the effective model ID identifies a GPT OAuth route. |
STATUSLINE_GPT_FETCH |
1 |
Set to 0 to keep reading a fresh GPT cache without launching codex-usage-fetch.sh. Has no effect unless STATUSLINE_GPT_LIMITS=1. |
STATUSLINE_GPT_AUTH_TTL |
300 |
Maximum age in seconds for displayed Codex usage. A stale snapshot is hidden rather than replaced with Claude limits. |
STATUSLINE_GPT_BACKOFF |
300 |
Seconds to pause Codex usage reads after an app-server, login, or payload failure. |
CC_STATUSLINE_RL_KEY |
auto | Override the rate-limits cache account key (a label like work). Normally auto-detected from the session's CLAUDE_CODE_OAUTH_TOKEN (hashed, read from the parent claude process's exec-time environment since Claude Code consumes the variable). Set empty to force the shared unsuffixed cache. |
STATUSLINE_GLYPH_MARGIN |
3 |
Columns reserved for Nerd Font glyphs that render double-width in some terminals. Set to 0 on a known mono-width font to reclaim them. |
STATUSLINE_PROFILE |
1 |
Set to 0 to hide the account/profile badge (see below). |
STATUSLINE_DEBUG |
unset | Set to 1 to write stderr to /tmp/statusline-debug.log. |
CC_STATUSLINE_PREFIX |
~/.local/share/cc-statusline |
Install prefix for install.sh. |
Themes
Run cc-statusline-theme to choose interactively. With optional fzf, the
choices sit above a full-width live preview of the two statusline rows. The
current theme is marked and selected initially when fzf supports it. Without
fzf, the chooser shows previews and a numbered menu.
cc-statusline-theme # choose interactively
cc-statusline-theme list # list themes and mark the current choice
cc-statusline-theme current # show the theme, resolved variant and source
cc-statusline-theme set classic # restore the original look
cc-statusline-theme reset # remove the saved choice
cc-statusline-theme preview # preview every theme
cc-statusline-theme preview tokyo-day # preview one theme
Homebrew puts the chooser on PATH. With install.sh, use~/.local/share/cc-statusline/cc-statusline-theme (or your custom prefix).
For a manual clone, use bash /absolute/path/to/cc-statusline/cc-statusline-theme.
Previews use the actual renderer with isolated sample data and caches, without
network fetches or terminal tab-title changes. The chooser honors the same dev
override as the statusline.
Choices are saved atomically to${XDG_CONFIG_HOME:-$HOME/.config}/cc-statusline/theme and apply on the next
redraw: immediately in active sessions, or at your configuredstatusLine.refreshInterval in idle sessions. Without a refresh interval, idle
sessions update on your next message.
An explicit STATUSLINE_THEME assignment in statusLine.command wins over the
saved file. The chooser recognizes leading literal assignments, optionally
following env, without evaluating or expanding the command. Its own shellSTATUSLINE_THEME is next, then the saved file, then tokyo-auto. The chooser
shows that source and warns when settings prevent a saved choice from applying.
Unknown or empty choices use tokyo-auto; default is an alias for it. With no
explicit choice, an existing color-overrides file retains classic.
tokyo-auto follows the host OS appearance, selecting tokyo-night ortokyo-day; it does not inspect the terminal background. Appearance is cached
for 60 seconds and refreshed on a subsequent redraw. Missing tools and failed
probes fall back to Night. current and the picker show the resolved variant.
You can also select a theme directly in your statusline command:
STATUSLINE_THEME=tokyo-night cc-statusline
| Theme | Appearance |
|---|---|
classic |
The original look: per-project hue, slanted caps, black second line. |
hue-dark |
Project hue on a dark tint, with vertical edge caps. |
nord |
Transparent backgrounds and a restrained Nordic palette. |
phosphor |
CRT green and ASCII bars, with distinct amber/red alerts. |
synthwave |
Pink, purple, and cyan gradient, with a dusk second line. |
tokyo-auto |
Follows OS dark/light appearance, with a 60-second cache. |
tokyo-day |
Tokyo Night's official Day colors with arrow segments. |
tokyo-night |
Neon on navy, with stepped Powerline arrows. |
gruvbox |
Warm earth tones, hard arrows, and block bars. |
dracula |
Purple and pink segments, with flame joins. |
catppuccin |
Mocha pastel capsules and round bars. |
default |
Alias for tokyo-auto. |
Classic retains the existing output byte for byte. Project color overrides
and project hues apply to classic and hue-dark; the other themes use fixed
palettes. All themes keep the same content, status meanings, hyperlinks, and
adaptive width rules. A theme's caps and separators can change how much detail
fits at a given width. Powerline caps require a Nerd Font, like the existing icons.
Phone layout (narrow viewports)
Claude Code exports COLUMNS/LINES to the statusline process (v2.1.153+), and it
reports the viewport of the client doing the viewing: the same session rendered
from the Claude mobile app arrives with COLUMNS=52 while the desk terminal
renders it at COLUMNS=324. Each attached client gets its own render, so both can
be right at once. Below STATUSLINE_PHONE_COLS (60) the script switches to a
layout built for that width, and above it the switch still happens whenever the
wide render measurably will not fit: line 2's wide base (model, effort, clock,
cost, context) cannot be truncated, so the tier is re-decided after measuring it.
That threshold therefore moves with your own line: a long model display name or a
5-figure cost can select the phone layout as high as the low 90s, and a lean
session stays wide down to 60. STATUSLINE_LAYOUT=wide overrides this if you
would rather have the wide render and accept the truncation.
The phone layout:
phone │ devmetaminds/phone !1 ?1
wxs │ ctx 46% │ 5h 77%↑ ↻2h28m │ 7d 81%↑ ↻4d8h │ ✓
Line 1 keeps the folder, branch and dirty markers; line 2 keeps the account badge,
the context fill (ctx NN%), and both rate-limit windows with their pace arrows and
reset countdowns (↻). The session name and title, model, effort, elapsed,
cost/credit estimate and cache are dropped: at 50 columns they cost more room than they earn. As the viewport
narrows further, each line sheds independently. Line 2 drops the reset countdowns
first (keeping ctx and the bare percentages), then drops ctx so the rate limits
themselves always survive (STATUSLINE_CTX=0 removes ctx entirely). Line 1
collapses the folder to its leaf, trims
the branch (keeping its tail, since worktree branches share long prefixes), drops
the dirty markers, trims the folder, and at the very narrowest drops the branch
entirely so the leaf folder survives: at that width, which session this is
matters more than which branch it is on.
No configuration is needed. STATUSLINE_LAYOUT=phone|wide forces a layout, and a
one-line $XDG_CONFIG_HOME/cc-statusline/layout file holding phone or wide
does the same for a running session (useful for clients that report no viewport);
the environment variable wins over the file, and the file wins over auto-detection.
Note that the tier follows the effective width, which is STATUSLINE_WIDTH
capped by the reported viewport. So an explicit STATUSLINE_WIDTH belowSTATUSLINE_PHONE_COLS selects the phone layout even on a wide terminal. That is
deliberate (the layout should match the width the line is being fitted to), but
if you set a narrow STATUSLINE_WIDTH as a truncation workaround and want the
full render anyway, pin it with STATUSLINE_LAYOUT=wide.
Account/profile badge (multi-account setups)
Opt-in: create ~/.claude/profile-labels.json with a profiles map and the badge shows which account a session is on (· MM), colored per profile. Entries are keyed by the account UUID from ~/.claude.json (.oauthAccount.accountUuid, keychain logins), or, for sessions launched with CLAUDE_CODE_OAUTH_TOKEN=... claude, by the cksum hash of that token (the same key the per-account rate-limits cache uses; an unlabeled account shows NNNNNN? so you know what to add):
{
"enabled": true,
"profiles": {
"ed3f1226-c7fe-45ef-af44-6d7fb62175d0": { "label": "home", "color": "orange" },
"4258859386": { "label": "work", "color": "red" }
}
}
Session name and title
Line 1 leads with two identifiers Claude Code provides natively, so neither needs a hook or an API call:
@handle(the session name): the short, addressable name other Claude sessions use to message this one (SendMessage({to: "<handle>"})), for example@uzi-60. It is read from Claude Code's per-session registry under~/.claude/sessions/*.json(the.namefield, matched to the session by its id), which reflects both the auto-derived default and a/rename. Hide it withSTATUSLINE_SESSION_NAME=0. This registry is an internal Claude Code file, so the read is best-effort: if its shape changes in a future release, the handle simply doesn't show.- Title (the descriptive label): the auto-generated
.session_name, for exampleAdd session names to status line. The statusline remembers each non-empty auto title in a private per-session cache. After a user rename, it shows that remembered description; if none was captured, it shows only the handle. A description matching the visible handle is hidden (case-insensitive), so@ccis not followed bycc. Hide the description withSTATUSLINE_TOPIC=0; hiding the handle leaves the description available. Title retrieval never reads the transcript, and empty title frames preserve the cache. The tab title uses the displayed description or falls back to the directory.
Earlier versions synthesized the title with an opt-in UserPromptSubmit hook that called Claude Haiku; that hook has been removed in favor of the native field, which needs no credential, transcript excerpt, or quota. If you registered that hook in settings.json before upgrading, remove its UserPromptSubmit entry: otherwise Claude Code prints session-topic-capture.sh: No such file or directory on every prompt (harmless but noisy). The stale ~/.claude/session-topics/ cache it wrote is safe to delete.
Sessions in this repo
When more than one Claude Code session works in the same repository, line 1 shows a repo-wide count of all of them, your own included, after the @handle (or first when the handle is hidden), for example [⚙2] ◷1 ?1 ○2:
| Glyph | Meaning |
|---|---|
⚙N |
busy: a turn is running (a running background subagent keeps a session busy too) |
◷N |
the turn ended but background shells are still running, e.g. a watcher waiting on a delegated run |
?N |
idle, and its last reply asked you something (an unanswered question prompt, or its final line ends with ?); drawn in reverse video so it stands out |
○N |
idle and asked nothing: probably finished, a candidate for a final check |
Zero counts are left out, and the whole segment is hidden when a session is alone in its repo. The count your own session belongs to is bracketed ([⚙N], [◷N] or [○N]), so each session shows where it stands; it is never counted as ?, since you are already looking at it. "Same repo" follows git worktree list, so sessions in linked worktrees at other paths count too. Codex threads attached as session peers are not counted; they are Codex runs, not Claude Code sessions.
The states come from Claude Code's per-session registry (~/.claude/sessions/*.json, the same internal file the @handle uses), and ? is a hint read from the end of each idle session's transcript, not a guarantee. Every session in the repo shows the same total, but not always the same split: a session waiting on you counts itself as ○ while the others count it as ?, so with two idle sessions where only A asked something, A shows [○2] and B shows ?1 [○1]. Each statusline also counts at its own redraw, so two sessions can briefly disagree by one; set refreshInterval on your statusLine so idle sessions redraw (60 seconds is plenty). Counts follow the directory and branch on phones. When space runs out, counts are dropped whole after Kubernetes context on wide layouts and first on phones. Only the upgrade notice stays right-aligned. Disable with STATUSLINE_PEERS=0.
Per-account usage fetcher
claude-usage-fetch.sh runs in the background (spawned by the statusline, throttled to once a minute across all your sessions per account) and asks api.anthropic.com/api/oauth/usage for the account's true 5h/7d usage, authenticated as the session itself: the session's CLAUDE_CODE_OAUTH_TOKEN when it was launched with one, your stored login otherwise. This exists because Claude Code feeds every session the same cached rate-limit numbers regardless of which account the session bills (shared ~/.claude.json state), so on multi-account machines the bars were whichever account fetched last. The credential is never logged, never put in argv/env, and is only sent to api.anthropic.com over HTTPS. Set STATUSLINE_RL_FETCH=0 to disable (the statusline then falls back to whatever Claude Code reports).
If the usage endpoint refuses a credential (it answers 429 to CLAUDE_CODE_OAUTH_TOKEN credentials that the Messages API accepts), the fetcher falls back to a minimal Messages request (haiku, max_tokens: 1) and reads the account's limits off the anthropic-ratelimit-unified-* response headers. That probe costs a token or two of the account's quota; STATUSLINE_RL_PROBE=0 turns it off, and after a failure with no usable fallback the account backs off for STATUSLINE_RL_BACKOFF seconds.
GPT/Codex plan usage
GPT limits are off by default. Set STATUSLINE_GPT_LIMITS=1 in statusLine.command to use them when the effective model ID is gpt-* or a recognized OpenAI OAuth routed form:
"command": "STATUSLINE_GPT_LIMITS=1 cc-statusline"
codex-usage-fetch.sh starts the official Codex app server in the background and calls its read-only account/rateLimits/read method. The Codex CLI handles its own ChatGPT login, account selection, credential storage, and token refresh; cc-statusline never reads or receives the OAuth token and makes no inference request. Run codex login status to verify that CLI is logged in.
The response can contain only a weekly window, only a 5h window, or both. Windows are identified by duration rather than primary/secondary position, and the statusline renders whatever is available. The cache preserves each window's exact reported duration for pace_arrow. Codex reports a rolling duration and reset timestamp, and a live active reset stayed fixed while usage increased, but a reset-to-zero boundary has not been observed directly. The GPT arrow is therefore a projection heuristic for active windows. Zero-percent uninitialized/sliding snapshots produce no arrow. GPT data lives in a separate private cache and never enters the Claude cache. If the GPT snapshot is unavailable or older than STATUSLINE_GPT_AUTH_TTL, the rate segment is hidden rather than showing unrelated Claude percentages.
The line-2 service icon also switches providers. GPT sessions read only the exact Codex API component from status.openai.com/api/v2/components.json, cache it separately from Claude status, and link the icon to status.openai.com. Missing, duplicate, or malformed component data leaves the last valid Codex status untouched; Claude page status is never substituted.
GPT renders never show Claude Code's native $... cost because Claude Code applies Claude model prices to GPT token counts. Instead, gpt-credits-fetch.sh streams the current main transcript and its subagents/*.jsonl, deduplicates repeated assistant responses by message ID, and estimates GPT-5.6 Sol usage at the flat rates published by ChatGPT Learn, verified 2026-09-10: 100 credits per million uncached input tokens, 10 per million cached input tokens, and 500 per million output tokens. Only recognized GPT-5.6 Sol routed IDs count; Claude, helper, opaque alias, and unknown model IDs are skipped.
The display is a ChatGPT credit-equivalent usage estimate, not billed dollars and not proof that credits were deducted while Pro usage remained within its included limits. The published ChatGPT table does not specify cache-write accounting or an API-style long-context multiplier, so neither is inferred. Any recognized row with nonzero cache_creation_input_tokens makes the session estimate unavailable rather than knowingly undercounting. The private cache is keyed by transcript path and refreshes asynchronously at most once a minute. Zero usage stays hidden; positive estimates appear as 211.29 cr below 1,000 or 2.07k cr at four digits. Set STATUSLINE_GPT_CREDITS=0 to hide it.
GPT sessions have been observed to report one context window with every usage counter at zero (used 0%, remaining 100%) between two normal readings. For a GPT effective model, independent of STATUSLINE_GPT_LIMITS, exactly that shape shows the session's last valid context percentage in dim gray instead of 0%, in both layouts; the capacity stays the current value. The last value is kept in a small private per-session file in the runtime directory. It is stored only when the transcript shows the matching assistant response after its last compact boundary, and it is used only while the session id, models, transcript path, and window size still match, the transcript is the same file (same device and inode, not shorter, and the last 4 KB before the recorded size unchanged; earlier edits to the same file are not detected, since the transcript is assumed to be append-only), and its last compact boundary is unchanged. A null or missing usage, any other zero-like shape, a /clear (new session id), a /compact, or a switch to a Claude model drops it, so a new session or one without a prior reading shows the native 0%. Genuine decreases, including a real 0% with input tokens, are always shown as reported.
Detection currently covers raw gpt-*, claude-ocx-native--gpt-*, clodex:openai-oauth:gpt-*, and anthropic-openai-oauth__gpt-* IDs, including a [1m] suffix. A short opaque alias such as sol cannot identify its provider by itself and is not detected. clodex:openai:* API-key routes are deliberately excluded because ChatGPT plan limits do not describe API-key usage.
Update indicator
When a newer cc-statusline release is available, line 1 ends with a gold ⇡ X.Y.Z at its right edge, Cmd/Ctrl+clickable (OSC 8) to that release's GitHub page. Nothing is shown while you are current, so a fresh install looks exactly as before. Upgrade with brew upgrade cc-statusline (Homebrew) or ./install.sh --version vX.Y.Z (installer), and the indicator disappears on the next render.
cc-statusline-update-fetch.sh runs in the background at most once an hour per user (spawned by the statusline, throttled across all your sessions) and asks GitHub's "latest release" endpoint (api.github.com/repos/vtmocanu/cc-statusline/releases/latest, unauthenticated, no credential involved) for the newest tag, which it compares against the VERSION file installed next to the script. The indicator is placed in the padding line 1 already has under a wider line 2, so on a typical render it costs no columns; when line 1 is the wider line and appending it would breach the width budget, it is dropped for that render rather than truncated. Only a plain vMAJOR.MINOR.PATCH tag is accepted (checked in both the fetcher and the statusline), so a malformed or tampered response can never reach the terminal. Disable with STATUSLINE_UPDATE_CHECK=0.
Versioning
Releases are tagged with semantic version tags (v2.0.0, v2.0.1, v2.1.0, ...). The main branch is always the latest tested state. The 2.x line is continuous with the script's pre-public history (it lived in a private dotfiles repo as statusline-modern.sh); see CHANGELOG.md for details.
To roll back:
# Reinstall a specific version (does not touch your clone)
./install.sh --version v3.6.0
The archived release must include the helper scripts required by the current
installer. Releases that predate those helpers need their own installer.
Testing
bash tests/run-tests.sh
# or, with go-task installed, the full validation suite (syntax + shellcheck + tests):
task ci
Runs the harness against the JSON fixtures in tests/fixtures/. Each fixture is piped through statusline.sh and asserted on:
- exit code 0
- exactly 2 stdout lines
- visible columns within
SAFE_WIDTH + WIDTH_SLOP(default 110 + 0) - empty stderr
CI runs the same harness on every push and pull request via .github/workflows/ci.yml, both under the default locale and under LC_ALL=C.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Line 2 missing in Claude Code | Line 1 exceeds the container width and cli-truncate drops subsequent lines |
Lower STATUSLINE_WIDTH (e.g. STATUSLINE_WIDTH=100) |
| Statusline not showing at all | Script crash; set -uo pipefail exits silently |
Run STATUSLINE_DEBUG=1 bash statusline.sh < /tmp/test.json and check /tmp/statusline-debug.log |
| Wrong project color | Color hash collision or stale override | Add the project root to ~/.claude/statusline-color-overrides.json |
| Service status icon missing | claude-status-fetch.sh not yet run, or curl failed |
Wait 60s, or run the fetcher manually: bash claude-status-fetch.sh |
| Update indicator never shows / stale | cc-statusline-update-fetch.sh not yet run (hourly), curl failed, or the per-user cache is stale |
Run it manually: bash cc-statusline-update-fetch.sh; it writes update-check in the state dir ($XDG_RUNTIME_DIR or $TMPDIR, cc-statusline-<uid>/) |
| Session title empty | Claude Code hasn't named the session yet (brand-new session), or you're on a Claude Code without .session_name |
Send a few prompts so a title is generated, or set one with /rename; upgrade Claude Code if the field is absent |
@handle missing |
Registry file absent (older Claude Code), or its shape changed | Upgrade Claude Code; the handle reads ~/.claude/sessions/*.json best-effort |
| Boxes/squares instead of icons | Terminal font is not a Nerd Font | Install one from nerdfonts.com and configure your terminal |
See KNOWN_ISSUES.md for known limitations.
Why two lines?
Claude Code's cli-truncate silently drops line 2 when a line exceeds the container width. This script measures visible columns with an ANSI-aware helper (it does not estimate) and truncates content (in priority order: K8s context, branch, agent, mode, title, session name, directory) before that happens. See the comments in statusline.sh for the full set of undocumented rendering quirks discovered through testing.
License
MIT, see LICENSE.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi