Skip to content

feat(usage): Block Usage can hide at 100%, swapping with Block Reset Timer - #747

Merged
sirmalloc merged 1 commit into
sirmalloc:mainfrom
eric-engberg:feat/block-usage-hide-at-limit
Oct 29, 2026
Merged

sirmalloc merged 1 commit into
sirmalloc:mainfrom
eric-engberg:feat/block-usage-hide-at-limit

Conversation

@eric-engberg

Copy link
Copy Markdown
Contributor

What

Block Usage gets a new hide state, when the 5-hour block is at 100% (at-limit, off by default). It's the mirror of Block Reset Timer's under-limit state from #697. With both turned on, the two widgets take turns: the block's percent shows until the limit, then the reset countdown takes its place.

Why

At the limit, the percent stops telling you anything: it reads 100% until the block resets, and what you want to know then is when you can work again. With only #697, a line that pairs the two shows both at the limit:

5h: 100.0%  |  5h reset 1hr 43m

and the percent next to the countdown is noise. Hiding it leaves the one number that matters:

5h reset 1hr 43m

How

  • One shared check. isAtSessionLimit in widgets/shared/usage-display.ts holds Block Reset Timer's test from feat(usage): Block Reset Timer can hide until the 5-hour block hits 100% #697, including the fix that went in with it: the usage API's raw percent when prefetch accepted one, else the payload's own percent, at 100 or more. An API percent prefetch rejected, as stale or from a block that has since reset, never counts, even when the merged usage data still holds it. Block Reset Timer now calls the check instead of its inline copy, and Block Usage's new state calls the same function, so the two always flip in the same render: never both, never neither. 99.7% that a whole-number percent shows as 100% still counts as under the limit, as in feat(usage): Block Reset Timer can hide until the 5-hour block hits 100% #697. The check takes the render context, since it reads the payload's percent.
  • Same data, no extra requests. feat(usage): Block Reset Timer can hide until the 5-hour block hits 100% #697's prefetch rule asks the usage API for the block's percent for a Block Reset Timer with under-limit. It now covers a Block Usage with at-limit too, through the same cache, so a line with both makes one request, and a line with neither state makes none (tested).
  • What stays the same: with the state off, Block Usage renders exactly as before; unknown usage keeps its no-data behavior ([Timeout] and friends, or hidden with no-data); the TUI preview keeps its sample.
  • The 5h label in front of the countdown: with under-limit on, Block Reset Timer only appears at the limit, so relabeling it (e, e.g. 5h reset ) keeps the 5h label where the percent was. USAGE.md says so next to both states.

Demo

Block Usage (at-limit) and Block Reset Timer (under-limit, label 5h reset ), piped with the 5-hour block at 61% and at 100% (fake rate_limits, reset 1hr 43m away). Before is main, where the new state doesn't exist.

Powerline

Before:

Before: at 100% the percent shows next to the countdown, Powerline

After:

After: at 100% only the countdown shows, Powerline

Plain

Before:

Before: at 100% the percent shows next to the countdown, plain

After:

After: at 100% only the countdown shows, plain

Turning the state on in the line editor: h on Block Usage, check "when the 5-hour block is at 100%", and the row reads (hide: at-limit). The preview keeps its sample.

Powerline

Turning on Block Usage's at-limit hide state, Powerline

Plain

Turning on Block Usage's at-limit hide state, plain

Testing

  • bun test: 3209 pass, 0 fail (26 new: the shared check's cases, Block Usage's state, the swap with Block Reset Timer, and the prefetch). bun run lint passes.
    • Block Usage: shown at 60% and 99.7%, hidden at 100% and 100.4%, the API's percent over a lagging payload's (both directions), unknown usage unchanged with and without no-data, state off at 100%, preview unaffected.
    • Swap: for five usage cases, exactly one of Block Usage (at-limit) and Block Reset Timer (under-limit) renders.
    • Prefetch: fetches the block's percent for at-limit even when rate_limits has one, fetches once for a line with both states, doesn't fetch without the state, and falls back to the payload's percent when the fetch fails.
  • Under Node (Vitest), the four changed test files pass, 146 of 146.
  • Built CLI under Bun 1.4.2 and Node 26.10.0, with a fake login and a seeded usage cache (no API call), at 61% and 100%: all runtimes agree in plain and Powerline modes (5h: 61.0% / 5h reset 1hr 42m); the TUI opens and exits cleanly under both.
  • After merging feat(usage): Block Reset Timer can hide until the 5-hour block hits 100% #697's fix that ignores a cached block percent once its block has reset (it now applies to at-limit too, through the same shared check): bun test 3211 pass, 0 fail; bun run lint passes.
  • Rebuilt as one commit on today's main (after feat(usage): Block Reset Timer can hide until the 5-hour block hits 100% #697 merged): the shared check follows feat(usage): Block Reset Timer can hide until the 5-hour block hits 100% #697's final rule above, with a new test that a rejected API percent at 100% doesn't hide Block Usage, and the Block Usage tests now pass the payload's percent through the render context as Block Reset Timer's do. bun test 3277 pass, 0 fail; bun run lint passes.

…Timer

At the 5-hour limit, the block's percent says nothing new: it's 100% until
the reset, and the countdown is what matters. Block Usage gets an "at-limit"
hide state, the mirror of Block Reset Timer's "under-limit": with both on,
the reset countdown takes the percent's place once the block is used up.

