Skip to content

fix(usage): Claude usage no longer lists a <synthetic> model - #14672

Merged
juliusmarminge merged 3 commits into
pingdotgg:mainfrom
tris203:fix/usage-skip-claude-synthetic
Oct 19, 2026
Merged

juliusmarminge merged 3 commits into
pingdotgg:mainfrom
tris203:fix/usage-skip-claude-synthetic

Conversation

@tris203

@tris203 tris203 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Claude Code writes local <synthetic> placeholders into transcripts. Counting them as usage adds a bogus model row, including after a restart when the row is already cached.

The shared line/projected parser now skips that exact marker. Cache loading applies the same filter to Claude regular and tail records, preserving real models, real zero-token records, other providers, parse positions, and saved usage for deleted transcripts. The cache version stays unchanged; no cold rescan is required.

Rebuilt from @tris203's #14672, preserving the contributor commits and merging main. Fixes #14670.

Verification

  • Two focused suites: baseline 19 passed; revised regressions against main exposed 2 expected failures (18 passed); after implementation 20 passed. The final review also ran the existing UsageService, transcript-reader, streaming, and pricing suites: 98 passed across six suites overall. The cache round-trip test was extended instead of adding another case/file.
  • Scoped server typecheck and changed-file lint/format checks passed.
  • Two independent adversarial rounds with Claude Opus 5.5 and Codex gpt-6-sol. Round 1 found no correctness issues; its test-simplification suggestion was applied without adding cases. Round 2 found no remaining findings across the complete diff against main.
  • Live headless Linux web app with isolated transcripts and an existing version 5 cache: main displays the bogus model; head removes it while retaining both real models, 3.75K tokens, and 2 sessions, including real cached history whose transcript no longer exists. Appending another placeholder and refreshing retains the same rows and totals. The persisted cache offset advanced to the appended file size.
  • Both captures use the same 1280×800 viewport and Past 24h token view. Chromium system fonts measured zero width, so the preview tab loaded a local DejaVu font for both captures; no product font changes.
  • Not verified: a live Claude account, macOS, Windows, iOS, Android, or Electron desktop. The server aggregation path is shared by clients; no client layout or contract changes.

Before — main parser/cache:

Before: Claude usage lists an unpriced synthetic model alongside two real models

After — head parser/cache, same real usage:

After: only the two real Claude models remain, retaining 3.75K tokens and two sessions

Implementation: Codex gpt-6.1-sol; tests: Codex gpt-6-astra; reviews: Claude claude-opus-5-5 and Codex gpt-6-sol, through T3 Code delegated tasks. Maintainer integration: Codex gpt-6.1-sol in T3 Code.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Oct 1, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 1, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 3d7b402

Macroscope's review found this PR approvable — This is a small, self-contained usage bug fix that filters only Claude’s known local <synthetic> placeholder in both fresh parsing and persisted cache loading. Tests cover parser paths, cache cleanup, real zero-token records, and preservation of other providers.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

We couldn't safely recover the incremental review. No full review was started, and the last reviewed checkpoint was preserved. Retry later, or explicitly request a full review by commenting @coderabbitai full review.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4912b3a3-2f28-4920-8cfb-e4883f2f0926
📥 Commits

Reviewing files that changed from the base of the PR and between 05826ad and 172b99f.

📒 Files selected for processing: 4
  • apps/server/src/provider/Drivers/claudeUsage.test.ts
  • apps/server/src/provider/Drivers/claudeUsage.ts
  • apps/server/src/usage/usageScanCache.test.ts
  • apps/server/src/usage/usageScanCache.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📝 Walkthrough

The Claude transcript parser rejects records with the <synthetic> model marker. The usage scan cache decoder also skips cached Claude records with that marker. Tests cover both filtering paths and verify that ordinary model records remain.

Changes: Claude usage transcript filtering

Layer / File(s) Summary
Reject synthetic transcript records
apps/server/src/provider/Drivers/claudeUsage.ts, apps/server/src/provider/Drivers/claudeUsage.test.ts
The parser rejects records with an empty model or the <synthetic> marker. Tests verify that synthetic records are ignored and a real model record is retained.
Skip synthetic cached records
apps/server/src/usage/usageScanCache.ts, apps/server/src/usage/usageScanCache.test.ts
The cache decoder skips Claude records with the <synthetic> marker. A test verifies that an ordinary record remains after decoding.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to 172b9

