What it detects
Offline, stdlib-only Python CLI for token and cost accounting of AI agent runs, computed from transcripts and usage logs you already have.
Honesty note. runledger counts what your logs report. It cannot see your provider's bill, cannot verify billing, and does not know about discounts, batch pricing, tiers, minimums, taxes, or price changes. Every dollar figure is an estimate from a price table *you* control. The shipped
prices.jsonis an EXAMPLE only - prices change and those numbers are not authoritative. Models missing from the table are reported as unpriced, never guessed.
Rules
This tool does not publish a numbered rules table; see the README for what it flags.
Usage
python3 runledger.py examples/ # table report for a directory
python3 runledger.py run.jsonl --json > report.json # machine-readable
python3 runledger.py logs/ --csv > turns.csv # one row per turn
python3 runledger.py logs/ --csv --csv-group tool # one row per tool
cat run.jsonl | python3 runledger.py - --top 10 # stdin
python3 runledger.py logs/ --budget 5.00 # exit 1 if estimate > $5
python3 runledger.py logs/ --prices my_prices.json # your own price table
python3 runledger.py logs/ --no-prices # tokens onlyAfter pip install of the kit, the same options work as agentsec runledger …. Every tool also accepts --help and almost every tool accepts --json.
Example output
Real run on the bundled fake logs (python3 runledger.py examples):
* marks totals that exclude unpriced turns. With --budget 0.05 --top 3 the exit code is 1 and stderr says:
--csv --csv-group model:
runledger 0.1.0 - token & cost ESTIMATES from logs (not a bill)
Turns: 11 Input: 18,812 Cache read: 23,528 Cache write: 8,000 Output: 3,795 (reasoning 896)
Total tokens: 54,135 Cache hit ratio: 46.7% Estimated cost: $0.0758*
* 1 turn(s) unpriced (models not in price table: mystery-model-x) - excluded from cost
By run:
run turns input cache_rd cache_wr output total cache% cost
------------------- ----- ----- -------- -------- ------ ------ ------ --------
anthropic_run.jsonl 4 9,150 16,000 8,000 770 33,920 48.3 $0.0590
run-oa-2 2 1,924 5,376 0 1,300 8,600 73.6 $0.0108
run-oa-1 2 1,338 1,152 0 75 2,565 46.3 $0.0055
tr-local-1 3 6,400 1,000 0 1,650 9,050 13.5 $0.0005*
By model:
model turns input cache_rd cache_wr output total cache% cost
------------------------- ----- ----- -------- -------- ------ ------ ------ --------
claude-sonnet-4-20250514 3 3,950 16,000 8,000 460 28,410 57.2 $0.0536
o3-mini 2 1,924 5,376 0 1,300 8,600 73.6 $0.0108
gpt-4o 2 1,338 1,152 0 75 2,565 46.3 $0.0055
claude-3-5-haiku-20241022 1 5,200 0 0 310 5,510 0.0 $0.0054
gpt-4o-mini 1 1,500 1,000 0 300 2,800 40.0 $0.0005
mystery-model-x 1 4,000 0 0 1,200 5,200 0.0 unpriced
example-local-7b 1 900 0 0 150 1,050 0.0 $0.0000
By tool:
tool turns input cache_rd cache_wr output total cache% cost
----------- ----- ----- -------- -------- ------ ------ ------ --------
bash 1 2,100 0 8,000 120 10,220 0.0 $0.0381
read_file 2 1,850 16,000 0 340 18,190 89.6 $0.0155
search_docs 2 1,924 5,376 0 1,300 8,600 73.6 $0.0108
get_weather 2 1,338 1,152 0 75 2,565 46.3 $0.0055
fetch_url 1 5,200 0 0 310 5,510 0.0 $0.0054
(none) 1 1,500 1,000 0 300 2,800 40.0 $0.0005
coder 1 4,000 0 0 1,200 5,200 0.0 unpriced
planner 1 900 0 0 150 1,050 0.0 $0.0000
By session:
session turns input cache_rd cache_wr output total cache% cost
---------- ----- ----- -------- -------- ------ ------ ------ --------
sess-gamma 3 3,950 16,000 8,000 460 28,410 57.2 $0.0536
sess-beta 2 1,924 5,376 0 1,300 8,600 73.6 $0.0108
sess-alpha 2 1,338 1,152 0 75 2,565 46.3 $0.0055
sess-delta 1 5,200 0 0 310 5,510 0.0 $0.0054
tr-local-1 3 6,400 1,000 0 1,650 9,050 13.5 $0.0005*
Top 5 most expensive turns:
turn model tool tokens cost
--------------------- ------------------------- ----------- ------ -------
anthropic_run.jsonl:1 claude-sonnet-4-20250514 bash 10,220 $0.0381
anthropic_run.jsonl:3 claude-sonnet-4-20250514 read_file 9,760 $0.0108
openai_run.jsonl:3 o3-mini search_docs 4,300 $0.0066
anthropic_run.jsonl:4 claude-3-5-haiku-20241022 fetch_url 5,510 $0.0054
anthropic_run.jsonl:2 claude-sonnet-4-20250514 read_file 8,430 $0.0046
SARIF and CI
agentsec runledger path/to/input --json > runledger.json
# runledger does not yet emit SARIF; use --json and keep --fail-on for CI.
# GitHub Actions (composite action ships with the repo)
- uses: dunkleschitz/agentsec@v0
with:
tools: runledger
paths: path/to/input
fail-on: high
--sarif is not available on this tool yet (resultguard and toolpoison are reserved as good first issues). Use --json and a --fail-on exit gate instead.
OWASP mapping
Heuristic mapping of what this tool helps a reviewer look for. Not an official OWASP endorsement, and not complete coverage of any item. Sources: OWASP Top 10 for LLM Applications 2025 and OWASP Top 10 for Agentic Applications 2026.
- LLM10 Unbounded Consumption — OWASP LLM Top 10 (2025)
Known limits
Heuristic scanner, not a security boundary. A clean result does not mean something is safe. All example secrets in this repository are fake.
Full source, tests, and fixtures: tools/runledger/ in the repository. Install the kit with pip install git+https://github.com/dunkleschitz/agentsec.git.