Skip to main content
Glama

Token ledger

token_ledger
Read-only

Walk host JSONL transcript directories to report actual API token usage and cost per session from usage blocks; name a model to price totals.

Instructions

What a session actually cost, read off the host's own transcripts. Walks root for *.jsonl transcripts — the host writes <cwd-slug>/<session>.jsonl and <cwd-slug>/<session>/subagents/*.jsonl beneath ~/.claude/projects — and answers ONE JSON document: root, transcripts, lines, requests (distinct API requests), totals (the four classes: input_tokens, cache_creation_input_tokens, cache_read_input_tokens, output_tokens), sessions (one row each), omissions, and cost only when model is given. A degraded server adds the footer as its last key, bantamkit_degraded. Call it to answer 'what did this work cost' from the API's own usage blocks; nothing is estimated. Point root at ONE project's slug directory: there is no time window or summary mode, so a whole-corpus call answers a row per session ever recorded and blows the host's tool-result cap. The four classes are priced separately: on a real prompt 98.1 % of the tokens were cache_read. Counting is per requestId, never per line: one response is written as several records with the same usage, so the dedupe spans the whole walk and every later copy is a duplicate-request omission. A subagent's transcript carries its PARENT's sessionId, so its cost lands in the parent row as sidechain_requests. lines equals requests plus the sum of every omission's count, always. An omission is {subject, count, what}; what names the first site as <relpath>:<line> plus and N more. cost needs a rate: the shipped price table has none, so {"unavailable": "no rate recorded for model ..."} is the NORMAL answer, not an error; a rate enters through $BANTAMKIT_PRICES or prices. Refused with their own sentence: an EMPTY root, a root that is missing or is a file, an EMPTY model, and a token total above 2**53-1. The record rule and the nine omission subjects: docs/ledger.md.

Input Schema

NameRequiredDescriptionDefault
rootYesDirectory of host transcripts to walk, absolute or relative to the server's working directory; `~/.claude/projects` is where the host keeps them on this machine. It must name a directory: the empty string is refused rather than resolved, because resolving it would read whatever directory the server happens to be standing in
modelNoModel to price the totals as, e.g. the id an assistant record's `message.model` carries. Omit it and no `cost` key is reported at all; name one with no recorded rate and `cost` is `{"unavailable": ...}`, which is what the shipped table answers for every model
pricesNoPrice table to read instead of `$BANTAMKIT_PRICES` or the shipped one; only consulted when `model` is given. A malformed table is a configuration fault and stops with its own sentence, rather than being reported as an unpriced model

Output Schema

NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.36.0

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover readOnly/openWorld; the description adds substantial behavior beyond them: per-requestId dedupe spanning the whole walk, duplicate-request omissions, subagent cost attributed to the parent as sidechain_requests, the invariant lines = requests + omission counts, the bantamkit_degraded footer, and the four explicit refusal cases. This is far more than the annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose, scoping rule, and misuse warning are front-loaded and every sentence carries information. It is dense and jargon-heavy (bantamkit_degraded, relpath:line omission format), which pushes against readability, but there is essentially no filler to cut.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-input aggregation tool with an output schema present, the definition covers invocation constraints, edge cases, invariants, and failure modes; an agent has everything needed to call it correctly and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3, but the description adds real meaning beyond the schema — the one-project-per-call constraint on `root`, that `prices` is only consulted when `model` is set, and that `{"unavailable": ...}` is the normal cost answer rather than an error.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource framing — reporting what a session cost from the host's own transcripts — and names the exact artifacts it walks (*.jsonl under ~/.claude/projects). No sibling tool does anything similar, and the agent can tell immediately what this produces.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit trigger ('Call it to answer "what did this work cost"'), an explicit scoping rule ('Point root at ONE project's slug directory'), and an explicit when-not with the consequence ('there is no time window or summary mode, so a whole-corpus call ... blows the host's tool-result cap').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.