The change removes synthetic entries from Claude usage while preserving ordinary model records. No actionable merge-blocking risk is evident.

Pre-merge checks: Passed 4
Check name Status Explanation
Linked Issues check Passed Issue #14670 requires the Usage model breakdown to list only real models or explain other entries. parseClaudeRecord now rejects CLAUDE_SYNTHETIC_MODEL, and the shared parser covers line and strea…
Out of Scope Changes check Passed The parser filter directly fixes issue #14670. The cache-load filter applies the same fix to existing cached transcripts and leaves other providers and real Claude models unchanged. The added tests su…
Title check Passed The title is concise, specific, and accurately describes the primary change: excluding Claude usage records.
Description check Passed The description clearly explains the problem, implementation, scope, linked issue, and verification results. It does not use the template's explicit Problem, Change, and Scope and approval headings, b…
Full details: Linked Issues check

Explanation

Issue #14670 requires the Usage model breakdown to list only real models or explain other entries. parseClaudeRecord now rejects CLAUDE_SYNTHETIC_MODEL, and the shared parser covers line and streaming readers. decodeScanCache also removes existing cached Claude records with that model. Tests cover dropping the placeholder and retaining a real-model zero-token record. These changes satisfy the issue requirement without removing billed records.

Full details: Out of Scope Changes check

Explanation

The parser filter directly fixes issue #14670. The cache-load filter applies the same fix to existing cached transcripts and leaves other providers and real Claude models unchanged. The added tests support both changes. The reviewed diff shows no unrelated change.

Full details: Description check

Explanation

The description clearly explains the problem, implementation, scope, linked issue, and verification results. It does not use the template's explicit Problem, Change, and Scope and approval headings, but the required information is present and the description is mostly complete.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.

Comment @coderabbitai help to get the list of available commands.

@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 2, 2026 — with ChatGPT Codex Connector
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 2, 2026 05:28

Dismissing prior approval to re-evaluate 46897b7

@tris203
tris203 force-pushed the fix/usage-skip-claude-synthetic branch from 46897b7 to ea65739 Compare October 4, 2026 07:56
@github-actions github-actions Bot added size:S 10-29 changed lines (additions + deletions). and removed size:XS 0-9 changed lines (additions + deletions). labels Oct 4, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 4, 2026
@tris203

tris203 commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Note

Opus 5.5 responding on behalf of @tris203

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@tris203
tris203 force-pushed the fix/usage-skip-claude-synthetic branch from ea65739 to d9e0047 Compare October 9, 2026 22:46
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 9, 2026 22:46

Dismissing prior approval to re-evaluate d9e0047

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 9, 2026
Claude Code stamps `<synthetic>` on messages it writes locally, such as the placeholder after an interrupted turn. They never reached the API, so the usage parser now drops them instead of giving them a model bucket. Entries already in the scan cache drop them when the cache loads, so already-scanned transcripts lose them too without a cold scan.

Fixes pingdotgg#14670
@tris203
tris203 force-pushed the fix/usage-skip-claude-synthetic branch from 05826ad to 172b99f Compare October 16, 2026 07:06
@juliusmarminge juliusmarminge self-assigned this Oct 19, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Taking over this one for batch claude-01. I’ll rebuild the synthetic-model filtering against current main, cover both newly parsed and cached records with minimal tests, and refresh the live proof before publishing.

@juliusmarminge

Copy link
Copy Markdown
Member

@coderabbitai resume

@macroscopeapp
macroscopeapp Bot dismissed their stale review October 19, 2026 13:55

Dismissing prior approval to re-evaluate 3d7b402

@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Incremental review skipped.

