Skip to content

feat: show plan limits and spend in the sidebar - #1026

Merged
small-angel merged 3 commits into
mainfrom
clo/usage-strip
Nov 14, 2026
Merged

small-angel merged 3 commits into
mainfrom
clo/usage-strip

Conversation

@small-angel

@small-angel small-angel commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

The sidebar footer becomes one status strip: you, a ring per Claude Code or Codex plan that drains as its lowest window runs out, and the machine, which also shows when it is offline. The rings open a panel with each plan's windows (always shown as what's left), a Codex usage reset when the account holds one, the week's compute cost by backend, and a daily AI or compute spend graph. The composer's context ring becomes a menu with the compaction point, the chat's plan and, when billed per token, its cost.

The choices that are expensive to undo:

  • Limits come from the agents themselves: Claude Code's get_usage control request on a throwaway child, Codex's account/rateLimits/read through the chat's running app-server when there is one. orx never reads their tokens. Claude has no public way to use its resets, so only Codex's are offered.
  • One new line leaves the machine: models.dev's public price list, fetched once a day to price agents that report only tokens (Codex, Cursor). It's in arc/storage.md, and costs never go to telemetry.
  • The store grows nullable cost_micros, cost_currency and recorded_at on chat_usage_samples, and price_json on runs: the price a backend quoted when the run launched, never rewritten. Contract fixtures cover both directions.
  • New endpoints: GET /api/usage, and POST /api/usage/refresh and /api/usage/reset behind the Origin guard.

It adds about 7,000 lines: roughly 3,000 are tests and 700 are strings across the 11 catalogs. Two size reviews (Opus and GPT-6.1 Sol) found it about right, and their cuts are in.

Tested on macOS against the dev server in WebKit and Chromium, and in the desktop window: real Codex on ChatGPT Pro (plan, and its one reset credit read but never spent) and Claude Code on an API key (chat cost). Not tested: a Claude subscription, agent profiles, a priced compute run, spending a reset, and the Windows and Linux windows.

Closes #807.

Proof: the full Rust, UI and e2e suites on this diff, and the running app in WebKit and Chromium against this machine's real Codex plan and agent costs (screenshots below).

Before After, light After, dark
Footer before Strip, light Strip, dark
Usage panel Using a Codex reset
Usage panel Reset dialog
Composer, Claude Code on an API key Composer, Codex on ChatGPT Pro
Composer menu, Claude Code Composer menu, Codex

Reviewed with sol-loop: 3 rounds with GPT-6.1 Sol on high. Sol verdict: approved

Assisted-by: claude-opus-5.5

The sidebar footer becomes one status strip: you, a ring per agent plan
draining as its lowest window runs out, and the machine, which also shows
when it is offline. The rings open a panel with each plan's windows, the
week's compute cost by backend, and a daily graph of agent or compute
spend. The composer's context ring becomes a menu with the compaction
point, the chat's plan and its cost. A Codex plan holding a usage reset
offers to use it, after a confirmation that shows what is left.

Plan limits come from the agents themselves (Claude Code's get_usage,
Codex's account/rateLimits/read) and are always shown as what is left.
Agent cost is what each agent reports, or models.dev's price for agents
that report only tokens, fetched once a day. Compute cost uses the price
each backend quoted when the run launched. Nothing is a hardcoded price,
and costs stay on the machine.

Closes #807.

Assisted-by: claude-opus-5.5
@greptile-apps

greptile-apps Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes reach local plan reads, account usage, and dashboard spend views.

Fix the missing finished-job costs and required read-error display before merging.

Findings

  1. P1 Finished jobs disappear from spend ▶
  2. P2 Plan balances stop updating ▶
  3. P2 Account requests race chat startup ▶
  4. P2 Usage read errors disappear ▶
Fix with agent prompt
### Issue 1
src/local/spend.rs:149-151
A paid job can finish between provider checks without ever being observed as running. That leaves `started_at` empty, so `running_time` drops it from the weekly totals. `chat_compute` still counts the run but adds neither cost nor an unpriced warning.

Keep finished jobs with an unknown start visible as unpriced, or recover their running time before totaling them.

### Issue 2
ui/src/queries/settings.ts:206-210
`staleTime` does not schedule another read. After the first report, an idle sidebar can keep showing the same limits and spend indefinitely. `observed` also drops limit changes received within the fresh minute without scheduling a later read.

Add a bounded refresh while the sidebar is visible, or schedule a read when a limit change is deferred.

### Issue 3
src/local/codex.rs:1049-1055
`live_client` can return a child before its startup handshake finishes. `ensure_with_spawn` puts the child in `inner` before calling `handshake`, and `account_request` immediately writes through the returned client. Unlike `reusable_client`, this lookup does not hold `spawn_lock`.

Wait for startup to finish before returning the child. Otherwise, usage reads and resets can send account requests before `initialize` completes, risking a rejected request.

### Issue 4
ui/src/components/StatusStrip.tsx:24-26
If the first `/api/usage` request fails, `report` is empty and the usage segment disappears. The user sees the same result as a machine with no usage, with no error or retry.

This violates the repository requirements “Unknown is not absent” and “Every failure reaches someone who can act on it.” Show the read error and a retry action before merging. Keep the existing quiet fallback for an older server’s 404.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Adds plan limits and spend to the sidebar and chat composer.

  • The sidebar shows plan limits beside the selected machine.
  • The usage panel adds prices for agent tokens and compute runs.
  • The composer’s context ring opens a menu with chat details.

Completed paid jobs can be omitted from spend when their start was never observed. The review also found missing refresh scheduling, a Codex startup race, and hidden first-read errors.

Checks were source-based; no runtime tests or visual checks were performed.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Agents[Claude Code and Codex] --> Plans[Cached plan limits]
  Samples[Chat usage samples] --> Costs[Stored chat costs]
  Backends[Compute backends] --> Quotes[Stored launch prices]
  Quotes --> Spend[Running-time estimates]
  Plans --> API[Usage API]
  Costs --> API
  Spend --> API
  API --> Sidebar[Sidebar status strip]
  API --> Composer[Chat usage menu]
  Sidebar --> Confirm[Confirm Codex reset]
  Confirm --> Agents
Loading

Reviews (1) · Last reviewed commit: "feat: show plan limits and spend in the ..." · Reviewed by Greptile

Comment thread src/local/spend.rs Resolved
Comment thread ui/src/queries/settings.ts Resolved
Comment thread src/local/codex.rs Resolved
Comment thread ui/src/components/StatusStrip.tsx Resolved
A paid job first seen after it finished counts as unpriced instead of
vanishing from spend, and a backend with priced and unpriced runs says
so beside its total. Limits a running chat reports within a minute of
the last read wait for that snapshot to go stale instead of being
dropped, also when a read finishes while they wait. The strip reads
usage again every five minutes while visible; a usage read never
reaches a Codex app-server before its handshake; and a failed read
keeps the segment, dimmed, with the last values, the error and Try
again, instead of hiding it or showing stale numbers as current.

Assisted-by: claude-opus-5.5
@small-angel
small-angel merged commit 9fb7fcb into main Nov 14, 2026
27 checks passed
@small-angel
small-angel deleted the clo/usage-strip branch November 14, 2026 02:15
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.

Add widget visualising model usage

1 participant