Repository navigation
v0.4.0
The rows are read, not modelled. A recent Claude Code writes what it sent into the session transcript: the skill listing as it went out, the tool names, each instruction file, its own tools and system prompt. context-tax now reads that record, and keeps the model for a machine that has none. A line under the table says which one the rows came from.
What your agent never received
Claude Code gives the skill listing a budget of 1% of the context window. Past it, every skill keeps its name and descriptions compete for what is left, so the ones that lose reach the model as a bare name. Nothing on screen says so.
It is now the first finding when it happens: how many, grouped by who owns them, and both ways out priced. Raise skillListingBudgetFraction and pay for every description, or switch skills off and hand their room on. context-tax fix --restore-descriptions writes the first. It is never part of a plain fix, because it is the one change here that makes every turn cost more.
Two screens made to be shared
context-tax receipt: the same totals by kind, with no server, plugin, skill or path on it.context-tax session [id] [--svg file]: one session turn by turn. The climb, each compaction, and the floor it never drops under, which is the fixed prefix the main screen itemises.
Also new
- The first line says the share of your window, and only when a session proves the window. The window is worked back from a listing pinned against its budget, never assumed.
CLAUDE CODE ITSELFis itemised: the client's own tools and system prompt are rows, sounattributedis the gap between characters and billed tokens and not most of the screen.- Connectors no file declares, such as one attached to a claude.ai account, are rows, read from what was sent.
Fixed, and these change your numbers
- 🚨 One reply is counted once. Claude Code writes a single API reply as several transcript lines, and every line repeats the reply's
usage. Earlier versions counted lines, so turns, tokens carried and every per-call figure ran at about twice the truth. Those figures drop on upgrade, and the new ones are right. - 🚨 A plugin's MCP server is no longer reported as never called. Its tools are keyed
mcp__plugin_<plugin>_<server>__, and the join looked for the bare name. - A server that could not connect is charged nothing and gets no finding.
- A server's per-turn cost is what a deferring client sends: its tool names and instructions, not every tool description.
claude -pand SDK runs no longer stand in for a session a person started.
Privacy
The transcript record holds the full text of your instruction files and skill descriptions. The parser takes lengths, counts and names from it and drops the text on the same line, so none of it reaches the report, --json or the library API. A test asserts that.
Verified before tagging
377 tests across 15 files on Node 20, 22 and 24. 27 guards mutation-checked: the bug put back, a test seen to fail. Packed locally and grepped rather than reasoned about: 93 files, the same top level as 0.3.1, and no name, path or count from a real machine anywhere in the tarball.
Full changelog: v0.3.1...v0.4.0