@juliusmarminge
juliusmarminge merged commit f34ba43 into pingdotgg:main Oct 19, 2026
30 checks passed
@tris203
tris203 deleted the fix/usage-skip-claude-synthetic branch October 19, 2026 18:18
Pipyakas pushed a commit to Pipyakas/t3code that referenced this pull request Oct 19, 2026
…otgg#14672)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
(cherry picked from commit f34ba43)
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Oct 19, 2026
## What's Changed
* fix(mobile): settings no longer tell you to update when you're up to date by @shivamhwp in pingdotgg/t3code#21688
* test(web): fix the workflow script test that times out on busy CI runners by @shivamhwp in pingdotgg/t3code#21699
* fix(mobile): a file shared into a new task shows in the composer before you send by @shivamhwp in pingdotgg/t3code#21659
* fix(desktop): a cold WSL distro gets 30 seconds to boot instead of 10 by @SunkenInTime in pingdotgg/t3code#21070
* fix(web): detect software keyboard before handling composer Enter by @Yash-Singh1 in pingdotgg/t3code#21763
* fix(mobile): the Git sheet uses the standard list rows by @juliusmarminge in pingdotgg/t3code#21785
* fix(server): changed files keep their real paths for renames and non-ASCII names by @Atharvsinh-codez in pingdotgg/t3code#20175
* fix(server): a message promoted into a stopping run stays queued by @lbgos in pingdotgg/t3code#16926
* perf(mobile): streaming re-renders less on the open thread screen by @juliusmarminge in pingdotgg/t3code#20963
* feat(usage): show even-pace marks on Limits bars by @flamboh in pingdotgg/t3code#14477
* fix(web): Usage hourly labels follow the Time format setting by @mInrOz in pingdotgg/t3code#15575
* fix(web): stop repeating the subagent name in the waiting banner by @saphid in pingdotgg/t3code#16022
* fix(web): Cmd+O no longer opens the editor more than once by @5knnbdwm in pingdotgg/t3code#18983
* fix(web): hoist favorited legacy models to the top of the model picker by @TonybynMp4 in pingdotgg/t3code#11933
* fix(server): a rollback blocked by Git's index lock says so instead of a generic error by @shivamhwp in pingdotgg/t3code#11340
* fix(mobile): expanded tool-call groups keep following new calls by @nekohasekai in pingdotgg/t3code#15747
* fix(web): going back in the command palette keeps the search that led there by @saphid in pingdotgg/t3code#15940
* fix(web): changing a project's model no longer keeps the old model's options by @yaacovcorcos in pingdotgg/t3code#16581
* fix(web): preserve snapshot thumbnail context and detail by @maria-rcks in pingdotgg/t3code#18440
* fix(web): keep expanded tool actions usable from the keyboard by @saphid in pingdotgg/t3code#18831
* fix(usage): Claude usage no longer lists a `<synthetic>` model by @tris203 in pingdotgg/t3code#14672
* fix(server): release webhook claims when acceptance fails by @saphid in pingdotgg/t3code#18820
* fix(desktop): make the annotation editor border and shadow actually render by @PollyGlot in pingdotgg/t3code#9406
* fix(server): Claude follow-ups no longer fail in Auto on models without Auto by @Gigioxx in pingdotgg/t3code#15687
* fix(web): reopening Connections picks up new network addresses by @lnieuwenhuis in pingdotgg/t3code#15840
* fix(client): MCP apps can no longer trap you in full screen; it opens only after a tap by @shivamhwp in pingdotgg/t3code#18548
* fix(web,mobile): disabled provider instances no longer badge their siblings by @tris203 in pingdotgg/t3code#14545
* fix(web): threads open at the newest message, not thousands of pixels above it by @t3dotgg in pingdotgg/t3code#19663
* fix(mobile): report rejected shared settings writes by @juliusmarminge in pingdotgg/t3code#9356
* fix(claude): show automatic compaction while it runs by @maria-rcks in pingdotgg/t3code#15631
* fix(web): keep the parent thread highlighted while viewing its subagent by @saphid in pingdotgg/t3code#15163
* fix(web): show pull request checkout error detail by @saphid in pingdotgg/t3code#15007
* fix(server): mark unvisited thread completions unread by @maria-rcks in pingdotgg/t3code#15607
* fix(web): started threads no longer offer a machine picker that does nothing by @tris203 in pingdotgg/t3code#19900
* fix(web): provider model names no longer get cut off by their slug by @ilyaliao in pingdotgg/t3code#16522
* fix(claude): mid-sentence skill chips keep the full request by @ScottN-PV in pingdotgg/t3code#15253
* fix(web): preserve unsaved keybinding edits when saving another binding by @pnupu in pingdotgg/t3code#11109
* fix(connections): retry unsupported saved direct connections by @none23 in pingdotgg/t3code#15107
* fix(web): show readable messages for structured thread errors by @juliusmarminge in pingdotgg/t3code#21483
* fix(web): custom shortcuts work when Local environment is off by @Mnigos in pingdotgg/t3code#15825
* fix(web): keep thread notification tags within the Windows toast limit by @satyalyadav in pingdotgg/t3code#12289
* fix(web): pinned thread marker stays put when hovering the row by @flamboh in pingdotgg/t3code#11122
* fix(web): keep a typed question answer when you open a new thread by @Gigioxx in pingdotgg/t3code#13865
* fix(web): renumber following items when continuing a plain-Markdown numbered list by @saphid in pingdotgg/t3code#14332
* fix(web): clicking a logged request route no longer opens it in the editor by @lnieuwenhuis in pingdotgg/t3code#15838
* fix(desktop): reject offscreen annotation screenshot crops by @maria-rcks in pingdotgg/t3code#18441
* fix(web): NVDA browse mode reaches the new-thread project picker again by @akj in pingdotgg/t3code#17877
* fix(web): stop composer banner glass overlap by @t3-code[bot] in pingdotgg/t3code#8034
* fix(web): keep pasted decorators as text by @Gigioxx in pingdotgg/t3code#8415
* fix(shell): avoid interactive job control in environment probes by @LouisDeconinck in pingdotgg/t3code#11275
* fix(web): a closed proactive diff stays closed when you return to a thread by @ilyaliao in pingdotgg/t3code#14705
* fix(web): render powerline separators at cell edges by @SadriG91 in pingdotgg/t3code#5607
* fix(server): provider failures say why a turn could not start by @saphid in pingdotgg/t3code#16303

