Spend · Metered spend
Metered spend
What it is
Metered spend answers a plain question: across Anthropic, OpenAI, Bedrock, Azure, OpenRouter, and Cloudflare, what has your AI usage cost? It reads the numbers RepoOps can already see and lays them out in one ledger, with each number honest about how exact it can be and which providers it has no data for.
It is a spend display, not a spend audit. Billing Guard recomputes what each day should have cost from your own telemetry, joins that against the provider's bill, and flags the difference as findings. Its output is an accusation with evidence. Metered spend flags nothing: its output is a ledger, not a verdict. The two are different jobs, so they are separate surfaces. This page deep-links to Billing Guard for the reconciliation view of the same providers, and to App LLM calls for the app-side call detail.
Where to find it
- Desktop:
http://localhost:4000/, then Spend → Metered spend in the sidebar. - Hosted: desktop-only. The repoops.ai sidebar carries an “On the desktop app” pointer for it.
- Keyboard: ⌘ K, then type “Metered spend”.
- API:
GET /api/metered-ledger?from=YYYY-MM-DD&to=YYYY-MM-DD&repos=<ids>(window defaults to the trailing 30 days; both lenses cover the same span).
Two lenses, never summed
The ledger shows two totals side by side and never adds them into one number, because they measure different things at different scopes:
- Provider-reported (authoritative, org scope).The bill each connected provider charged the whole organization, pulled from that provider's own Admin or Cost API. This is the number your finance team sees on the invoice.
- Locally-captured (attributed, local scope). Only the calls this RepoOps install actually saw, summed from its own
ai-callsrows through the same cost rule the App LLM calls and Telemetry tabs use, so the numbers agree across tabs.
Adding them would be wrong: the reported lens is org-wide while the captured lens is a single install, so one is not a subset of the other. Read them as two independent views of the same spend, not as parts of a total.
Precision bands
Not every provider exposes cost at the same granularity, so each line carries a band saying how exact its number can be. The band is text, never color alone:
- Per-token (Anthropic, OpenAI). Exact, priced from real per-model token counts against a versioned rate card.
- Day-level (Bedrock, Azure). A day-level dollar bucket. Their cost APIs return a daily total with no per-model token counts, so the number is a day bucket, not a per-model figure.
- Per-call (OpenRouter). Forward-capture only. There is no historical cost API to backfill from, so the number covers calls captured going forward, not past usage.
How to light up each lens
The reported lensfills once you set each provider's Admin or Cost key in the aggregator's environment, the same keys Billing Guard uses:
ANTHROPIC_ADMIN_KEYfor the Anthropic Usage and Cost report.OPENAI_ADMIN_KEYfor the OpenAI Costs API.AWS_*credentials for the Bedrock day-level cost pull.AZURE_*credentials for the Azure OpenAI day-level cost pull.
The captured lensfills on its own, with no keys, from RepoOps' own BYOK Anthropic calls (its chat, analyze, diary, dream, and graph passes, each recorded with its real cost when the call returns usage) and from OpenRouter embeddings, captured with the gateway's authoritative per-call cost when the response returns one. When OpenRouter does not return a cost, RepoOps falls back to a rate-card estimate from the response's token counts and marks that row estimated, so an estimate is never passed off as the gateway's authoritative figure. If a model is not in the rate card, nothing is written: RepoOps never fabricates a number.
Honest limits
- Unconfigured providers read "not connected," never $0. A provider with no key is a blank, not a zero. A null reported cost is never rendered as $0.00.
- Low volume reads near-zero. On a fresh install or a quiet window the captured lens sits near zero until traffic accrues. That is the honest state, not a bug.
- Bedrock and Azure are day-level only. Their cost APIs carry no per-model token counts, so their lines are day buckets, not per-model figures.
- OpenRouter is forward-only. With no historical cost API, its captured spend starts from when capture turned on, not from past usage.
- Cloudflare AI Gateway has no live capture path on this install yet. It appears in the provider list so its absence is visible, not hidden.
Read more
- Billing Guard: reconcile telemetry against the provider's bill and flag mismatches.
- App LLM calls: the app-side, per-call LLM telemetry detail.
- Telemetry: combined-mode Claude Code telemetry across every tracked repo.