Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
# Changelog

## v0.41.0 — 2026-09-02 — a session wall is not a weekly wall

Claude Code 2.1.258 can offer `/low-priority` after the 5h session window
binds, letting that session continue against the weekly pool while requests
wait for spare capacity. The statusline used to render the wall as
`5h[101%]` and then pin a weekly-surplus notice, which made an interrupted
session look like an invitation to spend.

The badge now says `5h[cap@04:00]`, and a capped 5h notice outranks weekly
opportunity. `/low-priority` is named only when the current transcript's
`quotaLimits.lowPriorityOffer` proves Claude Code offered it for this exact
window; the local-command result distinguishes offered from active. Neither
statusline stdin nor `/api/oauth/usage` exposes the separate lower-priority
allowance, so no allowance percentage is guessed. A fresh sibling account
still outranks the bypass because it avoids the queue and preserves this
account's week.

The cache policy is explicit now too. A 5h cap is not a terminal account:
stdin continues to update 5h/7d on every render, while scoped and extra-usage
fields keep a finite two-minute API TTL. The outer spawn gate and the
lock-side cache recheck now share one function, with regression tests holding
100% to 120 seconds rather than to the reset.

491 bats.

## v0.40.0 — 2026-09-01 — what a cold cache costs

**The bar's extra color above 200k was a pricing claim, and the price is
Expand Down
16 changes: 16 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ What the readers know, beyond the badges:

```
fb capped ~Thu 07:00 the running model is gone until then
5h capped · /low-priority uses 7d
this session wall can be bypassed, and this session's
transcript proves Claude Code offered the mode
lower priority · 47% of 7d left
the bypass is active; the weekly pool is now the budget
5h caps ~05:18 this sitting hits the wall before its reset
7d dry ~Thu 09:00 the learned weekday forecast, not a straight line
7d rebased 53%→12% utilization fell INSIDE one window: a plan change or
Expand All @@ -181,6 +186,15 @@ fb ~22% expires the ACCOUNT caps first: at this week's mix the 7d pool
~62% will expire on pace to strand a large chunk of the subscription
```

At the 5h wall the badge says `5h[cap@04:00]`, never `100%` or `101%`:
the percentage has stopped being a reading and the reset is the useful fact.
`/low-priority` is never inferred from weekly headroom. Its eligibility is
gated per session and absent from both statusline stdin and `/api/oauth/usage`;
only a matching `quotaLimits.lowPriorityOffer` in this session's transcript
allows the notice to name it. The transcript's local-command result then
distinguishes offered from active. The separate lower-priority allowance is
not exposed there either, so this statusline does not manufacture one.

The budget line is the one sentence with three clauses, and each answers a
different question:

Expand Down Expand Up @@ -210,6 +224,8 @@ The API is asked for what the protocol does not hand us, and no more.
a monotone envelope: a dip is stale, never a refund.
- `/api/oauth/usage` (scoped weekly `fb`, extra usage): adaptive TTL by 5h
heat (300→30 s) with a 120 s floor whenever stdin already carries 5h/7d.
A capped 5h window never freezes this cache: lower-priority requests still
move 7d and scoped counters, so API-only fields keep the finite 120 s TTL.
- Profile: 24 h. Prepaid: 5 min. All caches shared per account under
`~/.claude/statusline/[accounts/<tag>/]` — one fetch serves every
session, container, and ccpace (`docs/api/state-dir.md`).
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ clauses about one window can never disagree.
| Notice | What it knows that line 1 doesn't |
|--------|-----------------------------------|
| `! fb capped ~Thu 07:00` | The weekly limit scoped to *this session's model* hit 100%: that model is gone until then. The long form names a model that still has room. |
| `! 5h capped · /low-priority uses 7d` | The shorter session window bound while the weekly pool still has room, and this session's transcript says Claude Code actually offered lower-priority mode. The statusline does not infer eligibility from headroom. |
| `+ lower priority · 47% of 7d left` | This session enabled the bypass. Requests may wait for spare capacity and now draw against the weekly pool; the lower-priority allowance itself is not exposed to statusline scripts, so no allowance percentage is guessed. |
| `! 5h caps ~05:18` | Linear projection off this window's own pace: you hit the wall before the reset. Long form adds how long you'd sit blocked. |
| `! 7d dry ~Thu 09:00 · hard stop` | The learned per-weekday burn profile (EWMA over your own history), not a straight line — your heavy Tuesday counts more than an average, and the learned hour-of-day shape puts the dry point where you are awake to act on it instead of at 03:00. Tail says what happens at 100%: extra billing, or a stop. |
| `! fb 91% vs 7d 55% · go op` | **The relation** between two badges: the *model* caps before the account does. Switching models buys the week's remaining capacity back; the roomiest other `weekly_scoped` limit in the payload gets named. |
Expand All @@ -412,6 +414,10 @@ clauses about one window can never disagree.
and `--week` print the long form, since a terminal command has a whole
line to spend.

