Repository navigation
feat(widgets): allow speed widget windows up to an hour - #769
Merged
Merged
Conversation
The Input, Output and Total Speed widgets' rolling window was capped at 120 seconds. Nothing in the calculation needs that cap: every render reads the whole transcript whatever the window, the window ends at the transcript's last entry and counts only the time responses were being generated, and a window longer than the session gives the session average. The cap only rules out longer horizons, such as the last 10 minutes or the last hour of a session. Raise the cap to 3600 seconds. The window editor already takes any number of digits and clamps on save, so 3600 is now kept and a longer value saves as 3600, the way 120 did before. Past the session's length a window equals the session average, which 0 already gives, so a bound loses nothing, and it keeps a typo such as 36000 from quietly meaning the whole session. Windows saved under the old cap read the same.
# Conflicts: # docs/USAGE.md
# Conflicts: # docs/USAGE.md
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 was referenced Nov 7, 2026
Closed
Closed
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.
What
The rolling window on the Input, Output and Total Speed widgets now goes up to 3600 seconds (an hour) instead of 120. The editor keeps a typed 600 or 3600. Anything longer saves as 3600, the same way values above 120 used to save as 120. 0 still means the whole-session average.
Why
The 120-second cap came in with the speed widgets in #141, and no reason was recorded for it. Nothing in the calculation needs it:
So the cap only rules out windows someone might want, such as the last 10 minutes or the last hour of a long session. Those smooth out the swings of a two-minute window without going all the way back to the start of the session.
Measured with two made-up transcripts, 40 minutes and 2 hours long. Each has one 20-second response a minute at 60 output t/s, then 30 t/s for the last 10 minutes and 15 t/s for the last 2. The line has five Output Speed widgets with windows of 0, 120, 600, 3600 and 36000 seconds:
mainThe built CLI prints the same under Bun 1.4.2 and Node 26.10.0. On
main, every window above 120 reads as 120. On this branch, 600 covers the last 10 minutes, and on the 40-minute session 3600 matches the session average.Render time doesn't depend on the window. Over a 100,000-line (11.9 MB) transcript, the built CLI took 180-189 ms under Bun and 391-412 ms under Node, for windows of 0, 120 and 3600 alike (7 runs each).
Why an hour rather than no limit: once a window is longer than the session, it gives the session average, and 0 already gives that. A limit loses nothing, and it stops a typo such as 36000 from quietly meaning the whole session. In the 2-hour row, 36000 reads as the last hour (54.5) and not as the session average (57.3).
How
MAX_SPEED_WINDOW_SECONDSgoes from 120 to 3600. Every clamp reads it: saving from the editor, reading a widget's saved window, and the list of windows the render asks the transcript scan for. The scan (normalizeSpeedWindowsinjsonl-metrics.ts) has no upper limit of its own.windowedSpeedMetricsis keyed by the clamped value on both the request side and the lookup side, so nothing else changes.(0-3600).docs/USAGE.mdnow say0-3600.settings.jsonby hand used to read as 120; it now takes effect, up to 3600.(600s window),(3600s window)). The editor takes seconds and the label repeats the number typed. Switching to minutes for round values would show10mfor a typed 600 next to90sfor a typed 90.0-120, because they describe that release.Demo
In the line editor: select Output Speed, press
w, clear the 0, type 600, press Enter and save with ctrl+s. Before, the row then shows(120s window); after, it shows(600s window). The TUI preview only has sample values, the same for every window, so each GIF then quits the TUI and pipes a payload through the CLI with the saved settings.The transcript in that payload is synthetic, written for the demo. It covers 25 minutes in five turns, with idle gaps between them. Every response runs at 30 output t/s, except the three in the last turn, which run at 80 t/s within the transcript's final 70 seconds. That gives three different figures: 35.0 t/s for the session average, 40.0 t/s for the last 600 seconds and 80.0 t/s for the last 120 seconds. The before GIFs end on 80.0 t/s, the 120-second figure, because the 600 was saved as 120. The after GIFs end on 40.0 t/s, the 600-second figure. Rendered directly with windows of 0, 120 and 600 seconds,
mainreads 35.0, 80.0 and 80.0, and this branch reads 35.0, 80.0 and 40.0.Powerline
Before:
After:
Plain
Before:
After:
Testing
mainas of [low] perf(claude-status): hold a lock while the status page fetch is in flight #635 and [medium] perf(git-review): key the PR cache through the cached runGit #639 (62a371b): merges cleanly,bun run lintis clean, andbun testgives 3711 pass, 0 fail. The built CLI under Bun 1.4.4 and Node 26.13.0 matchesmainin plain and Powerline mode with the baseline configs, and the TUI opens and exits cleanly.bun test: 3176 pass, 0 fail (179 files).mainhas 3168 pass (178 files).main:0-3600; the editor saves 600 and 3600; the editor clamps 3601 to 3600.main. They check that a saved 120-second window reads and saves unchanged.bun run lintis clean.main's code, the same 10 fail.main. The TUI opens and exits cleanly under both. Windowed renders are in the table above.