Repository navigation
Releases
v0.9.6
- Honor the
autoCompactWindowsetting from~/.claude/settings.json(Claude Code 2.1.311+, also written by/autocompact): env var first, then the per-modelmodelSettingsentry, then the top-level value. Previously onlyCLAUDE_CODE_AUTO_COMPACT_WINDOWwas read, so line 2 kept measuring against the full window.
v0.9.5
v0.9.4
Every install channel now ships from a tagged release instead of main.
Until now both the manual curl and /claude-pace:setup fetched raw.githubusercontent.com/.../main/claude-pace.sh, so what you installed was whatever main happened to be at that second — not a version anyone could name, reproduce, or roll back to. Releases, tags and the npm package recorded versions but were never what actually shipped.
The issue was reported against the manual curl only, but setup.md ran the same command, so the "recommended" plugin path was installing main too.
/claude-pace:setupmakes no network calls. It copies${CLAUDE_PLUGIN_ROOT}/claude-pace.sh, the script the plugin already bundles. The plugin was downloading a second copy of a file it was carrying — a package manager ignoring its own package. There is deliberately nocurlfallback: a missing bundled script means a broken plugin install, and the command stops and says so.- Marketplace entry pins to the release tag. The previous
"source": "./"served the default branch, so pinningsetup.mdalone would still have handed new installs the contents ofmain. - Manual install pulls
releases/latest/download/claude-pace.sh, withreleases/download/vX.Y.Z/claude-pace.shdocumented for pinning an exact version. - The manual
curlgained the-fit was missing. Without it a 404 exits 0 and writes the literal textNot Foundinto~/.claude/statusline.sh, which the next line thenchmod +x. This was a live defect independent of the version-pinning issue.
What this does and does not buy: bad code now has to pass through an explicit release action to reach users, which blocks accidental merges, unreviewed pushes, and force-pushes to main from shipping directly. It does not defend against anyone who can publish releases or a compromised maintainer account, and a lightweight tag remains a movable ref.
Upgrading an existing plugin install:
/plugin marketplace update claude-pace-marketplace
/plugin update claude-pace
/reload-plugins
/claude-pace:setup
Reported in #16.
v0.9.3
- Stop stranding temp files in the cache directory. Cache records went through
mktemp+mvfor atomicity, but Claude Code cancels the status line script whenever a refresh arrives while it is still running, so every cancellation landing between the write and themvleft a uniquely named temp file behind permanently. On a slow machine that is the normal path, not an edge case: the reporter's~/.cache/claude-pace/had accumulated 3008 orphanedclaude-sl-tmp-*files (1913 of them zero-byte) against 45 real cache records, and the directory size then fed back intomktempandstatlatency. Records are now written straight to their final path (#17, diagnosis and field data by @volkanncicek) - Rationale for dropping atomicity rather than bounding the temp files: a cache record is one short line of git metadata with a 5s TTL, so a torn write is simply a cache miss — the reader already sanitizes non-numeric fields and the next run recomputes from git. Removing the temp file makes the orphans impossible instead of merely bounded, drops two subprocess spawns per refresh (worth ~400ms on Git Bash, where each spawn costs 180-300ms), and shrinks the cancellable window from "across two process launches" to a single builtin write
- Refuse symlinked cache paths explicitly:
mvused to replace the symlink itself, while>follows it. Covered by the existing Test 16, which fails without the guard - Existing
~/.cache/claude-pace/claude-sl-tmp-*files from earlier versions are orphans, ignored by claude-pace, and safe to delete - Add regression coverage asserting the invariant directly — a cache write spawns neither
mktempnormv— since a leftover-file check alone cannot catch this class of bug (a temp-file scheme also cleans up after itself whenever the run completes)
v0.9.2
- Fix the auto-compact bar briefly showing the model's full window (e.g.
0% 1M) at the very start of a session. Claude Code sendscontext_window.total_input_tokensas0on a fresh session's first frame, and v0.9.1 only recomputed against the auto-compact window when that value was> 0— so the bar (and its1Mlabel) fell back to the full window until the first API response landed, the exact1Mflash issue #15 set out to remove. The recompute now fires whenever the field is present, including a genuine0, and falls back to the full window only when Claude Code omits the field entirely (older CC that predatestotal_input_tokens). jq now emits a-1sentinel for the missing field so a real0(fresh-session first frame) and an absent field no longer collapse to the same value (follow-up to #15) - Add regression coverage for the present-zero first frame measuring against the compact window, plus an explicit guard that a missing field never relabels to the compact window
v0.9.1
Track context against CLAUDE_CODE_AUTO_COMPACT_WINDOW.
Since Claude Code 2.1.117 the statusline's context_window.context_window_size is the model's full window (e.g. 1M for Opus 4.7) and used_percentage is measured against it. On a context capped by CLAUDE_CODE_AUTO_COMPACT_WINDOW (e.g. 400K) the bar filled against 1M and looked nearly empty right as auto-compaction was about to fire.
When the env var is set and context_window.total_input_tokens (CC 2.1.132+) is available, the bar now measures used tokens against the auto-compact window and relabels the size (e.g. 15% 400K), matching the desktop app's context indicator. Clamped to the real window, capped at 100%, and falls back to full-window behavior when the env var is unset or token data is missing (early session). Line 1 keeps the model's full-window label (e.g. (1M)) because that reflects the model's capability, not the active budget.
Closes #15
v0.9.0
Breaking change
Removes the last-known quota cache fallback. When stdin rate_limits is absent, claude-pace now shows -- for 5h/7d quota and the session cost when available, instead of replaying a cached snapshot from a previous run.
Cross-provider contamination reported by @kvdb in #14 surfaced the underlying identity gap: stdin carries no provider/account identifier, so a cached account-level snapshot cannot be proven to belong to the current session. Multi-provider users (e.g. Claude Max + Microsoft Foundry) saw one account's quota leak into the other. Showing -- is an honest failure mode; replaying a wrong-account snapshot is a silent wrong answer.
The per-project cache key proposed in PR #14 would only paper over the most common collision pattern without restoring identity, so the fallback is removed entirely instead of re-keyed.
See docs/decisions/2026-05-20-quota-cache-removal.md for the full reasoning and the conditions under which a cache could be reintroduced.
What you need to know
- Claude Code
>=2.1.80providesrate_limitsin statusline stdin — the common case is unaffected - Sessions where
rate_limitsis absent now show--for 5h/7d quota and the session cost when present - Existing
~/.cache/claude-pace/claude-sl-quota*files from v0.8.x are now orphans, ignored by claude-pace, and safe to delete manually
Diffstat
- Drops ~250 lines covering quota cache write/read, snapshot validation, symlink and unreadable-file hardening, and expired-reset guards
- Tests: Test 19-33 replaced with two tighter behavior contracts (absent
rate_limits→ placeholders + session cost without consulting any cache; legacy orphan quota cache files are ignored)
v0.8.6
Fixes
- Windows Git Bash compatibility: replace
jq --slurpfile+ process substitution with--argjson./proc/<pid>/fd/Nis unavailable on Windows, which previously causedMODELandDIRto render blank. Thanks @capraCoder in #13. - Settings validation: validate
~/.claude/settings.jsonwithjq -e .before passing to--argjson, falling back to{}for empty, whitespace-only, or malformed JSON so settings parsing failures stay localized to effort level.
Verification
98 regression assertions pass on Linux/macOS. Windows Git Bash + jq 1.8.1 verified by the PR author.
Full diff: v0.8.5...v0.8.6
v0.8.5
- Show the effort level as a word (
low/medium/high/xhigh/max) on line 1 instead of a glyph, for readability (#12) - Bump model-name truncation budget on line 1 from 22 to 28 chars to fit the longest word (
medium) without clipping - Update regression tests to assert effort word + pipe alignment for all five levels, and pin the new 28-char truncation budget so a
Sonnet 4.6 (200K) mediumline stays unclipped