AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻译准备中
Choose a Claude Code transcript and see how many input tokens each CLAUDE.md, rule, skill, memory and tool result cost, counted from the API usage the transcript records, next to the usual characters
翻译准备中
开发工具Python · HTMLGitHub @peterwkdev-creator在线运营者未确认
试用过了吗? 点一下就好,无需登录。
How much each source (CLAUDE.md, rules, skills, memory, tool results) costs in the context of a Claude Code session, counted from the API usage in its transcript. Also a context budget for CI, and the git version of each file a session loaded.
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
How much each source (your CLAUDE.md, rules, skills, memory, tool results)
costs in the context of a Claude Code session, counted from the API usage
recorded in its transcript, not estimated from characters. For Claude Code
users who want to know what fills their context.
Or try it in the browser:
choose one of your transcripts, or run the synthetic example. The library runs
in the page (Pyodide); your file is never uploaded.
Reads only the transcripts under ~/.claude/projects on your machine.
Nothing is sent anywhere. The numbers are tokens, not dollars.查看完整 README ↗How much each source (your CLAUDE.md, rules, skills, memory, tool results)
costs in the context of a Claude Code session, counted from the API usage
recorded in its transcript, not estimated from characters. For Claude Code
users who want to know what fills their context.
Try it in a minute:
pip install claude-context-cost
claude-context-cost --example
Or try it in the browser: choose one of your transcripts, or run the synthetic example. The library runs in the page (Pyodide); your file is never uploaded.
Reads only the transcripts under
~/.claude/projectson your machine. Nothing is sent anywhere. The numbers are tokens, not dollars.
The usual shortcut, characters ÷ 4, counts 40 to 45% too few tokens (−45% in the author's sessions, mostly in Portuguese; −40% in one in English). Here the sources of every response add up exactly to the token total the API recorded, checked in 457 transcripts.
Also: --budget
fails a pull request or a commit that makes a CLAUDE.md, a rule or an
import grow over the limit you set, and
--versions
shows which git commit of each CLAUDE.md, rule and memory file a session
loaded.
pip install claude-context-cost
Python 3.11 or newer, no dependencies. To install a tagged version straight from GitHub instead:
pip install "git+https://github.com/peterwkdev-creator/[email protected]"
claude-context-cost --example
claude-context-cost ~/.claude/projects/<project-folder>/<session-id>.jsonl
The newest .jsonl in a project's folder is its latest session (on Windows,
~ is %USERPROFILE%). A subagent has its own transcript,
<session-id>/subagents/agent-<id>.jsonl.
Pass a project's folder instead of a file to sum its sessions and their
subagents: the costliest sources first, then one line per session. Pass
~/.claude/projects itself to sum every project. Tools and your own
~/.claude/... files add up across projects; a project's CLAUDE.md and
rules stay apart, marked with the project. A resumed or forked session
repeats the responses it came from in its own file: each is counted once.
--steps shows what entered before each response, --all lists every
source, --json is for scripts (for a folder too). On the synthetic example
shipped with the package (some rows left out):
cost share entered in chars/4 error how source
128,240 80.6% 36,640 7 - - - unattributed: system prompt, tools, overhead
10,400 6.5% 3,200 4 2,000 -38% measured, split tool: Read
5,600 3.5% 1,600 7 1,000 -38% estimated claude.md: CLAUDE.md
...
1,600 1.0% 800 4 500 -38% split, estimated path rule: .claude/rules/python.md
-38% means it would count 38% too few.measured (alone between two responses, so the usage gives its
exact tokens), split (shared with others, in proportion to bytes) or
estimated (at the start or after a compaction); rarely unknown (no
text to weigh, as an image) or shrank (the context got smaller); see
What it counts.claude.md, rule (always loaded), path rule (a
rule with paths:, loaded on demand), memory, skill, tool (its
results), prompt (your messages), output (Claude's earlier answers,
which the next request sends back), summary (a compaction's summary),
attachment (the text Claude Code wraps around them) and unattributed
(Claude Code's own system prompt and tool definitions: not from your
files, usually the largest row; fewer MCP servers make it smaller).From Python:
from claude_context_cost import analyze, example_path
report = analyze(example_path()) # or the path of any .jsonl transcript
print(report.total) # 159160: input tokens summed over the 7 responses
read = report.sources[("tool", "Read")]
print(read.entered, read.responses, read.cost) # 3200 4 10400
print(read.estimate_div4) # 2000.0: characters / 4 for the same text
summarize(folder) returns the same sum as a folder on the command line:
.sources maps (kind, name, project) to the totals, with project set only
for a project's own files.
A transcript keeps the text of every CLAUDE.md, rule and memory file as it
was loaded, and the counts above use that text. --versions finds it in git:
claude-context-cost --versions ~/.claude/projects/<project-folder>/<session-id>.jsonl
CLAUDE.md, rules and memory as this session loaded them: their git version, and today's file
tokens loads version today file
337 1 no git same claude.md: ~/.claude/CLAUDE.md
871 1 1c3456f 2026-10-05 +289 tokens claude.md: CLAUDE.md
248 1 not committed same rule: .claude/rules/style.md
160 1 5c41635 2026-10-08 (later) same rule: .claude/rules/tests.md
680 2 e8e382b 2026-10-01 not found path rule: .claude/rules/api.md
tokens: of one load; loads: how many times the session loaded this text
version: the commit with exactly this text; (later): committed only after it was loaded
not committed: no commit has this text; no git: the file is not in a git repository
today: the file on disk now, as Claude Code would load it: same, +N or -N tokens (grew or shrank since), changed, or not found
entered adds up every load.(later).+289 tokens means it grew by
that much since the session loaded it.git log, git cat-file), never written. --json adds
the list under "versions" (the top-level "version" is the tool's own);
from Python, loaded_versions(transcript).--versions only on your own transcripts: it runs git in the folders
the transcript names. Git runs there with core.fsmonitor off, and only
absolute local paths are looked up (not relative or //host/share ones).There is no transcript in CI, so --budget measures the repository itself:
every CLAUDE.md, rule and @import Claude Code would load from it, as
Claude Code loads them (frontmatter and HTML comment blocks removed), held to
the limits you declare. It exits with 1 when a limit is exceeded, so a pull
request that bloats the context fails.
# context-budget.toml, at the root of the repository
startup = 3000 # everything loaded when a session starts
[limits] # per file; a file is held to every pattern that matches it
"CLAUDE.md" = 2000
".claude/rules/*.md" = 1500 # * stays in one folder, **/ is any number of folders
"**/CLAUDE.md" = 2000
claude-context-cost --budget context-budget.toml
It measures the current folder; give another after the budget file
(--budget context-budget.toml path/to/repo). A relative path to the budget
file starts from the current folder, not from the repository.
context budget of my-repo: 5 instruction files, 2.25 bytes per token (default)
tokens limit loaded file
622 1,500 start-up rule: .claude/rules/style.md
1,705 2,000 start-up claude.md: CLAUDE.md
1,066 - start-up claude.md: docs/architecture.md (imported by CLAUDE.md)
1,813 1,500 on demand path rule: .claude/rules/api.md OVER
427 2,000 on demand claude.md: web/CLAUDE.md
3,393 3,000 start-up total OVER
not counted, as not in the repository: your ~/.claude/CLAUDE.md, memory and any CLAUDE.md above it
over budget: 2 limits exceeded
path rule: .claude/rules/api.md: 1,813 tokens > 1,500 (limit ".claude/rules/*.md")
start-up total: 3,393 tokens > 3,000 (limit startup)
CLAUDE.md, .claude/CLAUDE.md, CLAUDE.local.md, rules in
.claude/rules/ without paths:, and what they import. On demand:
rules with paths: and the CLAUDE.md of a subfolder, with their imports.
Hidden folders and node_modules are skipped. Your own
~/.claude/CLAUDE.md, your memory (MEMORY.md) and any CLAUDE.md above
the repository are not in it, so they are not counted, though a session
loads them too.--quiet prints only the verdict and the limits
exceeded: within budget, or the over budget lines.bytes_per_token = ... in the budget. Running the tool on one of your
transcripts prints the ratio measured in it.*, ? and **/ are special; [ and ] are plain
characters. Quote a pattern with a dot, as above: TOML reads CLAUDE.md = 1
as a nested key.In a GitHub Actions workflow:
- uses: actions/setup-python@v7
with:
python-version: "3.x"
- run: pip install claude-context-cost==1.7.0
- run: claude-context-cost --budget context-budget.toml
--json gives the same result for scripts; from Python,
check_budget(repository, budget_file) returns it, and raises BudgetError
for an invalid budget.
claude-devtools already shows
the context by source. Read in its code at commit 1486f20 (the latest on
2026-10-10):
src/main/utils/tokenizer.ts);
only the turn total comes from the usage..claude/rules/ are listed as global sources without reading
their paths:, so a rule that never loaded still counts. Issue
#224, open since
2026-07-17.CLAUDE.md and rules are read from disk today, not as they were during the
session. On the author's machine (2026-10-11), only 290 of the 2,863
distinct texts loaded were still the same on disk.This tool fixes all three: it counts from the usage and from the text the
transcript kept, and --versions finds that text in git.
message.id. A response is written over several
lines with the same usage; it counts once.input_tokens + cache_read_input_tokens +
cache_creation_input_tokens.usage.paths: count only from the response where Claude Code
loaded them (nested_memory), never before.tests/fixtures/build_example.py)
where every source's tokens are worked out by hand: each one comes out
exact, every response adds up to its usage, a paths: rule that never
loaded counts 0, a response written over several lines counts once.tests/test_budget.py):
what loads at start-up and on demand, imports, rendering, limits, invalid
budgets. --versions is tested on synthetic git repositories
(tests/test_versions.py): a commit before and after the load, a text that
comes back, a deleted file, a file outside git.python tests/mutate.py breaks each of those rules in a copy of the code
(51 mutants: 24 in the budget, 10 in --versions); the tests catch all 51.usage, 0 where the response count differs from an independent count, and
the sum over every project takes every transcript. For the budget
(2026-10-11): the files found are the ones Claude Code loaded in 257 of
257 start-ups and 252 of 252 on-demand loads, with the same bytes in 268
of 268 files (loads whose files changed afterwards are left out). The
ratio was measured in 50 of the 73 sessions with responses, median 2.22
bytes per token. For --versions (2026-10-11): of 2,863 distinct texts
loaded, 811 were in a git repository and the commit was found for 798; the
other 13 were never committed. Every one of the 212 texts that are the same
today and in HEAD got its commit. Run it on yours with
CLAUDE_CONTEXT_COST_CORPUS=1 python -m unittest tests.test_corpus -v
(it prints only counts).how column says
which is which. Many steps bring a tool result together with a small
reminder, so splitting is common.@import that resolves to a file: on the
author's machine Claude Code loaded 32 of 35 such imports, with no rule
found for the other 3, so the budget may count more than loads, never less.--versions finds only the exact text. A commit that differs by one
character is not it; the file is then not committed. It needs git on
the PATH, and it reads only .md files.Transcripts of Claude Code 2.1 (the synthetic fixture follows 2.1.293). Python 3.11 to 3.14, tested on Linux and Windows.
Versions follow Semantic Versioning: the names in
claude_context_cost.__all__ and the keys of --json change incompatibly only
in a new major version. The transcript format is Claude Code's and changes
without notice; when it does, a fix keeps the API and ships as a minor or
patch version.
See CONTRIBUTING.md. Never paste a real transcript in an issue or pull request: it holds paths, file contents and sometimes secrets. Report a security problem privately, as in SECURITY.md.
| Project | What it does |
|---|---|
| numeros-publicos · site | Open data on every Brazilian municipality (IBGE, National Treasury, INEP), checked against the source, one page per municipality |
| simples-nacional-br · site | Brazil's Simples Nacional tax regime checked against the law: rate, DAS, split, Fator R and CNAE |
| linguagem-simples-br · site | Open checker for Brazil's Plain Language Act (Law 15,263/2025): tests a text against its art. 5 |
| vra-anac | On-time performance of Brazil's domestic flights from ANAC's VRA data |
| tts-ptbr | Brazilian Portuguese text-to-speech with open models (Kokoro and Piper), measured by Whisper |
| carrossel-terminal | Terminal-style Instagram carousel: Markdown becomes PNG, checked before posting, and the post becomes a Reel |
| ia-testada | The measurements behind the @peterwk.dev posts, with the script and how to redo them |
| numerasheets-site · site |
| Shop window for NumeraSheets: spreadsheet templates and free calculators |