At a spent session window, line 1 renders `5h[cap@04:00]` rather than
`5h[100%]` or the occasional API value `5h[101%]`. Once the window binds,
`cap` is the state and the reset is the number to plan around.

## The waste ledger

The advisor prevents waste prospectively; `report` proves it
Expand Down Expand Up @@ -524,6 +530,8 @@ shared dir -- `~/.claude/statusline/` -- and a single fetch serves all
concurrent sessions. Per-session prompt-cache-health state stays under
`~/.claude/statusline/sessions/`. Old `$SCRIPT_DIR` state is migrated on first
run. Setting only `CLAUDE_CACHE_DIR` keeps the legacy single-dir behavior.
At a 5h cap, stdin keeps 5h/7d live and API-only scoped/extra fields continue
on a two-minute TTL; the cache is never frozen to the session reset.

</details>

Expand Down
3 changes: 3 additions & 0 deletions docs/api/oauth-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ does that automatically (`curl_ca_bundle` in `statusline.sh`).
**`five_hour` / `seven_day`** — the two account-wide windows. `utilization`
is a float percentage; `resets_at` is ISO-8601 with microseconds and offset.
The `*_dollars` fields have only been observed `null` on subscription plans.
`five_hour.utilization` has been observed at `101.0` when the session window
binds; it is a server reading, not a bounded progress-bar value. Renderers in
this repository treat any value at or above 100 as `cap` and keep the reset.

**`limits[]`** — the newer, generic limit contract (this is what the
statusline parses first):
Expand Down
2 changes: 1 addition & 1 deletion docs/api/state-dir.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ The raw `/api/oauth/usage` response (see `oauth-usage.md`) plus one field:
| Field | Type | Meaning |
|-------|------|---------|
| `fetched_at` | int epoch s | When this fetch succeeded |
| `five_hour.utilization` | number 0–100 | 5h window used % |
| `five_hour.utilization` | number, 0+ | 5h window used %. The API has emitted 101 at the binding wall; consumers should treat >=100 as capped, not as extra precision. |
| `five_hour.resets_at` | ISO-8601 | 5h window end |
| `seven_day.*` | same | 7d window |
| `extra_usage.*` | object | overage spend (see oauth-usage.md) |
Expand Down
12 changes: 6 additions & 6 deletions llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
> health, and git activity in Claude Code's statusLine hook — plus a
> week row (this 5h window as five hour cells, the 7d period as its 5h
> windows with the future folded to a counted `...▯(✕28)` tail: where the
> points went), an advisor row that interprets the
> numbers (cap projections, expiring-surplus and underuse advice, fleet
> relief), and a `report` subcommand that ledgers what each closed window
> expired unused. 435 bats tests, deps are jq + curl, no daemon, no
> points went), a notice engine that pins the top condition and briefly
> explains the next (cap projections, expiring-surplus and underuse advice,
> fleet relief), and a `report` subcommand that ledgers what each closed
> window expired unused. 491 bats tests, deps are jq + curl, no daemon, no
> telemetry.

Key facts for agents:
- Everything lives in `statusline.sh` (~5300 lines, plain bash). Install
- Everything lives in `statusline.sh` (~6000 lines, plain bash). Install
copies it to `~/.claude/statusline.sh`, copies the usage-insight skill to
`~/.claude/skills/`, and wires `settings.json` (keeping any flags already
on the command). `install.sh` is the one installer for both entrypoints:
Expand Down Expand Up @@ -45,7 +45,7 @@ Key facts for agents:
- [statusline.sh](https://github.com/thevibeworks/claude-code-statusline/blob/main/statusline.sh): the entire product
- [install.sh](https://github.com/thevibeworks/claude-code-statusline/blob/main/install.sh): installer (curl | bash, or STATUSLINE_SRC=<checkout>)
- [Makefile](https://github.com/thevibeworks/claude-code-statusline/blob/main/Makefile): install / status / diff / uninstall / check
- [t/statusline.bats](https://github.com/thevibeworks/claude-code-statusline/blob/main/t/statusline.bats): 417 statusline tests
- [t/statusline.bats](https://github.com/thevibeworks/claude-code-statusline/blob/main/t/statusline.bats): 473 statusline tests
- [t/install.bats](https://github.com/thevibeworks/claude-code-statusline/blob/main/t/install.bats): 18 installer tests

## Optional
Expand Down
5 changes: 5 additions & 0 deletions skills/usage-insight/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ the deep-dive version of what the advisor row says in one sentence.
the useful fact is its `resets_at`, not the percentage.
- 5h pressure with a reset < 30min away is self-healing — say "resets
in N minutes" instead of alarming.
- A capped 5h window is the shorter session wall, not an exhausted week.
If the live statusline says `/low-priority` was offered or is active,
explain that it continues against the remaining 7d pool while requests
wait for spare capacity. The state dir alone cannot prove eligibility or
see the separate lower-priority allowance, so never invent either.
- Recommending another account: only name siblings whose cache is
fresh (< 1h); an idle-looking stale account is unknown, not free.

Expand Down
Loading
Loading