Skip to content
SkilledDragonEngineering Intelligence
MinilabKeylessOctober 13, 2026 · re-run October 14, 2026

cc-switch's usage rules, ported: one decision counted 50,783 tokens, 48,719 cached

We ported cc-switch's Claude Code session-usage rules to a keyless Bun CLI. 12 of 12 tests pass on upstream's fixtures, and one fixture decision counts 50,783 tokens, 48,719 of them cache reads.

By David Discua

Measured in the lab

4
decisions counted
1
lines skipped
12
bun tests passed
claude-opus-4-81 decision50,783
claude-opus-4-62 decisions15752.5
claude-sonnet-4-51 decision180
  • 12 of 12 bun tests pass, typecheck passes
  • dedup by message.id keeps the line with stop_reason
  • billable line without stop_reason still counts
  • upstream frontend and backend CI pass at the pin

From reports/burn.json · run on October 14, 2026. pin 479964f2; upstream session_usage.rs fixture lines only; Bun 1.4.3; no prices hard-coded; CI run 38506104110

How it is wired

readby modelSession logsJSONL, localburn-ledgercc-switch rulesYoutokens per decision

01/03Claude Code writes a session log for every run.

cc-switch is a desktop app for managing Claude Code, Codex and other coding agents, and its Rust backend has a file, session_usage.rs, that reads Claude Code's JSONL session logs and decides which assistant lines count toward usage. We ported those rules into a keyless Bun CLI called burn-ledger, ran it on upstream's own test lines, and ran upstream's frontend and backend CI at a fixed pin. On the fixture, one claude-opus-4-8 decision counted 50,783 tokens, and 48,719 of them were cache reads.

The catch

tokens_per_decision adds input, output, cache read and cache creation into one number. Your provider prices those four buckets differently, so a big count dominated by cache reads can cost less than a smaller count of fresh output. The ledger hard-codes no prices. Pass --prices prices.json (USD per 1M tokens) to get a column in your own prices.

The fixture is small and synthetic. It is two files built from the test lines in upstream's session_usage.rs, so the per-model numbers describe those lines and nothing about your workload. The accounting rules are what carry over to your logs. The same message.id can appear more than once in a session log. In the fixture, msg_1 appears with 26 output tokens and again with 1,349 and a stop_reason, and the ledger keeps only the second. A line with real usage and no stop_reason still counts, which matches upstream's test_sync_imports_billable_message_without_stop_reason. Malformed lines and all-zero placeholders are skipped and counted.

What we ran (keyless)

export DISABLE_TELEMETRY=1 DO_NOT_TRACK=1
bun install --frozen-lockfile
bun run typecheck
bun test
bun run ledger ./sample-logs
bash scripts/upstream-cc-switch-frontend.sh
bash scripts/upstream-cc-switch-backend.sh

The two upstream scripts copy commands from upstream's .github/workflows/ci.yml at the pin. The backend one needs Rust 1.95 and webkit2gtk, so it runs on ubuntu-22.04 in GitHub Actions.

From reports/burn.json, run on October 14, 2026 (2 files scanned, 4 decisions, 1 line skipped):

ModelDecisionsInputOutputCache readCache creationTokens per decision
claude-opus-4-6261,49910,00020,00015,752.5
claude-opus-4-812148,7192,06150,783
claude-sonnet-4-51102010050180

Bun 1.4.3 ran 12 tests with 0 failures and the typecheck passed. In CI run 38506104110, all four jobs succeeded: lab in 11 s, upstream-frontend in 295 s, upstream-backend in 682 s, and security.

How it is wired

burn-ledger reads a folder of Claude Code session logs you copy to your machine and prints usage per model and per session. It rejects paths that escape the folder through symlinks. It works offline on the logs you pass and ships no proxy or account-pooling configuration. The lab skill measure-decision-burn tells the agent to run the ledger before anyone swaps a model or a route.

Minilab (open source)

Upstream is farion1231/cc-switch: 144,256 stars, MIT, Rust, as of October 14, 2026. Copy one of your own session-log folders to ./sample-logs (it is gitignored), run bun run ledger ./sample-logs, and read tokens_per_decision for the models you use.

Run it yourself

SkilledDragonCorp/minilab-cc-switch-burn-ledger

Clone, install and run the report with no API keys. The numbers above are what that run writes.

bun install --frozen-lockfile && bun run typecheck && bun test

SkilledDragon is not affiliated with cc-switch or its authors. Numbers are from our own keyless lab run; re-run the report before relying on them. Marks belong to their owners.

All labs