The cost layer for AI-assisted development. Reads local Codex, Claude Code, Cursor, and Aider logs and prints what each PR cost. Offline. No login.
Project description
Caliper
The cost layer for AI-assisted development.
Reads local Codex, Claude Code, Cursor, and Aider logs. Prints what each PR cost. Offline. No login.
uvx --from caliper-ai caliper
About Caliper
Caliper is a small, local-first Python CLI that turns AI coding session logs into one usage record and prints what each pull request cost.
It supports four sources today: OpenAI Codex CLI, Claude Code, Cursor, and Aider. It reads files those tools already write to your disk, joins them into one frozen event shape, prices them with sourced rate cards, and attributes the cost to a PR, a commit, or a project.
There is no daemon, no SDK, no account, and no telemetry. The default code path makes zero network calls. The only network call in the whole codebase is an opt-in pricing refresh behind a flag.
Caliper is MIT-licensed and built by one developer who wanted to know which PRs spent the four-figure bill.
The problem
You ran Codex, Claude Code, Cursor, or Aider this month. A bill arrived. You cannot point at one pull request and say what it cost.
The vendor dashboards each speak their own dialect, sit behind a login, and stop at the model boundary. None of them know which commits, which PRs, or which projects spent the money.
Caliper reads the logs those tools already write to your disk, joins them into one event shape, and answers the only question that matters in a budget review: what did this PR cost.
The 30-second proof
On the machine that wrote this README, three commands.
caliper overview
Caliper - Overview
Vendors: claude-code (74,590 events) · openai-codex (20,500 events)
Last 7 days 48,727 credits $3,383
Last 30 days 52,691 credits $10,516
Last 90 days 52,691 credits $10,897
Events: 95,090
Cache savings: $65,871 at 99.3% cache hit
caliper insights
High cache reuse: 99.3% of input tokens served from cache,
saving about $63,415. Keep prompts and file context stable
to preserve cache hits.
caliper project --lookback-days 30
SlidesDockerTemp 4 models 18,746 credits $3,009
ace-ai 4 models 15,603 credits $1,160
caliper 3 models 9,219 credits $443
Real numbers, one machine, one developer, ninety days. No account. No upload. The first run took eleven seconds on a cold cache. Later runs are under a second.
Who this is for
- Indie developers paying their own AI bill. You see the credit card charge. You want the line items.
- Engineering managers running AI-heavy teams. You want a number per PR that survives a budget meeting.
- Anyone under a strict data policy. Logs stay on disk. The parser is open and small enough to read end to end.
Who this is not for
- Teams that want a hosted dashboard with sign-in. There are products for that. Caliper is not one.
- Teams that have not adopted Codex, Claude Code, Cursor, or Aider. There is nothing on disk to read.
If you want this to also speak to GitHub Copilot or to a hosted SaaS, open an issue. The wedge stays local-first.
What a PR receipt looks like
caliper pr 42
Caliper - PR #42
128 events 432,118 tokens $4.82 · 7 commits
Vendor Model Events Tokens (in/out) Cached API $
openai-codex gpt-5.4 standard 74 210,000 / 31,000 61% $2.10
claude-code claude-sonnet-4.6 31 88,000 / 12,000 48% $1.12
cursor composer 23 72,118 / 19,000 22% $1.60
caliper pr <N> resolves the PR commits and filters local events whose
recorded git SHA matches those commits. If the PR cannot be resolved
automatically, pass an explicit range:
caliper pr --git-range main...feature-branch
The same shape is available per commit (caliper commit <sha>) and per
project (caliper project).
How it works, in one breath
- Caliper reads JSONL session logs from
~/.codex/sessions,~/.claude/projects, the local Cursor store, and Aider chat history. - It joins them into one frozen event shape: vendor, model, service tier, project, session, timestamp, token counts, cache counts, pricing source, git SHA where present.
- It groups, prices, and prints. The pricing catalog ships embedded and can be refreshed from public sources behind an explicit flag.
There is no daemon, no agent, no SDK. The default code path makes zero network calls.
Install
Requires Python 3.11+. Pick one.
uvx --from caliper-ai caliper # zero-install, recommended
uv tool install caliper-ai # persistent install
pipx install caliper-ai
python -m pip install caliper-ai
The PyPI distribution is caliper-ai. The command and Python package are
both caliper.
First sixty seconds
caliper # rolling 7 / 30 / 90 summary
caliper doctor # verifies your local setup
caliper daily --lookback-days 7 # daily rollup
caliper project --lookback-days 30 # which projects cost what
caliper insights # cache and tier signals
The first run parses everything and writes a sidecar cache. Later runs reuse
it. Pass --disable-parse-cache when you want to bypass the cache.
Privacy is a constraint, not a feature
- No login, ever.
- No upload, ever.
- No telemetry, ever.
- Prompts and titles are redacted in default output. Pass
--show-promptsif you want them. JSON output never leaks session titles when redaction is on. It falls back to session IDs. - The only network call in the codebase is the opt-in pricing refresh,
gated by
--allow-network. The privacy invariant is tested.
If you do not trust the claim, read src/caliper/parser.py and
src/caliper/parse_cache.py. They are short on purpose.
Pricing is explicit
- Money is computed in
Decimal. - Cached input, cache creation, output, and reasoning tokens are tracked separately when the source exposes them.
- Long-context multipliers are applied per model.
- Unknown or partial pricing is surfaced as a warning, never silently guessed.
- The embedded rate card carries a
checkeddate.caliper doctorwarns past 30 days and fails past 90.
caliper rates show
caliper rates catalog
caliper rates refresh --allow-network
Use a pinned rate card when you need to match an invoice exactly:
caliper daily --rate-card-file ./rates.json
Budgets in CI
Caliper exits with stable codes so CI can gate on cost.
# .caliper.toml
[budgets]
daily_credits = 25000
weekly_credits = 100000
monthly_api_dollars = 500
caliper budgets check
| Exit | Meaning |
|---|---|
0 |
ok |
1 |
warning threshold crossed |
2 |
breach threshold crossed |
Add the command to your CI step. The exit code is the contract.
Exports
caliper export receipt --receipt-month 2026-05 --receipt-format html
caliper export prometheus --metrics-port 9090
caliper export grafana
Receipts render as Markdown or HTML and are suitable for finance handoff.
The Prometheus exporter is a local process. The Grafana exporter prints a
dashboard JSON. The optional [prom] extra brings prometheus-client in.
Python library
from caliper.parser import load_usage
from caliper.config import build_options
from caliper.aggregation import aggregate_total
options = build_options(days=7)
result = load_usage(options)
total = aggregate_total(result, options)
print(total.totals.total_tokens)
The public import path is caliper. The dataclasses are frozen.
Configuration
caliper init # writes a commented .caliper.toml
Environment overrides:
CALIPER_CACHE_DIR: parse-cache location.CALIPER_DATA_DIR: pricing-catalog location.CODEX_HOME: Codex CLI data location.CLAUDE_CONFIG_DIR: Claude Code data location.
FAQ
Does it work with Cursor today?
Yes, for session files. Some Cursor files do not carry per-event token
counts. caliper doctor flags those and the event still appears in
session-level rollups.
Why not just read the vendor dashboards? Because the dashboards are per-vendor and per-account. They do not know which commit, which PR, or which project spent the money. They also require a login, which is the wrong fit for offline-only workflows.
How accurate are the costs?
As accurate as the rate card. The rate card ships embedded with a
checked date and warns when it ages. You can pin a local rate card to
match an invoice exactly.
What about the Anthropic admin API or the OpenAI usage API? Out of scope on purpose. Caliper is local-only. The trade-off is named: you get nothing if the vendor never wrote a log to disk.
Can I self-host the export? Yes. The Prometheus and Grafana exporters are local processes. The HTML receipt is a file you can email yourself.
Is there a hosted version? No. There is no hosted version on the roadmap. If your team needs a hosted dashboard, Caliper is the wrong tool. The wedge stays local.
Development
uv sync --all-extras --dev
uv run ruff check .
uv run ruff format --check .
uv run pytest
uv run pytest --cov=src/caliper --cov-report=term
Build and inspect the package:
rm -rf dist
uv run python -m build
uvx twine check dist/*
See CONTRIBUTING.md for the contribution surface (rate-card updates, new vendor parsers, schema changes).
Who built this
I am Rajdeep Mondal. I built Caliper because I had a four-figure AI coding bill, a clear hunch about which projects caused it, and no offline way to prove it. The first version paid for itself in one PR review.
If Caliper saves you a meeting, a fight, or a renewal, that is the intended outcome.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file caliper_ai-0.0.2.tar.gz.
File metadata
- Download URL: caliper_ai-0.0.2.tar.gz
- Upload date:
- Size: 105.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da8eac10a711be93bff6debc743f3f6c85bdafaae8d90ec289777423ec54f00a
|
|
| MD5 |
f6c18ee4aee5c0cdbc029a34a7b07e35
|
|
| BLAKE2b-256 |
d473d87416fe9e39f8208aacd0b355d75c9a68c01f5c910315bdc0e4bc8e78f0
|
File details
Details for the file caliper_ai-0.0.2-py3-none-any.whl.
File metadata
- Download URL: caliper_ai-0.0.2-py3-none-any.whl
- Upload date:
- Size: 126.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd2338b797b041bb66f421a1398d2b148c168da991e4d8a3bae6dd3f4909cf29
|
|
| MD5 |
31f4571eaf8d62a121a4155f85751227
|
|
| BLAKE2b-256 |
f8162c75a892dd532141bf43993ea83195d48ef76509a1f3fbb3e8f007a589bc
|