Both states read one shared check, isAtSessionLimit, which reads the
percent the way Block Reset Timer's under-limit state does: the usage API's
raw percent when prefetch accepted one, so 99.7% shown as "100%" isn't the
limit yet and a lagging payload doesn't decide, and otherwise the payload's
own percent, never an API percent prefetch rejected as stale. The two
widgets therefore always swap in the same render, never both or neither.
The prefetch asks the usage API for the block's percent for either state,
through the same cache, so a line with both makes one request.
@sirmalloc
sirmalloc merged commit 59524d6 into sirmalloc:main Oct 29, 2026
3 checks passed
axisrow added a commit to axisrow/ccstatusline that referenced this pull request Oct 29, 2026
sirmalloc#755 live picker preview, sirmalloc#754 fast mode widget, sirmalloc#753 thinking-effort test stub, sirmalloc#752 transcript block fallback fixes, sirmalloc#751 editor keys no longer pause on global install lookup, sirmalloc#750 git cache TTL starts after the run, sirmalloc#749 npx cache skip, sirmalloc#747 Block Usage hides at 100% and swaps with Block Reset Timer)

Conflict policy: upstream infra wins, fork features ported on top. Joins:
sirmalloc#750 stamps the git cache after the run while keeping the fork's execGit
hardening/env snapshot and daemon prefetch bookkeeping; sirmalloc#752's
isApiErrorMessage guard lands in the fork's shared collectTimestampFromLine
(sync + async twins), upstream's duplicate getActivityTimestamp dropped;
sirmalloc#747 adds SESSION_AT_LIMIT alongside the fork's zero hide state
(BlockResetTimer keeps zero + under-limit via isAtSessionLimit, SessionUsage
is no-data/zero/at-limit); sirmalloc#755 replaces the fork's picker window + "Showing
X-Y of N" note with upstream's renderWindowedList/getPickerMaxVisible and
live preview (markers ↑/↓ N more cover the counts); sirmalloc#751's installationState
useMemo replaces the fork's inline lookups, the fork's mainMenuIndex helper
is kept.

Co-Authored-By: Claude Code <[email protected]>
pcvelz added a commit to pcvelz/ccstatusline-usage that referenced this pull request Oct 29, 2026
Upstream: Extra Usage Limit widget (sirmalloc#756), live widget preview while picking (sirmalloc#755), Fast Mode widget (sirmalloc#754), transcript block fallback fixes (sirmalloc#752), editor keys on a global install (sirmalloc#751), git cache TTL (sirmalloc#750), npx cached copy skip (sirmalloc#749), Block Usage hide at 100% (sirmalloc#747), Block Reset Timer hide until 100% (sirmalloc#697), fish-style branch abbreviation (sirmalloc#614), jj detached HEAD (sirmalloc#705), hooks save warning (sirmalloc#703), dev reload (sirmalloc#700), merge ends at a hidden widget (sirmalloc#698), Block Forecast and Block Limit Timer widgets (sirmalloc#699), contributor guide (sirmalloc#706), POSIX path case fix (sirmalloc#707), whitespace-distinct conflict filenames (sirmalloc#709), Quick Start reorder (sirmalloc#715), bunx launch guidance (sirmalloc#714), jj diff summary counts (sirmalloc#711), powerline manual separators (sirmalloc#713), keychain credential by account (sirmalloc#532), Keychain probe timeout (sirmalloc#760), usage cache scoped per CLAUDE_CONFIG_DIR (sirmalloc#266), test isolation (sirmalloc#717, sirmalloc#753), dev-dependency bumps (sirmalloc#745)

Conflicts resolved per the standard-resolution table; fork deletions re-applied.

Hand edits outside conflicts:
- src/utils/global-command-resolution.ts: fork-rename (ccstatusline@ -> ccstatusline-usage@ in upstream's new bunx pattern)
- src/utils/__tests__/global-package-manager.test.ts: fork-rename (package dir ccstatusline-usage in upstream's new tests)
- src/utils/usage-fetch.ts: compat fix - cacheUsageData gained a fetchedAtMs arg (upstream sirmalloc#266); adapted the fork-only fetchFreshUsageData call site
- src/utils/__tests__/usage-fetch.test.ts: compat fixes - cache/lock now hashed per CLAUDE_CONFIG_DIR (usageFilePath helper) in four fork tests; upstream fableUsage renamed to fork's weeklyFableUsage; seedUsageCache takes TokenHome
- src/utils/__tests__/usage-prefetch.test.ts: compat fix - mockFetchUsageData renamed to upstream's mockFetchUsage in cleanly-merged tests
- README.md: took upstream's Quick Start move (sirmalloc#715) and dropped the fork's old copy; fork-rename of its ccstatusline@ specifiers; links to fork-deleted docs (docs/USAGE.md, docs/WINDOWS.md) replaced with the fork's inline text
- CONTRIBUTING.md: links to the fork-deleted docs/DEVELOPMENT.md pointed at the README Development section
- docs/test-retirements.md: ledger entries for the 12 upstream test renames (sirmalloc#697, sirmalloc#698, sirmalloc#700, sirmalloc#705, sirmalloc#713, sirmalloc#760)
eric-engberg added a commit to eric-engberg/ccstatusline that referenced this pull request Oct 30, 2026
…build

The branch was rebuilt on today's updated #115 and #80, which hold upstream
main; #71 and #89, which it also merged, are upstream (sirmalloc#697, sirmalloc#747) and in
#115 through main. This keeps the old history so the push is a
fast-forward; the tree is the rebuild's.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants