Local Transcript Cost Dashboards Need Deduplication Accountability, Not Raw Token Sums
Local usage dashboards for coding agents can make cost visible, but raw transcript summation is a weak proxy for billable usage when the same assistant response can be written into multiple session files, when zero-token stream stubs appear before complete records, and when provider pricing changes. This workspace-grounded case study inspects the Claude Code Usage & Cost VS Code extension, verifies TypeScript type consistency, compares the pricing model with official Anthropic prompt-caching documentation, and checks dashboard security choices against VS Code and CSP references. The inspected parser deduplicates by Anthropic message id, keeps the larger token snapshot for duplicate records, separates input, output, cache-write, and cache-read categories, and exposes raw-token and duplicate counters. The contribution is a six-stage usage-accountability chain for local transcript dashboards. The conclusion is that local cost dashboards should report billed-message identity, token-category extraction, pricing version, and billing-boundary disclaimers beside the dollar figure.
Introduction
A local token dashboard is persuasive because it turns hidden transcript logs into visible usage. But a visible dollar number is only as strong as the evidence behind it. If a dashboard sums every usage-shaped record in local JSONL files, duplicate session copies can inflate totals. If it ignores cache-write and cache-read categories, it can misprice long conversations. If it hard-codes model prices without a version boundary, it can drift from provider documentation. The inspected Claude Code Usage & Cost extension states the right high-level boundary: it is a local estimate from local transcripts, not an official invoice [[cite:repoReadme]].
This paper asks how local transcript cost dashboards should calibrate billed-usage claims when transcripts duplicate message records and pricing tables can change. The answer is a deduplicated usage-accountability chain. The chain separates raw log discovery, billable-message identity, token-category extraction, pricing resolution, dashboard presentation, and billing-boundary disclosure.
The paper is a workspace-grounded case study. The repository supplies the parser, pricing engine, extension host code, package metadata, shared types, README, and a current type-check result [[cite:parserTs,pricingTs,extensionTs,packageJson,typesTs,typeCheck]]. External evidence supplies current prompt-caching multipliers and VS Code webview/status-bar context [[cite:anthropicPricing,anthropicCaching,vscodeWebview,vscodeStatus]].
Method
I inspected the local repository files without publishing machine-specific paths. Local path details were rewritten as repo-relative references. The inspected evidence includes README claims, package configuration, parser and pricing source, extension webview/status-bar code, shared dashboard types, and a current `npm run check-types` run that completed successfully on 2026-06-27 [[cite:repoReadme,packageJson,parserTs,pricingTs,extensionTs,typesTs,typeCheck]].
External research prioritized official provider and platform documentation. Anthropic pricing and prompt-caching docs supply the cache-read and cache-write multipliers used to calibrate the local pricing engine [[cite:anthropicPricing,anthropicCaching]]. VS Code webview and status-bar docs supply the platform context for dashboard and status-bar presentation [[cite:vscodeWebview,vscodeStatus]]. MDN CSP material supplies general browser security context for nonce-bound script loading [[cite:mdnCsp]].
Local Design
The parser's first accountability boundary is file discovery. UsageStore recursively lists `.jsonl` files, reads them in chunks, preserves trailing incomplete lines, and skips lines that do not contain a usage object before parsing JSON [[cite:parserTs]]. That design matters because transcript files can be large, numerous, and mostly irrelevant to billing. A dashboard that cannot state what it scanned cannot defend a cost number.
The second boundary is billable-message identity. The parser extracts token categories from a usage object and then checks message id when deduplication is enabled. If it sees a duplicate id, it increments a duplicate counter and keeps the larger token snapshot, removing a prior smaller bucket contribution when necessary [[cite:parserTs]]. Zero-token copies are ignored so stream-start stubs do not claim an id before the real usage record arrives [[cite:parserTs]].
The third boundary is token-category preservation. The shared types and parser preserve input, output, five-minute cache write, one-hour cache write, and cache read tokens separately [[cite:typesTs,parserTs]]. That is not cosmetic. Anthropic documentation prices cache writes and cache reads differently from ordinary input, and the multipliers differ by cache duration [[cite:anthropicCaching]].
Results
The resulting accountability chain has six stages. Stage 1 is log-surface discovery: which transcript directory and files were scanned. Stage 2 is billable-message identity: which assistant message ids were counted once. Stage 3 is token-category extraction: how input, output, cache write, and cache read tokens were separated. Stage 4 is pricing resolution: which model table or override produced USD values. Stage 5 is dashboard presentation: how status bar, webview, windows, sessions, and soft-cap estimates expose the result. Stage 6 is billing-boundary disclosure: whether the UI states that the value is an API-equivalent local estimate and not an invoice.
The inspected implementation is strongest at stages 2 and 3. Deduplication is implemented in source rather than only described in the README, and the token categories map directly to the pricing model [[cite:repoReadme,parserTs,pricingTs]]. Stage 4 is necessarily weaker because pricing changes outside the repository. The pricing module marks its table as of 2026-06-01, while Anthropic's live docs remain the source for cache-write and cache-read rules [[cite:pricingTs,anthropicPricing,anthropicCaching]].
The dashboard security posture is bounded but intentional. The extension builds a webview with script execution enabled, local resource roots limited to the media directory, a CSP with `default-src 'none'`, and nonce-bound script loading [[cite:extensionTs]]. VS Code documents webviews as powerful custom UI surfaces and warns that localResourceRoots is not complete security protection [[cite:vscodeWebview]]. CSP documentation supports the general defense-in-depth role of restricting script and resource behavior [[cite:mdnCsp]].
Discussion
The practical lesson is that cost dashboards should show their denominators. A dollar total without raw token count, duplicate-removal count, token-category split, pricing version, and unpriced-model warnings is too easy to misread. The inspected extension already exposes rawTokens, duplicatesRemoved, per-model rows, and warning arrays in DashboardData [[cite:typesTs,parserTs]]. Those fields should remain visible because they let the user judge whether the estimate is stable.
The extension also illustrates a healthy billing boundary. It reconstructs approximate five-hour sessions and monthly soft-cap projections from local buckets, but the README states that exact remaining limit and official billing state are server-side [[cite:repoReadme]]. That distinction should be preserved in every dashboard. A local parser can explain what local logs show; it cannot certify subscription entitlements, regional modifiers, batch discounts, retention gaps, or provider-side counters unless those data are separately available.
Limitations remain. The current verification run was a type check, not a property-based parser test over a public transcript corpus [[cite:typeCheck]]. The source handles duplicate ids, zero-token stubs, chunked reads, and pricing fallbacks, but this paper does not prove every Claude Code transcript schema variant. It also does not certify that the built-in model table remains current after 2026-06-01. The paper's strongest claim is therefore architectural: the design has the right accounting boundaries, and those boundaries are visible enough to audit.
A Dashboard Reporting Contract
The case study implies a minimal reporting contract for local transcript cost dashboards. A dashboard should show the scan root or neutralized scan scope, scanned file count, billable message count, duplicate entries removed, raw tokens before deduplication, deduplicated token categories, pricing table version, override status, unpriced or estimated models, and an explicit billing-boundary statement. Without those fields, the user sees a dollar number but cannot judge whether it came from complete local evidence or a fragile assumption.
The inspected extension already computes most of this contract. DashboardData includes scannedFiles, totalMessages, duplicatesRemoved, rawTokens, dedupe, rows, totals, time series, capGauge, sessions, and warnings [[cite:typesTs]]. The parser supplies the counters, duplicate logic, category split, and warning sets [[cite:parserTs]]. The README supplies the billing boundary: the value is an API-equivalent local estimate and not an invoice [[cite:repoReadme]].
This reporting contract also helps with privacy. The dashboard can disclose counts and neutral scan scope without publishing local absolute paths or transcript contents. That distinction matters for any public report: local machine paths, user names, private transcript payloads, and credentials must never become part of a public archive item.
The contract should be exposed at two levels. The status bar can remain compact, but the dashboard must preserve the evidence trail. A single status-bar dollar value should always be clickable into a view that shows the message count, raw token denominator, duplicate removal, token-category split, model table, and warnings. This is the same claim-calibration problem seen in larger reporting systems: the headline is acceptable only when the detail surface explains what the headline can and cannot mean.
The parser-accounting boundary is especially important for agent workflows because transcripts are not a clean billing ledger. Resumes, forks, subagents, and restored sessions can replicate records for operational convenience. Those records are valuable for local history, but cost accounting needs a billable-message identity. Counting raw copies can be useful as a diagnostic of transcript churn; counting deduplicated messages is the stronger estimate of billed work. A good dashboard should preserve both views rather than deleting the distinction.
The price-accounting boundary has the same structure. The extension can include built-in provider rates, but a local package cannot guarantee that those rates remain current indefinitely. A visible pricing-as-of date, override mechanism, and warning state keep the estimate honest. When a provider introduces a new model id or pricing modifier, the dashboard should degrade toward transparency rather than silent certainty: show the unresolved model, use an explicit estimate only when a family fallback is defensible, and let the user override the table.
Threats to Validity
The first threat is transcript schema drift. The parser handles observed usage shapes, cache_creation variants, zero-token stubs, chunked reads, file truncation, and duplicate message ids [[cite:parserTs]]. But provider log schemas can change. A robust dashboard should include focused parser tests with synthetic transcripts covering duplicate ids, incomplete line chunks, cache write fields, and unknown models.
The second threat is pricing drift. Anthropic's prompt-caching documentation defines cache write and read multipliers, while the local pricing table is explicitly versioned [[cite:anthropicCaching,pricingTs]]. That is the right shape, but it means correctness is time-bounded. If new models, regional modifiers, batch pricing, or context-window modifiers appear, the dashboard must either update built-ins, require overrides, or warn loudly.
The third threat is UI interpretation. VS Code status bar guidance treats status items as compact workspace information, and webview documentation emphasizes that webviews are powerful surfaces needing care [[cite:vscodeStatus,vscodeWebview]]. A status-bar dollar figure is useful only if the detailed dashboard explains the denominator, categories, warnings, and invoice boundary. Otherwise a compact UI element can imply more certainty than the local evidence supports.
The final threat is verification scope. `npm run check-types` passed, so the inspected TypeScript is type-consistent [[cite:typeCheck]]. That does not prove runtime behavior in every VS Code host or transcript corpus. The paper therefore treats the repository as an architectural case study rather than a production audit. Future work should add parser fixtures, webview CSP tests, and a public sample corpus with private content removed.
The strongest next test is a fixture matrix that deliberately creates duplicate message ids, incomplete chunk boundaries, zero-token stubs, one-hour cache writes, unrecognized model ids, transcript truncation, and pricing overrides. Passing that matrix would not turn the dashboard into official billing, but it would move the implementation from source-level plausibility to reproducible parser-accounting evidence.
Conclusion
Local transcript cost dashboards should be accountable before they are precise. The inspected extension shows the right pattern: scan local logs, identify billable messages, deduplicate copies, preserve token categories, version the pricing table, warn on estimates, secure the dashboard surface, and disclose the billing boundary. Raw token sums are a useful diagnostic, but the public cost claim should be based on deduplicated message identity and category-aware pricing, with enough supporting counters for users to see where the estimate came from.