Release notes
Full notes and diffs live on the GitHub releases page.
v2.3.0 — fast enough to be right
A status line that renders slowly shows old numbers: Claude Code cancels a render that is still running when the next update arrives. On Windows (Git Bash), a render took about 9 seconds, so the line could stay minutes behind the session. This release rebuilds the render path, and fixes what that investigation found.
What’s new
- A render starts 5 processes instead of 113 — one
jqcall and onegit statuscall; everything else is bash builtins. Measured on the same machine: 9 s to 0.8 s on Windows (Git Bash), 178 ms to 65 ms on Linux. The usage API request moved to a background job (stale-while-revalidate), so it can never delay or cancel a render. - Windows (Git Bash) is supported — the directory showed as
C://Users//me//My Drive//Notes//Vault; it now shows as…/Notes/Vault, and the home directory is abbreviated to~. - Cold prompt cache — once the prompt cache has expired, the per-turn figure is replaced by
486k next turn (cache cold), with a hint: the next message re-writes the whole context at the cache-write rate. While the cache is warm, the context hint ends with its expiry time. Needs Claude Code ≥ 2.1.251;CESL_SHOW_CACHE=0turns it off. - A test suite and CI —
bash tests/run.sh, on Linux, macOS (bash 3.2) and Windows. versionsubcommand —statusline.sh version, andexplainprints the version too.
Fixes
- The Fable weekly row was hidden — the usage API marks the Fable weekly allowance as inactive while it counts usage, and inactive limits were dropped. A per-model row now shows when the limit is active or has usage.
- Context percentage matches Claude Code — the script truncated its own division (35%) where Claude Code rounds (36%). It now uses
context_window.used_percentagefrom stdin, and rounds when that field is absent. - Interrupted fetches left files behind — a render cancelled during an API request left
usage-cache.json.<pid>files in the cache directory. They are removed, and the fetch no longer runs where it can be cancelled. - A timed-out
git statusno longer looks complete — when the 2-second bound stops git, the counts are followed by…. - Worktree marker — uses
workspace.git_worktreefrom stdin when Claude Code sends it.
Compatibility
On a machine with no usage cache yet, the per-model and extra-usage rows appear on the second render, because the first one only starts the background request. explain still fetches in the foreground. The cache directory gains a usage-digest file. No configuration changes are required.
v2.2.1 — Fable 5.2 and Mythos 5.2
Fixes
- Per-turn cost on Fable 5.2 and Mythos 5.2 — both models read cache at 2.5% of the input price, like Fable 5.1, but
CESL_TURN_RATE=autogave them the 10% default, so/turnwas four times too high. Mythos 5.1 had the same problem.autonow uses 2.5% for Fable and Mythos 5.1 and 5.2. Fable 5 and Mythos 5 keep 10% (platform.claude.com model overview, November 2026).
v2.2.0 — Ultra plans and per-model cache rates
Two changes driven by Anthropic’s own updates: the Max 20x plan became Ultra on 2026-10-30, with no 5-hour limit for verified accounts, and Opus 5.5, Sonnet 5.5 and Fable 5.1 read cache cheaper than other models.
What’s new
- Per-model cache-read rate —
CESL_TURN_RATEnow defaults toauto. The per-turn cost uses the rate of the model you are on: 5% of the input price for Opus 5.5 and Sonnet 5.5, 2.5% for Fable 5.1, 10% for every other model (claude.com/pricing). On Opus 5.5, a 486k session now reads24k/turninstead of an overstated48k/turn. A number inCESL_TURN_RATEstill wins.explainshows the rate and where it came from.
Fixes
- Ultra accounts keep their per-model and extra-usage rows — a usage-API payload was only accepted when it had a
five_hoursection. Without a 5-hour limit, that section can be empty, and the whole payload (per-model weekly limits included) was thrown away. A payload is now accepted when it has at least one non-empty known section; error bodies still never reach the cache. With no 5-hour data in stdin, the 5-hour row is not drawn, andexplainsays why. - Stricter
CESL_TURN_RATE— a value that is not one number between 0 and 1 (.,1.2.3,5) falls back toautoinstead of rendering 0 or millions of tokens per turn.explainnames the invalid value. - Clearer hint line — “every turn re-sends it, ~24k at the cache rate”: the whole context is re-sent, and the number is what that costs.
Compatibility
The default per-turn rate changes from 0.1 to auto, so /turn numbers halve on Opus 5.5 and Sonnet 5.5 (and drop to a quarter on Fable 5.1). Set CESL_TURN_RATE=0.1 to keep the old numbers. No other breaking changes.
v2.1.0 — what a turn costs
A percentage tells you how much room is left. It does not tell you what the next message costs, and on a 1M-token window those two diverge badly. This release closes that gap, and makes the rate-limit dashboard something you can trim a row at a time.
What’s new
- Per-turn context cost —
48k/turnin the metrics group: the whole context re-sent at the cache-read rate, which is what every message costs before you type a character. Coloured on absolute token thresholds (CESL_CTX_WARN60k,CESL_CTX_HIGH120k), because a percentage of a large window hides exactly this. - Turn count —
88t, the API requests on this conversation so far (Claude Code ≥ 2.1.251). - Pace projection — the 5-hour and 7-day rows can end with
⇢ 94%: where the window lands at the current burn rate. Stateless — the window opened atresets_atminus its own length, so the elapsed fraction comes from the payload with no state file and no extra request. Quiet unless the pace actually overruns. - Context hint line — one line under the dashboard naming the right command.
/compactfor a window that is nearly full,/clearfor a session that is merely expensive; a 486k conversation on a 1M window is half full and still pays 48k a turn, so compacting it misses the point. - Per-row rate-limit toggles —
CESL_SHOW_EXTRA,CESL_SHOW_SCOPEDandCESL_SHOW_PROJECTIONswitch individual rows. On a Team plan the org can have extra usage enabled at the billing level with nobody intending to use it, and hiding that row no longer means losing the 5-hour, 7-day and per-model rows with it (#13, reported by @mh-holdrent). - The API call is now skippable — with both
CESL_SHOW_SCOPED=0andCESL_SHOW_EXTRA=0nothing needs enrichment, so OAuth token resolution and the HTTP request are skipped entirely on every render. NO_COLORsupport —NO_COLORandTERM=dumbare honoured, andCESL_COLOR=0/1overrides the detection either way. Stripping happens at a single point before output, so no segment can leak colour past the gate.explainreports the new values — per-turn cost, context thresholds, projections, colour resolution and whether the API fetch was needed at all.
Compatibility
No breaking changes. Every new segment is on by default and every one has a CESL_SHOW_* toggle; existing config files keep working untouched.
cd claude-epic-status-line && git pull && bash install.sh
v2.0.0 — the epic redesign
A ground-up rewrite, designed around one idea: quiet when healthy, loud exactly where something needs attention.
What’s new
- New layout — a refined single line (model · context · dir+git · cost · duration · lines ± · effort · badges) plus an always-visible rate-limit dashboard with
█░bars for the 5-hour window, 7-day window, per-model weekly limits (data the official UI does not surface), and extra-usage credits. - Semantic colour — one escalation scale everywhere (yellow ≥ 70%, orange ≥ 80%, red ≥ 90%), model name coloured by family, and a steady bold
⚠instead of a blinking one. - stdin-first data — rate limits, cost, duration, lines changed, effort, fast-mode / thinking / vim / output-style badges and the subagent name all come from Claude Code’s own status JSON (2.1.140 or newer recommended; older versions degrade gracefully). The usage API is queried only for enrichment, cached per-user with a single-flight lock and negative caching.
- Configuration system — zero-config by default;
~/.config/claude-epic-status-line/config.sh(scaffolded byinstall.shwith all knobs commented out) plusCESL_*environment overrides for thresholds, palette and model hues, bar width, glyph sets, per-segment toggles, currency conversion and cache TTL. explainsubcommand — pipe a status JSON throughstatusline.sh explainto see the raw input, every parsed value, cache state and effective config.- Adversarially reviewed — four review rounds across two reviewers, 34 findings fixed: terminal-escape injection, OAuth token exposure on argv, arithmetic overflow and octal traps, hostile-JSON handling, installer data-loss paths, cache races and macOS portability bugs. Hostile inputs now degrade, never corrupt.
Breaking changes
- Rate-limit labels renamed
current/weekly→5-hour/7-day; bars are now█░(dots are still available viaCESL_GLYPHS). - Effort is read from the session’s stdin (
effort.level); the~/.claude/settings.jsoneffort read is gone. - The usage cache moved to a per-user directory (
$XDG_RUNTIME_DIR/claude-statusline-$UIDor equivalent). - The blinking context warning was replaced by a steady bold one.
Upgrading
cd claude-epic-status-line && git pull && bash install.sh
Your config file is never touched by the installer.
v1.0.1 — bug-fix release
- Fixed rate-limit percentages exceeding 100%.
- Revived the cost and duration segments, which could silently render empty.
- Hardened the usage cache.
- Fixed date handling on macOS.
v1.0.0
Initial release: model, context usage, git branch and status, session cost, duration and rate limits in a single status line.