Repository navigation
Description
I run Claude Code behind a local relay that answers every response with the same message id ("ocgo") and no request id. Usage reports were wrong in a big way: daily and monthly views showed 750K tokens of claude usage while my raw session logs summed to 1.21B across three days.
Cause: push_deduped_entry (lib.rs) and push_deduped_daily_entry (daily.rs) key entries on (message_id, request_id) alone. When those two are identical for every record, which is the normal case behind an LLM gateway, each record after the first scanned one matches the exact hash and gets dropped unless its total is strictly larger. One survivor per relay, everything else gone.
Minimal repro: two jsonl session files where assistant records share message.id and have no requestId. Scanned together, only one file's usage survives. Scanned alone, each reports correctly. I can put this up as a fixture-based test.
Fix that worked for me: add session_id and timestamp to the exact-match hash and matcher. True double-writes still collapse. Claude Code does write some (same session, same timestamp, same usage). Distinct sessions keep their own rows. On my data this took claude all-time from 750K to 1.21B tokens, which now matches an independent sum over the raw logs within 0.03%.
Related: #1459 did the same thing for codex ("scope event dedupe to sessions"), and #1155 introduced this dedup for the sidechain replay case. Fork-copied transcripts keep collapsing under the scoped key because their internal session ids and timestamps still match - verified against two identical copies at different paths before writing this.
Happy to send the patch as a PR with regression tests once approved here.
About how this report was produced
The initial investigation and draft were written by an AI coding agent: pi coding agent running ox-alpha-free via OpenCode Go. It found the bug by bisecting my own session logs against ccusage's output, verified the fix on about 240 real session files, and drafted this text. A human reviewed the findings and this report before posting.
Activity
pullfrog commentedon Aug 24, 2026
Assessment
This issue is actionable. The reported failure is confirmed in the current Rust implementation:
rust/adapters/claude/src/lib.rs:147-209anddaily.rs:401-440use only(message_id, request_id)for the exact lookup, so a gateway that reuses those values can discard usage from independent sessions. The regular loader already has the parsed timestamp and path-derived session context, while the daily loader currently parses both timestamp andsessionIdbut retains only the date. The unified Claude loader delegates to these two paths (rust/crates/ccusage-adapter-all/src/loader.rs:593-610), so no separate unified dedupe implementation is needed.One compatibility detail needs to be handled deliberately: the existing
keeps_most_complete_duplicate_usage_entrytest relies on two records with the same message/request IDs but different timestamps collapsing to the more complete record. The safest scope is to always include session provenance, and use timestamp as part of the identity for records without a request ID, which fixes gateway records without changing established request-ID replacement behavior.Implementation Plan
TimestampMswhenrequestIdis absent. Prefer the serialized recordsessionIdso fork-copied transcripts with the same internal identity still collapse; fall back to the path-derived session ID when the field is missing so unrelated files do not collide.push_deduped_entryandpush_deduped_daily_entry, including their hash indexes and equality matchers. Apply the session and timestamp scope to the sidechain replay lookup as well, preserving the existing parent-versus-sidechain preference and higher-usage replacement rules.AgentProgressrecords, retain the parsed timestamp onDailyLoadedEntry, and update its unit-test fixture helpers accordingly.rust/adapters/claude/src/README.md, then run the focused Claude/ccusageRust tests and the relevant workspace checks.No implementation has been started.
Task list (3/3 completed)
@v0or keep the SHA fresh with Dependabot | Implement plan ➔ | View workflow run | via Pullfrog | UsingGPT Luna(free via Pullfrog for OSS) | 𝕏github-actions commentedon Aug 24, 2026
This issue was auto-closed. Issues from new contributors are auto-closed by default.
Maintainers review auto-closed issues and reopen worthwhile ones. Issues that do not meet the quality bar in CONTRIBUTING.md may not be reopened or receive a reply.
Keep the issue short, concrete, and written in your own voice.
If a maintainer replies
lgtmi, your future issues will stay open. If a maintainer replieslgtm, your future issues and PRs will stay open.See CONTRIBUTING.md.
ryoppippi commentedon Aug 27, 2026
@pullfrog Triage this issue using the repository standing issue-triage instructions. Inspect the full issue body, comments, current main branch, and related issues or pull requests. Choose exactly one priority label. If the issue is clearly unresolved and is priority:critical or priority:high with safe and well-scoped requirements, implement it and open a focused pull request. Otherwise, only triage it. Keep the explanation short and use simple English.
pullfrog commentedon Aug 27, 2026
Priority: high. This is a real usage undercount bug: Claude records from independent sessions can collapse when a gateway reuses
message.idand omitsrequestId. Currentmainstill has the affected deduplication, and related Codex work does not fix Claude. I prepared a focused fix with regression tests, but could not open the PR because pushing the branch failed:remote: Permission to ccusage/ccusage.git denied to github-actions[bot].@v0or keep the SHA fresh with Dependabot | View workflow run | via Pullfrog | UsingGPT Luna(free via Pullfrog for OSS) | 𝕏github-actions commentedon Aug 28, 2026
Pullfrog triage: priority:high
A maintainer explicitly requested an implementation attempt. Clear, actionable, repository-scoped Claude undercount bug with a concrete reproduction, identified deduplication cause, proposed safe fix, and regression-test plan. Related Codex and Claude deduplication work confirms the scope; it is not a duplicate.
Decision: kept open; Pullfrog will attempt a focused implementation PR.
ryoppippi commentedon Aug 31, 2026
Historical audit: this discussion was auto-closed by the legacy contributor gate. That closure did not assess technical importance.
Audit result: resolved. A later merged change or the current
mainimplementation covers this request. This item is kept for history and does not need to be reopened.