Cost & usage
How cost is computed#
Two sources, one rule: use the vendor's number when it exists, derive it when it does not, and say which happened.
Derived at ingest, once#
When a runtime records tokens but not dollars, ClawMetry derives cost from the token split and the model, using a multi-provider pricing table covering Anthropic, OpenAI, Google, xAI, OpenRouter and others.
The derivation happens at ingest, not at read time. That is deliberate: if cost were computed on read, updating the pricing table would silently rewrite your history, and last month's report would change every time a provider changed a price.
Cache-aware#
This is where most cost tooling goes wrong. A cached prompt read is priced very differently from a fresh input token — often by an order of magnitude — and a naive reconstruction that counts all input tokens at the input rate can overstate by several times.
ClawMetry accounts for four buckets separately:
| Bucket | What it is |
|---|---|
| Input | Fresh input tokens |
| Cache write | Tokens written into the prompt cache |
| Cache read | Tokens served from the cache |
| Output | Generated tokens, including reasoning where the runtime reports them merged |
If another tool disagrees
Check whether it is accounting for cache reads separately. A tool that reconstructs cost from transcripts without a cache split will report a much larger number, and the difference is not a rounding error.
Vendor dollars win#
Where a runtime records real dollars, those are used and the session is marked
exact:
| Runtime | Source |
|---|---|
| Cline | metadata.usage.totalCost |
| opencode | session.cost, per session and per message |
| Pi | A per-turn cost object |
| Copilot | The credit ledger — total_nano_aiu, where one credit is one cent |
| Exo | usage.cost_usd, computed by Exo at call time |
| Goose | accumulated_cost, for paid providers |
| Devin | Committed ACU and credit cost per message |
Copilot's is the most interesting: because it bills in AI credits and the ledger records them exactly, that cost is vendor-billed truth rather than any kind of estimate.
The honesty states#
Every session carries one:
| Status | Meaning |
|---|---|
exact | Vendor dollars, or every call priceable |
estimated | Derived, with a caveat worth knowing — see Kimi below |
partial | Some calls priced, some not |
tokens_only | Real tokens, no priceable model |
unavailable | Neither on disk. Shown as unknown, never as $0.00 |
$0.00 and unknown are different facts. A local Ollama run genuinely costs
zero and opencode records that honestly. PicoClaw simply records nothing, and
treating that as zero would quietly understate a fleet.
The estimated caveat#
Kimi is the clearest example. It persists a complete token breakdown but never the model id — no wire record carries one. The model is resolved from the share directory's current configuration, which is the model configured now, not necessarily the one that historical session ran on.
So those sessions are marked estimated with modelSource: "config". A
sub-agent that recorded its own effective model is marked log instead. Where
no pricing match exists at all, cost is unknown rather than a fabricated zero.
Per-runtime availability#
The full table is in What each runtime exposes. The short version:
- Most runtimes write a real token split. Cost is derived.
- Seven write real dollars. Those are used directly.
- PicoClaw writes neither. Cursor writes neither locally, and gets tokens only
from a hosted VM's loopback usage log.
Hosted VM usage#
On a managed agent VM, a loopback LLM shim writes one line per model call — timestamp, model, token split, an opaque session reference, numbers only, never content. For runtimes whose own stores carry no tokens, this is the only cost source.
It is deliberately restricted to a token-blind allowlist: Cursor and PicoClaw. Self-reporting runtimes are structurally excluded even when the provisioner exports the environment fleet-wide, because ingesting both would double-count every session.
One definition of a window#
"This week's cost" has exactly one definition, applied everywhere. The number on
Home, the number on Cost, the number in clawmetry status and the number an
agent gets from get_cost_summary are the same query against the same rollups.
If they ever disagreed, that would be a bug, not a subtlety about which window each page happened to use.
Reading it#
# per-day totals
curl -s localhost:8900/api/local/aggregates | jq '.rows[-14:]'
# per model per day
curl -s 'localhost:8900/api/local/models?since=2026-08-01' | jq '.rows'
# per runtime per day
curl -s localhost:8900/api/local/runtimes | jq '.rows'
# per session, with status
curl -s 'localhost:8900/api/local/sessions?limit=50' \
| jq '.rows[] | {session_id, cost_usd, cost_status, model}'