Repository navigation
Record Claude Code token usage with token_format = "claude-json" - #155
Open
Poncho1112 wants to merge 1 commit into
Open
Poncho1112 wants to merge 1 commit into
Poncho1112 wants to merge 1 commit into
Conversation
In one operator's eval log the claude engine recorded no tokens on any of 2,672 attempts. Two causes stacked up: - `claude --print --output-format json` prints a single JSON result line whose usage holds several counts, and nested blocks later in the same line also carry "output_tokens". A token_regex takes the last match (606 instead of 4,745 in a real result) and cannot add fields together. - The configured regex was mis-escaped: inside a single-quoted TOML string backslashes are literal, so a doubled backslash before s reached Python as a literal backslash and the pattern never matched. An engine can now set token_format = "claude-json". The parser reads the top-level usage of the last result line and records non-cached input + cache creation + output tokens (cache reads are re-reads of context already counted). If no result line is found it falls back to token_regex, and other engines are unchanged. load_engines prints a one-line warning when a token_regex has a doubled backslash before a regex class letter, and config.sample.toml gains a commented [engines.claude] example. Tests: tests/test_claude_tokens.py (11) with synthetic result lines, plus an end-to-end run through a fake claude-shaped engine. Full suite: 295 tests, all passing. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This was referenced Oct 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In one operator's eval log, the claude engine recorded no tokens on any of 2,672 attempts. That left the biggest lane with no token or cost evidence on the scoreboard. Two problems stacked up:
claude --print --output-format jsonprints a single JSON result line:{"type":"result", ..., "usage":{"input_tokens":..,"cache_creation_input_tokens":..,"cache_read_input_tokens":..,"output_tokens":.., ...}, "modelUsage":{...}}. Nested blocks later in that line also contain"output_tokens".parse_token_counttakes the last match, which on a real result gave 606 instead of 4,745, and a regex can't add fields together anyway.'"output_tokens"\\s*:...'reached Python as a literal backslash followed bysand never matched anything.What changes
token_format = "claude-json"is a new optional engine key. It's inherited liketoken_regex, and unknown values are rejected. With it set,parse_claude_json_tokens()reads the top-levelusageof the last result line and records non-cached input + cache creation + output tokens. Cache reads are left out because they re-read context that was already counted, and including them would inflate long sessions several times over.parse_worker_tokens()is used at the one call site that computes a worker attempt's tokens. If a claude-json engine prints no result line, it falls back totoken_regexas before. Engines withouttoken_formatbehave exactly as today.load_engineswarns on stderr, without failing, when atoken_regexhas a doubled backslash before a regex class letter, the single-quoted-TOML mistake above.config.sample.tomlgains a commented[engines.claude]example using the new key.Tests
tests/test_claude_tokens.pyhas 11 tests, all on synthetic data: nestedoutput_tokensafter the top-level usage, surrounding log lines, no result line, truncated JSON, last of two results wins,token_formatloading and rejection, regex fallback, the mis-escape warning, and an end-to-endringer.py runthrough a fake Claude-shaped engine that asserts the eval row'sworker_tokens.RINGER_NO_SELF_UPDATE=1 python3 -m unittest discover -s testspasses all 295 tests.This is independent of #154 (the INFRA verdict); either can merge first.
🤖 Generated with Claude Code