Repository navigation
feat(usage): add Weekly Limit Timer and Weekly Fable Limit Timer widgets - #768
Merged
Merged
Conversation
Two widgets that say how long until a 7-day limit at this week's average pace, shown only when that comes before the window's reset: `Weekly limit in: 1d 22hr 40m` for the all-models window and `Fable limit in: 1d 4hr 8m` for Fable's. The pace is the window's percent over the time since it started (its reset minus 7 days), so nights and days off count; a 30-minute pace like Block Limit Timer's would put the limit a day away during any busy hour. Both stay hidden during the window's first day, when the limit comes after the reset, and at 100%. Block Limit Timer's rendering, `s` key, raw value and 1-minute floor move into a LimitTimerWidget base that all three timers share.
pcvelz
added a commit
to pcvelz/ccstatusline-usage
that referenced
this pull request
Nov 2, 2026
Upstream: weekly limit timers (sirmalloc#768), prompt cache miss widgets (sirmalloc#770), context window size env override (sirmalloc#352, sirmalloc#407), windowed speed fixes (sirmalloc#769, sirmalloc#771), separator/renderer fixes (sirmalloc#773), custom-command styling (sirmalloc#775), clickable cwd links (sirmalloc#744), account email from live credentials (sirmalloc#724), cache timer reported expiry + short toggle (sirmalloc#576, sirmalloc#592), claude-status lock (sirmalloc#635, sirmalloc#772), dedup token metrics (sirmalloc#622, sirmalloc#725, sirmalloc#735). Not adopted: sirmalloc#765 terminal width from COLUMNS with fixed reserve - the fork keeps flexMode/compactThreshold and tmux pane priority. Hand edits outside conflicts: - README.md: kept fork Configure flex separator behavior bullet and older-updates details wrapper; dropped upstream Related Projects additions (claude-eta) - AGENTS.md: kept fork terminal width wording (sirmalloc#765 not adopted) - src/types/FlexMode.ts, src/tui/components/TerminalWidthMenu.tsx, src/tui/components/__tests__/TerminalWidthMenu.test.ts, src/tui/components/TerminalOptionsMenu.tsx, src/tui/components/__tests__/TerminalOptionsMenu.test.ts: restored, fork keeps terminal width settings - src/tui/App.tsx, src/tui/components/index.ts, src/types/index.ts: re-wired terminal width menu and FlexMode export - src/types/StatusJSON.ts: dropped fork duplicate prompt_cache key, upstream schema is a superset - src/utils/terminal.ts: COLUMNS source gated on non-tmux so tmux pane width keeps priority - src/widgets/WeeklyLimitTimer.ts, src/utils/usage-prefetch.ts, src/widgets/__tests__/WeeklyLimitTimer.test.ts: compat fix - fableUsage/fableResetAt -> weeklyFableUsage/weeklyFableResetAt - src/widgets/ApiUsage.tsx: compat fix - Context Bar honors effective context window (override, clamp, 1.0M format); Weekly renders a valid value despite a session error - src/widgets/__tests__/ApiUsage.localModelFallback.test.ts: output tokens no longer counted in context (upstream sirmalloc#730) - src/utils/__tests__/renderer-flex-width.test.ts, src/utils/__tests__/renderer-ansi.test.ts, src/utils/__tests__/gradient.test.ts, src/utils/__tests__/renderer-separator-collapse.test.ts, src/utils/__tests__/config.test.ts, src/tui/__tests__/App.test.ts: fork deviation - fork width model (flexMode, 6-column full reserve, kept settings, Terminal Width menu entry) - src/utils/__tests__/default-colors.test.ts: fork deviation - accept ansi256:/hex: defaults - src/utils/__tests__/usage-prefetch.test.ts: fork deviation - weekly usage comes from the API, fork widget imports from ApiUsage - src/widgets/__tests__/CurrentWorkingDir.test.ts, src/widgets/__tests__/CustomCommand.test.ts: Settings literal gains flexMode/compactThreshold - src/utils/__tests__/context-window.test.ts, src/utils/__tests__/jsonl-metrics.test.ts: restored fork tests upstream dropped - docs/test-retirements.md: ledger for the dev-reload snapshot-path and RemoteControlStatus glyph (sirmalloc#605) tests upstream replaced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Relates to #55, where a user asked for a projection of the 5-hour and 7-day limits.
What
Two widgets that say how long until a 7-day limit at this week's average pace, shown only when that comes before the window's reset:
Weekly limit in: 1d 22hr 40m. Its label reads as a countdown, like Block Limit Timer'sLimit in:.Fable limit in: 1d 4hr 8m.sfor the short form (1d22h40m), as Block Limit Timer does. Neither ever shows0m.Why
Block Limit Timer answers "will I hit the 5-hour limit before it resets?" The weekly limits raise the same question over a longer stretch, and running out of one costs days rather than hours. Fable has a weekly limit of its own, which Weekly Fable Usage already shows.
The pace has to differ from the 5-hour one. Block Limit Timer extrapolates the last 30 minutes, which suits a window you work through in one sitting. Nobody works a week straight, so the same rule would put a weekly limit a day or two away during any busy hour. These use the week's average instead, the window's percent over the time since it started, so nights and days off count toward the pace. The window is the account's own: it starts at its reset time minus 7 days, not at a calendar week.
They wait a day because early on, a single busy hour would read as the week's pace.
How
utils/weekly-limit.ts,getWeeklyLimitInMs({ percent, nowMs, resetAtMs }): a pure function.percent / elapsed, whereelapsedruns fromresetAt − 7 daysto now, and the limit comes in(100 − percent) × elapsed / percent.widgets/shared/limit-timer-widget.ts:skey, editor display, raw value and the 1-minute floor move into aLimitTimerWidgetbase.WeeklyLimitTimertakes the window it follows, from a small table, as the usage percent widgets take their kind:weeklyUsageandweeklyResetAt, from the payload'srate_limits.seven_dayor the usage API;fableUsageandfableResetAt, from the usage API only, since the payload has no Fable window. Like Weekly Fable Usage's time cursor, Fable's window falls back to the all-models reset when the API sends none of its own.FableWeeklyLimitTimeris the Fable instance. Neither needs a history file.Prefetch: each widget requires its window's percent and reset; for Fable, the all-models reset can stand in for Fable's. A failed fetch made only for these widgets isn't an error for the rest of the line, as with the forecast widgets.
Registered after Weekly Usage and Weekly Fable Usage.
docs/USAGE.mddescribes both, and the key list now sayssfor all three limit timers.Demo
Piped from seeded payloads (made-up data) in six situations. The first five show Weekly Usage, Weekly Limit Timer and Weekly Reset Timer. The last adds Weekly Fable Usage and Weekly Fable Limit Timer: Fable is on pace for its limit while all models aren't. Its Fable percent comes from a seeded usage cache, since the payload has no Fable window.
Powerline
Plain
Adding Weekly Limit Timer after Weekly Usage with the picker's search; the preview shows its sample.
Powerline
Plain
Testing
weekly-limit.test.ts:WeeklyLimitTimer.test.ts(Date.nowstubbed): one suite runs for both widgets.1d 13hr,2d 4hr), the editor display ands.usage-prefetch.test.ts:rate_limits.seven_daywithout fetching, and fetches only a missing reset, quietly.fableUsagewhen the payload has the all-models reset, quietly when that fails.widgets.test.ts: the catalog lists both under Usage.main:bun test3736 pass, 0 fail (Bun 1.4.2).bun run lintpasses. Under Node (Vitest), the five changed test files pass 131 of 131.1d 22hr 40m, hidden,2d 6hr, hidden, hidden, andFable limit in: 1d 4hr 8mbeside a hidden all-models timer.runtime-check.shmatchesmainwith the baseline configs. With the Fable demo config and the seeded HOME, both runtimes agree and differ from the base only by the new widgets.