Skip to content

v0.4.0

Choose a tag to compare

@shoustak shoustak released this 21 Sep 19:47
· 8 commits to main since this release
5e7a1f3

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 ITSELF is itemised: the client's own tools and system prompt are rows, so unattributed is 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 -p and 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