Repository navigation
Description
Overview
Show a provider's five-hour window only when that provider reports it, for both Claude and Codex.
Whether an account has a five-hour limit now depends on the provider and plan. Accounts without one currently see dead UI: the menu bar shows --·70, the compact label shows -- permanently because it displays the first window only, and the popover keeps a "5-hour Unavailable" row.
Reference: owner direction, 2026-11-02. Plan-dependent changes are reported for Claude and Codex.
Requirements
Use one rule for both providers: the five-hour window appears only when the current usage data has a value for it. Do not look up the plan.
- A plan check gives the wrong answer today:
claude auth status --jsonreportssubscriptionType: maxon an account whose Claude window is already gone. - Reports also say Ultra accounts awaiting verification keep Claude's cap, and that Codex's limit differs between Plus and Pro.
- For Claude, presence tracked the limit in 3,497 usage samples from one account, taken 2026-08-20 to 2026-11-02. The window was reported in all 3,393 samples before the change, including 2,160 at 0% utilization, so an idle window is not omitted. It was absent from all 10 samples after the change.
five_hourand thesessionentry inlimitsagreed in every sample. The other 94 samples recorded no Claude data and say nothing either way. - For Codex, the live
account/rateLimits/readresponse on CLI 0.163.0 reports only the 10,080-minute window for the same account. - This recovers by itself: if a provider reports the window again, it comes back on the next refresh. That preserves the v0.1.4 lesson that a window's absence can be temporary.
| Window reported | Window not reported | |
|---|---|---|
| Full menu bar label | ✳ 45·70 |
✳ 70 |
| Compact menu bar label | ✳ 45 |
✳ 70 |
| Popover rows for Claude | 5-hour, Weekly, Fable | Weekly, Fable |
| Popover rows for Codex | 5-hour, Weekly | Weekly |
| 5-hour notifications | 80% and 95%, as today | None |
The label examples show Claude; Codex follows the same pattern with ⬡.
Existing behavior stays as it is:
- A failed refresh that keeps earlier values still keeps them, including the five-hour value.
- Codex windows are identified by duration, and expired ones are rejected, so a stale five-hour value in a rollout file does not bring the window back.
Usagekeeps its optional five-hour fields, and the parsers keep reading them.
Docs. Update the README.md description and feature list to say the five-hour window appears when the provider reports it, and add a CHANGELOG.md [Unreleased] entry.
Design Direction
This only removes UI, so it adds no new visual language. Keep the existing UsageWindowRow, glyphs, threshold colors, separators and 320pt popover width. When a window does not apply, leave it out entirely: no placeholder, explanatory text or empty row.
Acceptance Criteria
- For each provider, data with a five-hour value renders and notifies as in the table's first column.
- For each provider, data without a five-hour value renders as in the table's second column, in both label modes, with no five-hour notification.
- A successful refresh that no longer reports the window removes it from the label and popover, and a later refresh that reports it brings it back, without a restart.
- A provider with no usage values at all (unavailable or before the first refresh) shows a single
--and no 5-hour row. - A Codex five-hour window whose reset time has passed is not shown, and its value never appears as weekly.
- Credential handling is unchanged: no new Keychain reads, and no plan lookup through the CLI or the credential.
- A popover and label screenshot, or an explicit note if macOS permissions block capture, is attached to the PR for an account without the window.
Testing
- Verify:
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer make test→ passes. - Verify:
git grep -n "showsFiveHourUsage" -- InferenceMeter→ no output, because the per-provider setting is replaced by the shared rule. - Run the built app on an account without the window and check the label in both modes and the popover. Capture with macOS
screencapture; la-forge drives Chrome and does not apply to this native app. Cover the window-reported column with the existing fixtures, since a live account cannot show both states.
Existing label tests that expect a -- placeholder for an absent five-hour value encode the old behavior, so update them to the new requirement. InferenceMeterTests/Fixtures/claude-usage-absent-five-hour.json already covers Claude's absent shape.
Not in scope
- Plan or tier detection, for the reasons above.
- A setting to show or hide the window. The app can determine this from provider data.
- Removing the compact toggle. It still matters for accounts with both windows, even though it only changes spacing on accounts without one.
- Changing the provider parsers or the rollout scan. Their existing handling already supplies what this needs.
- Adding Fable to the menu bar.
- Rewriting historical research in
docs/spikes/andspikes/. - Cutting a release or changing the version.
Activity
[-]Show Claude's five-hour window only when reported and remove Codex's[/-][+]Show five-hour usage windows only when the provider reports them[/+]