## New Contributors
* @Atharvsinh-codez made their first contribution in pingdotgg/t3code#20175
* @lbgos made their first contribution in pingdotgg/t3code#16926
* @yaacovcorcos made their first contribution in pingdotgg/t3code#16581
* @pnupu made their first contribution in pingdotgg/t3code#11109
* @LouisDeconinck made their first contribution in pingdotgg/t3code#11275
* @SadriG91 made their first contribution in pingdotgg/t3code#5607

**Full Changelog**: pingdotgg/t3code@v0.1.1-nightly.20261019.3360...v0.1.1-nightly.20261019.3373

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.1.1-nightly.20261019.3373
github-actions Bot added a commit to davidvanderklay/t3code-flake that referenced this pull request Oct 19, 2026
## What's Changed
* fix(mobile): settings no longer tell you to update when you're up to date by @shivamhwp in pingdotgg/t3code#21688
* test(web): fix the workflow script test that times out on busy CI runners by @shivamhwp in pingdotgg/t3code#21699
* fix(mobile): a file shared into a new task shows in the composer before you send by @shivamhwp in pingdotgg/t3code#21659
* fix(desktop): a cold WSL distro gets 30 seconds to boot instead of 10 by @SunkenInTime in pingdotgg/t3code#21070
* fix(web): detect software keyboard before handling composer Enter by @Yash-Singh1 in pingdotgg/t3code#21763
* fix(mobile): the Git sheet uses the standard list rows by @juliusmarminge in pingdotgg/t3code#21785
* fix(server): changed files keep their real paths for renames and non-ASCII names by @Atharvsinh-codez in pingdotgg/t3code#20175
* fix(server): a message promoted into a stopping run stays queued by @lbgos in pingdotgg/t3code#16926
* perf(mobile): streaming re-renders less on the open thread screen by @juliusmarminge in pingdotgg/t3code#20963
* feat(usage): show even-pace marks on Limits bars by @flamboh in pingdotgg/t3code#14477
* fix(web): Usage hourly labels follow the Time format setting by @mInrOz in pingdotgg/t3code#15575
* fix(web): stop repeating the subagent name in the waiting banner by @saphid in pingdotgg/t3code#16022
* fix(web): Cmd+O no longer opens the editor more than once by @5knnbdwm in pingdotgg/t3code#18983
* fix(web): hoist favorited legacy models to the top of the model picker by @TonybynMp4 in pingdotgg/t3code#11933
* fix(server): a rollback blocked by Git's index lock says so instead of a generic error by @shivamhwp in pingdotgg/t3code#11340
* fix(mobile): expanded tool-call groups keep following new calls by @nekohasekai in pingdotgg/t3code#15747
* fix(web): going back in the command palette keeps the search that led there by @saphid in pingdotgg/t3code#15940
* fix(web): changing a project's model no longer keeps the old model's options by @yaacovcorcos in pingdotgg/t3code#16581
* fix(web): preserve snapshot thumbnail context and detail by @maria-rcks in pingdotgg/t3code#18440
* fix(web): keep expanded tool actions usable from the keyboard by @saphid in pingdotgg/t3code#18831
* fix(usage): Claude usage no longer lists a `<synthetic>` model by @tris203 in pingdotgg/t3code#14672
* fix(server): release webhook claims when acceptance fails by @saphid in pingdotgg/t3code#18820
* fix(desktop): make the annotation editor border and shadow actually render by @PollyGlot in pingdotgg/t3code#9406
* fix(server): Claude follow-ups no longer fail in Auto on models without Auto by @Gigioxx in pingdotgg/t3code#15687
* fix(web): reopening Connections picks up new network addresses by @lnieuwenhuis in pingdotgg/t3code#15840
* fix(client): MCP apps can no longer trap you in full screen; it opens only after a tap by @shivamhwp in pingdotgg/t3code#18548
* fix(web,mobile): disabled provider instances no longer badge their siblings by @tris203 in pingdotgg/t3code#14545
* fix(web): threads open at the newest message, not thousands of pixels above it by @t3dotgg in pingdotgg/t3code#19663
* fix(mobile): report rejected shared settings writes by @juliusmarminge in pingdotgg/t3code#9356
* fix(claude): show automatic compaction while it runs by @maria-rcks in pingdotgg/t3code#15631
* fix(web): keep the parent thread highlighted while viewing its subagent by @saphid in pingdotgg/t3code#15163
* fix(web): show pull request checkout error detail by @saphid in pingdotgg/t3code#15007
* fix(server): mark unvisited thread completions unread by @maria-rcks in pingdotgg/t3code#15607
* fix(web): started threads no longer offer a machine picker that does nothing by @tris203 in pingdotgg/t3code#19900
* fix(web): provider model names no longer get cut off by their slug by @ilyaliao in pingdotgg/t3code#16522
* fix(claude): mid-sentence skill chips keep the full request by @ScottN-PV in pingdotgg/t3code#15253
* fix(web): preserve unsaved keybinding edits when saving another binding by @pnupu in pingdotgg/t3code#11109
* fix(connections): retry unsupported saved direct connections by @none23 in pingdotgg/t3code#15107
* fix(web): show readable messages for structured thread errors by @juliusmarminge in pingdotgg/t3code#21483
* fix(web): custom shortcuts work when Local environment is off by @Mnigos in pingdotgg/t3code#15825
* fix(web): keep thread notification tags within the Windows toast limit by @satyalyadav in pingdotgg/t3code#12289
* fix(web): pinned thread marker stays put when hovering the row by @flamboh in pingdotgg/t3code#11122
* fix(web): keep a typed question answer when you open a new thread by @Gigioxx in pingdotgg/t3code#13865
* fix(web): renumber following items when continuing a plain-Markdown numbered list by @saphid in pingdotgg/t3code#14332
* fix(web): clicking a logged request route no longer opens it in the editor by @lnieuwenhuis in pingdotgg/t3code#15838
* fix(desktop): reject offscreen annotation screenshot crops by @maria-rcks in pingdotgg/t3code#18441
* fix(web): NVDA browse mode reaches the new-thread project picker again by @akj in pingdotgg/t3code#17877
* fix(web): stop composer banner glass overlap by @t3-code[bot] in pingdotgg/t3code#8034
* fix(web): keep pasted decorators as text by @Gigioxx in pingdotgg/t3code#8415
* fix(shell): avoid interactive job control in environment probes by @LouisDeconinck in pingdotgg/t3code#11275
* fix(web): a closed proactive diff stays closed when you return to a thread by @ilyaliao in pingdotgg/t3code#14705
* fix(web): render powerline separators at cell edges by @SadriG91 in pingdotgg/t3code#5607
* fix(server): provider failures say why a turn could not start by @saphid in pingdotgg/t3code#16303

## New Contributors
* @Atharvsinh-codez made their first contribution in pingdotgg/t3code#20175
* @lbgos made their first contribution in pingdotgg/t3code#16926
* @yaacovcorcos made their first contribution in pingdotgg/t3code#16581
* @pnupu made their first contribution in pingdotgg/t3code#11109
* @LouisDeconinck made their first contribution in pingdotgg/t3code#11275
* @SadriG91 made their first contribution in pingdotgg/t3code#5607

**Full Changelog**: pingdotgg/t3code@v0.1.1-nightly.20261019.3360...v0.1.1-nightly.20261019.3373

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.1.1-nightly.20261019.3373
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:S 10-29 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Claude usage lists a <synthetic> model with no explanation

2 participants