Files
ai-agent/docs/usage-calibration.md
Gabriel Vidal da23d22519 feat(scripts): usage-calibration — fit /usage % against transcript spend
Lines the plan windows' official percentages (HA sensors from the homelab's
claude-usage-notifier) up against the account's archived token spend, priced
at list price, and fits dollars-per-1% for the 5h and week windows plus a
Fable multiplier. docs/usage-calibration.md records the method and the
2026-10 calibration (1% week ≈ $22, 1% 5h ≈ $5.6, Fable ×1.75, no separate
Fable bucket) and notes that pricing.py overstates the newest models.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:40:14 +02:00

84 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# What 1 % of a Claude plan window is worth
Claude Code's `/usage` shows how full the subscription's windows are (rolling
5 h, 7-day week), as whole percentages. The transcripts show what was spent, in
tokens. `scripts/usage-calibration.py` lines the two up and fits the exchange
rate, so a dollar figure on the dashboard can be read as "% of my week", and
the plan's ceiling can be expressed in tokens.
```bash
uv run scripts/usage-calibration.py # personal seat, last 9 days
uv run scripts/usage-calibration.py --since 2026-09-13 --json /tmp/cal.json
uv run scripts/usage-calibration.py --account work --prefix sensor.claude_work_usage
```
## Inputs
- **Usage %**: Home Assistant long-term statistics (hourly min/max) of the
sensors that the homelab's `claude-usage-notifier` pushes (`<prefix>_5h`,
`_week`, `_fable`). The script reads the recorder SQLite db read-only, so it
goes back to the sensors' creation, beyond the 10-day state history.
- **Tokens**: the account's conversations listed by `/api/conversations?account=`
(the backend resolves each conversation's account), parsed from the archive,
subagents included. Records are de-duplicated on (message id, request id) and
priced at **list price** (the script's own table; see "Pricing" below).
## Method
The data is binned by hour. A window's % only rises between resets, so each
bin's increase is the usage spent in it. Bins that contain a reset are dropped,
and so are 5 h bins above 100 % (overage). The fit is `Δ% = k·cost + c`, by
non-negative least squares. `c` soaks up usage the archive can't see
(claude.ai, the desktop app, a Mac that isn't paired as a worker). It came out
at ≈ 0 once both Macs were paired.
Unweighted list-price dollars leave a drift. Through a Fable-heavy week the
cumulative $/% climbed from $13.5 to $20 as the mix moved to Opus. A **Fable
multiplier** removes it. It is chosen by grid search on the combined R² of the
5 h and week fits, and with it the cumulative ratio stays flat at $21–23/%.
Other weightings were tested and lost: cache reads free, cache reads at 0.1×
input, cache reads at 1× input, Opus 5.5 priced as Opus 5, and raw token
counts.
Use 1 h bins. With 3 h bins most 5 h resets fall inside a bin, which then gets
dropped, and the 5 h fit collapses.
## Calibration — personal Max plan (€200/month), 2026-10-12
Window: 2026-10-04 18:00 → 2026-10-12 (Opus 5.5 / Fable 5.1 era), 1 h bins.
Intervals are 90 % CIs from a 300-draw day-block bootstrap.
| | API $ at list price | tokens at the real Opus 5.5 mix¹ |
|---|---|---|
| 1 % of the **5 h** window | **$5.6** [5.4–6.8] | ≈ 17 Mtok |
| 1 % of the **week** | **$22.1** [21.1–24.6] | ≈ 68 Mtok |
| Fable multiplier | **×1.75** [1.6–2.5]: 1 % week ≈ $13 of Fable 5.1 | ≈ 14 Mtok of Fable¹ |
| full 5 h window | ≈ $560 ≈ 25 % of a week | |
| full week | ≈ $2,200 | ≈ 6.8 Gtok |
| 100 % of every week for a month (×4.35) | ≈ $9,600 (≈ $5,700 if all Fable) | ≈ 30 Gtok |
¹ Agentic Claude Code traffic is 98 % cache reads by tokens. On Opus 5.5 they
are about 61 % of the dollars, cache writes 32 % and output 8 %. The same 1 % of
the week buys ≈ 1.1 M Opus 5.5 output tokens, or 5.5 M fresh input, or 110 M
cache reads.
- **No separate Fable bucket.** The `seven_day_<model>` key never appeared in
the status line's `rate_limits` from 2026-07-17 to 2026-10-12, despite heavy
Fable 5 and Fable 5.1 use. Fable draws on the same 5 h and week windows, about
1.75× faster per list-price dollar than Opus 5.5.
- **The week binds, not the 5 h window.** A full 5 h window is ≈ 25 % of the
week, and a week has 33.6 of them.
- **Earlier eras differ.** In Jul–Aug (Opus 4.8 / Opus 5 / Fable 5), unweighted
fits gave ≈ $30 per 1 % of the week. Limits and prices move with model
launches, so re-run the script after one.
## Pricing: the backend overstates current models
`backend/conversations/pricing.py` predates the latest price cuts. It prices
every Opus at $5/$25 with a flat 0.1× cache read, so Opus 5.5 ($4/$20, cache
read $0.20) comes out ≈ 2× too high. It prices Fable 5.1 cache reads at $1.00
(list $0.25), Sonnet 5/5.5 at $3/$15 (list $2/$10), and Haiku 5.5 at $1/$5 (list
$0.10/$0.50). Across 2026-09-13 → 10-12 the dashboard's personal total is ≈ 1.9×
list price. In the dashboard's own dollars, 1 % of the week ≈ $44.5 and 1 % of
5 h ≈ $11.2.