Skip to content

fix(claude): dedupe sidechain replayed usage#1155

Merged
ryoppippi merged 3 commits into
mainfrom
codex/fix-claude-sidechain-costs
May 25, 2026
Merged

fix(claude): dedupe sidechain replayed usage#1155
ryoppippi merged 3 commits into
mainfrom
codex/fix-claude-sidechain-costs

Conversation

@ryoppippi
Copy link
Copy Markdown
Owner

@ryoppippi ryoppippi commented May 25, 2026

Summary

Fixes Claude Code /btw sidechain overcounting by tracking isSidechain metadata and deduping replayed parent messages by message id. This prevents sidechain logs from re-counting the parent conversation history when Claude writes the same assistant message with a different request id, while still counting distinct sidechain responses.

Testing

  • env -u CFLAGS -u CPPFLAGS NIX_CONFIG="access-tokens = github.com=$(gh auth token)" nix develop --command cargo test -p ccusage adapter::claude:: --manifest-path rust/Cargo.toml
  • env -u CFLAGS -u CPPFLAGS NIX_CONFIG="access-tokens = github.com=$(gh auth token)" nix develop --command pnpm run test
  • env -u CFLAGS -u CPPFLAGS NIX_CONFIG="access-tokens = github.com=$(gh auth token)" nix develop --command pnpm typecheck

Fixes #913.

@coderabbitai review


Summary by cubic

Fixes sidechain overcounting in Claude Code /btw by tracking is_sidechain and preferring the parent when a sidechain replays a message with a new request_id, and documents the behavior. Applies to usage logs and daily AgentProgress. Fixes #913.

  • Bug Fixes
    • Added is_sidechain to UsageEntry; propagated through Claude loaders and daily AgentProgress; other adapters default to None.
    • Updated dedupe to check both (message_id, request_id) and message-only; keep non-sidechain parent when a sidechain replays; otherwise replace by higher tokens/cost or presence of speed.
    • Applied the same logic to daily summaries; added regression tests for entry loading and daily paths; documented sidechain dedupe in the Claude adapter README.

Written for commit 04599a8. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • Added sidechain metadata to usage records so entries explicitly indicate sidechain provenance.
  • Bug Fixes

    • Improved deduplication to handle message replays with different identifiers and to prefer/retain parent vs. sidechain answers, improving token/cost attribution.
  • Documentation

    • Added guidance describing sidechain entries and how deduplication treats them.
  • Tests

    • Updated and added tests to validate sidechain metadata propagation and dedupe behavior.

Review Change Stack

Track Claude Code isSidechain metadata on usage entries so /btw sidechain logs can be distinguished from parent session logs.

When a sidechain file replays an existing assistant message with a new request id, dedupe it by message id without replacing the original parent usage. This prevents ccusage from counting the replayed cache-read history as fresh spend while still preserving distinct sidechain responses.

Adds regression coverage for both entry loading and daily summary dedupe paths. Fixes #913.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4115f32b-f7ad-4c6f-b0aa-62f53771be0d

📥 Commits

Reviewing files that changed from the base of the PR and between b5b27d2 and 04599a8.

📒 Files selected for processing (3)
  • rust/crates/ccusage/src/adapter/claude/README.md
  • rust/crates/ccusage/src/adapter/claude/daily.rs
  • rust/crates/ccusage/src/adapter/claude/mod.rs
✅ Files skipped from review due to trivial changes (1)
  • rust/crates/ccusage/src/adapter/claude/README.md

📝 Walkthrough

Walkthrough

Adds is_sidechain: Option<bool> to UsageEntry; threads sidechain provenance through Claude daily parsing and main dedupe logic with exact and message-only fallbacks and sidechain-aware replacement; initializes the new field in all adapters and updates tests to include it.

Changes

Sidechain usage tracking and deduplication

Layer / File(s) Summary
Core type definition: is_sidechain field
src/types.rs
UsageEntry gains an optional is_sidechain field (serialized as isSidechain).
Claude daily adapter: sidechain-aware deduplication refactor
src/adapter/claude/daily.rs
DailyLoadedEntry and DailyUsageEntry carry is_sidechain; DailyUsageLine::into_entry propagates agent-progress is_sidechain; read_daily_usage_file stores it; push_deduped_daily_entry refactored to exact (message_id, request_id) then message-only fallback with sidechain-aware matching; replacement/indexing logic moved into helpers; unit tests added.
Claude main adapter: sidechain-aware deduplication refactor
src/adapter/claude/mod.rs
should_replace_deduped_entry checks sidechain status first; push_deduped_entry uses exact-hash then message-only fallback with sidechain-aware predicates; dedupe index now records exact + message-only mappings and avoids duplicates; helpers and a unit test added.
Adapter updates: is_sidechain initialization across providers
src/adapter/amp/parser.rs, src/adapter/codebuff/loader.rs, src/adapter/copilot/loader.rs, src/adapter/droid/loader.rs, src/adapter/gemini/parser.rs, src/adapter/goose/parser.rs, src/adapter/hermes/parser.rs, src/adapter/kilo/parser.rs, src/adapter/kimi/parser.rs, src/adapter/openclaw/parser.rs, src/adapter/opencode/parser.rs, src/adapter/pi/parser.rs, src/adapter/qwen/parser.rs
All adapters now set is_sidechain: None when constructing UsageEntry records during parsing/loading.
Test fixture updates: is_sidechain field propagation
src/adapter/codebuff/loader.rs, src/adapter/droid/loader.rs, src/adapter/goose/report.rs, src/adapter/hermes/report.rs, src/adapter/qwen/parser.rs, src/main.rs, src/summary.rs
Test helpers and fixtures updated to include is_sidechain: None in constructed LoadedEntry/UsageEntry test data.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

"🐰
I sniffed the logs and hopped around,
Marked sidechains without a sound.
Parent stays, kids kept light,
Deduped fairly—hop and bite! 🥕"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.58% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(claude): dedupe sidechain replayed usage' accurately summarizes the main change: implementing deduplication logic for Claude's sidechain-replayed usage entries to prevent overcounting.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-claude-sidechain-costs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@ryoppippi
Copy link
Copy Markdown
Owner Author

@coderabbitai review

Initial push for #1155 is ready for review.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 25, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ccusage-guide 04599a8 Commit Preview URL

Branch Preview URL
May 25 2026, 07:06 PM

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

Tip

For best results, initiate chat on the files or code changes.

PR Review: fix(claude): dedupe sidechain replayed usage

The approach is sound: indexing each new entry under both its exact (message_id, request_id) hash and a message-only (message_id, None) hash, then using the latter as a fallback when at least one party carries is_sidechain = true, cleanly solves the overcounting without touching non-Claude adapters.


🔍 Logic correctness

should_replace_deduped_entry / should_replace_deduped_daily_entry

The new sidechain guard:

if candidate_is_sidechain != existing_is_sidechain {
    return existing_is_sidechain;
}

Covers both orderings correctly:

candidate existing returns effect
parent sidechain replay true replace sidechain with parent ✓
sidechain replay parent false keep parent ✓

loaded_entry_matches_sidechain_dedupe_key

entry.data.message.id.as_deref() == Some(message_id)
    && (candidate_is_sidechain || is_sidechain_usage_entry(&entry.data))

The || condition ensures cross-request-id dedup only fires when at least one party is known to be a sidechain. This is appropriately conservative — for older logs where isSidechain was never written, neither side will be flagged and the fallback path will not trigger, avoiding false deduplication.


⚠️ Potential gap: DailyUsageLine::load hardcodes is_sidechain: None

// daily.rs, impl DailyUsageLine
DailyLoadedEntry {
    ...
    is_sidechain: None,  // <-- hardcoded
}

read_daily_usage_file correctly propagates data.is_sidechain, but DailyUsageLine::load (a separate deserialization path) always emits None. If any daily-summary file written through the DailyUsageLine format can carry isSidechain: true, those entries will be treated as non-sidechain and the cross-request-id dedup won't fire for them.

Could you confirm whether sidechain metadata can appear in the DailyUsageLine format, or add a short comment explaining why None is safe here?


🔍 Minor: O(n) contains in push_deduped_index

fn push_deduped_index(deduped_indexes: &mut FxHashMap<u64, SmallIndexVec>, hash: u64, index: usize) {
    let indexes = deduped_indexes.entry(hash).or_default();
    if !indexes.contains(&index) {   // linear scan
        indexes.push(index);
    }
}

SmallIndexVec is presumably a SmallVec, so this is fine in practice since the number of entries sharing a message-only hash is small (typically ≤ 2: one parent + one sidechain replay). Not a bug — just flagging in case SmallIndexVec ever grows.


✅ What's well done

  • Symmetric implementation between mod.rs (per-entry) and daily.rs (daily summary) — no risk of the two paths diverging.
  • Regression tests with realistic fixture data covering the exact scenario from #913 (parent entry survives with original token counts; sidechain replay is dropped; sidechain answer with a distinct message_id is kept separately).
  • Non-Claude adapters all updated to set is_sidechain: None — struct exhaustiveness is maintained.
  • Conservative by default — absence of isSidechain metadata doesn't cause false deduplication.

Summary: One gap worth clarifying (DailyUsageLine hardcoded None), otherwise the implementation is clean and the tests are solid.

Propagate isSidechain from Claude AgentProgress lines into the daily summary path instead of dropping it during normalization.

This closes the CodeRabbit review gap and keeps the sidechain dedupe behaviour consistent for both direct and AgentProgress daily records.
@ryoppippi
Copy link
Copy Markdown
Owner Author

@coderabbitai review

Pushed b5b27d2 to address your note: Daily AgentProgress normalization now propagates isSidechain, with a regression test covering that path.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 20 files

Re-trigger cubic

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

@ryoppippi The fix is correct. DailyAgentProgressMessage carries #[serde(rename_all = "camelCase")] (Line 169), so is_sidechainisSidechain resolves cleanly without any extra rename attribute — consistent with how the rest of the struct fields are handled (with cost_usd getting its own explicit override only because camelCase would give costUsd, not costUSD).

The propagation chain is now complete end-to-end:

  • JSON isSidechainDailyAgentProgressMessage.is_sidechain
  • DailyLoadedEntry.is_sidechain via into_entry()
  • → sidechain dedupe logic fires correctly for AgentProgress daily records ✓
  • Regression test covers the path ✓

The original concern is fully addressed. The implementation is solid — happy to approve.

🐇 ✨

✅ Actions performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 25, 2026

Open in StackBlitz

ccusage

npx https://pkg.pr.new/ryoppippi/ccusage@1155

@ccusage/ccusage-darwin-arm64

npx https://pkg.pr.new/ryoppippi/ccusage/@ccusage/ccusage-darwin-arm64@1155

@ccusage/ccusage-darwin-x64

npx https://pkg.pr.new/ryoppippi/ccusage/@ccusage/ccusage-darwin-x64@1155

@ccusage/ccusage-linux-arm64

npx https://pkg.pr.new/ryoppippi/ccusage/@ccusage/ccusage-linux-arm64@1155

@ccusage/ccusage-linux-x64

npx https://pkg.pr.new/ryoppippi/ccusage/@ccusage/ccusage-linux-x64@1155

@ccusage/ccusage-win32-arm64

npx https://pkg.pr.new/ryoppippi/ccusage/@ccusage/ccusage-win32-arm64@1155

@ccusage/ccusage-win32-x64

npx https://pkg.pr.new/ryoppippi/ccusage/@ccusage/ccusage-win32-x64@1155

commit: 04599a8

Document Claude Code /btw side question logs, the isSidechain field used by ccusage, and issue #913 as the motivation for sidechain replay deduplication.

Add short comments at the message-only fallback so the daily and full Claude loaders explain why sidechain duplicates can match by message ID when request IDs differ.
@ryoppippi
Copy link
Copy Markdown
Owner Author

@coderabbitai review

Pushed 04599a8 with Claude adapter README context for #913, the Claude Code /btw documentation link, and short comments explaining the sidechain message-ID fallback.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

@ryoppippi The documentation commit looks great — no issues.

README.md — The new "Sidechain entries" section is accurate and well-placed:

  • Source (subagents/, /btw aside_question), replay mechanism (same message ID, new request ID, parent cache-read usage), dedupe outcome (parent kept, replay dropped, distinct sidechain responses still counted), and the #913 backlink are all correctly stated and match the implementation.

Inline comments (daily.rs / mod.rs) — // /btw sidechain logs can replay parent messages with new request IDs. is exactly the right level of commentary: one line, placed right above the fallback path, explains the why without restating the code.

The PR is in excellent shape across all three commits. Marking all comments resolved.

✅ Actions performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

@github-actions
Copy link
Copy Markdown

ccusage performance comparison

PR SHA: 909fb98be3c8
Base SHA: bf84d4bc1ce8

This compares the PR package against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new bf84d4bc1ce8 1.356s 674.5ms 31.0ms 3
PR pkg.pr.new 909fb98be3c8 489.7ms 608.8ms 31.4ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: bf84d4bc1ce8; PR package: 909fb98be3c8. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 491.1ms 553.7ms 0.89x 248.58 MiB 292.83 MiB 1.18x 2.05 GiB/s 1.82 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 350.3ms 352.2ms 0.99x 57.45 MiB 58.45 MiB 1.02x 2.87 GiB/s 2.86 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 536.0ms 1.88 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 495.7ms 2.03 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 352.0ms 2.86 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 321.9ms 3.13 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 29.2ms 28.8ms 1.01x 43.61 MiB 43.61 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
claude session --offline --json 0.00 MiB 29.2ms 29.0ms 1.01x 43.48 MiB 43.61 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
codex daily --offline --json 0.00 MiB 29.1ms 29.2ms 0.99x 43.48 MiB 43.73 MiB 1.01x 0.03 MiB/s 0.03 MiB/s
codex session --offline --json 0.00 MiB 28.9ms 28.4ms 1.02x 43.61 MiB 43.61 MiB 1.00x 0.03 MiB/s 0.03 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 497.4ms 538.5ms 0.92x 268.20 MiB 298.20 MiB 1.11x 2.02 GiB/s 1.87 GiB/s
codex --offline --json 1.01 GiB 343.1ms 352.8ms 0.97x 59.45 MiB 59.08 MiB 0.99x 2.93 GiB/s 2.85 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB +0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@github-actions
Copy link
Copy Markdown

ccusage performance comparison

PR SHA: 909fb98be3c8
Base SHA: bf84d4bc1ce8

This compares the Rust PR release binary against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new bf84d4bc1ce8 705.0ms 465.3ms 31.9ms 3
PR pkg.pr.new 909fb98be3c8 546.4ms 452.3ms 32.4ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: bf84d4bc1ce8; PR package: 909fb98be3c8. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 489.0ms 545.3ms 0.90x 262.58 MiB 306.95 MiB 1.17x 2.06 GiB/s 1.85 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 353.9ms 351.6ms 1.01x 63.45 MiB 59.45 MiB 0.94x 2.84 GiB/s 2.86 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 534.0ms 1.89 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 515.3ms 1.95 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 348.4ms 2.89 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 326.9ms 3.08 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 28.6ms 3.9ms 7.39x 43.73 MiB 2.83 MiB 0.06x 0.05 MiB/s 0.40 MiB/s
claude session --offline --json 0.00 MiB 28.8ms 3.8ms 7.50x 43.61 MiB 2.83 MiB 0.06x 0.05 MiB/s 0.40 MiB/s
codex daily --offline --json 0.00 MiB 28.7ms 3.7ms 7.83x 43.61 MiB 2.83 MiB 0.06x 0.03 MiB/s 0.23 MiB/s
codex session --offline --json 0.00 MiB 29.5ms 3.6ms 8.19x 43.61 MiB 2.83 MiB 0.06x 0.03 MiB/s 0.24 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 476.5ms 505.2ms 0.94x 262.45 MiB 309.58 MiB 1.18x 2.11 GiB/s 1.99 GiB/s
codex --offline --json 1.01 GiB 347.3ms 316.6ms 1.10x 55.20 MiB 64.08 MiB 1.16x 2.90 GiB/s 3.18 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB +0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@github-actions
Copy link
Copy Markdown

ccusage performance comparison

PR SHA: b5b27d204cf1
Base SHA: bf84d4bc1ce8

This compares the Rust PR release binary against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new bf84d4bc1ce8 900.5ms 632.3ms 32.8ms 3
PR pkg.pr.new b5b27d204cf1 489.4ms 479.9ms 33.1ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: bf84d4bc1ce8; PR package: b5b27d204cf1. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 497.3ms 579.6ms 0.86x 282.95 MiB 295.58 MiB 1.04x 2.02 GiB/s 1.74 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 355.9ms 364.0ms 0.98x 65.33 MiB 55.58 MiB 0.85x 2.83 GiB/s 2.77 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 527.6ms 1.91 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 510.3ms 1.97 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 359.5ms 2.80 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 334.4ms 3.01 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 29.6ms 3.8ms 7.86x - 2.83 MiB - 0.05 MiB/s 0.41 MiB/s
claude session --offline --json 0.00 MiB 29.5ms 3.9ms 7.59x 43.73 MiB 2.83 MiB 0.06x 0.05 MiB/s 0.40 MiB/s
codex daily --offline --json 0.00 MiB 29.4ms 3.7ms 8.04x 43.48 MiB 2.83 MiB 0.07x 0.03 MiB/s 0.23 MiB/s
codex session --offline --json 0.00 MiB 29.2ms 3.7ms 7.98x 43.61 MiB 2.83 MiB 0.06x 0.03 MiB/s 0.23 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 485.0ms 509.4ms 0.95x 267.45 MiB 290.58 MiB 1.09x 2.08 GiB/s 1.98 GiB/s
codex --offline --json 1.01 GiB 349.3ms 328.9ms 1.06x 50.95 MiB 59.45 MiB 1.17x 2.88 GiB/s 3.06 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB -0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@github-actions
Copy link
Copy Markdown

ccusage performance comparison

PR SHA: b5b27d204cf1
Base SHA: bf84d4bc1ce8

This compares the PR package against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new bf84d4bc1ce8 576.9ms 485.7ms 34.1ms 3
PR pkg.pr.new b5b27d204cf1 640.2ms 433.8ms 34.2ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: bf84d4bc1ce8; PR package: b5b27d204cf1. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 505.1ms 569.8ms 0.89x 303.58 MiB 291.70 MiB 0.96x 1.99 GiB/s 1.77 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 371.1ms 374.1ms 0.99x 63.83 MiB 50.70 MiB 0.79x 2.71 GiB/s 2.69 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 549.7ms 1.83 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 519.0ms 1.94 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 405.7ms 2.48 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 337.2ms 2.99 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 31.1ms 30.9ms 1.01x 43.73 MiB 43.48 MiB 0.99x 0.05 MiB/s 0.05 MiB/s
claude session --offline --json 0.00 MiB 31.3ms 31.5ms 0.99x 43.48 MiB 43.48 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
codex daily --offline --json 0.00 MiB 30.9ms 31.4ms 0.98x 43.61 MiB 43.48 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
codex session --offline --json 0.00 MiB 30.8ms 30.7ms 1.00x 43.73 MiB 43.48 MiB 0.99x 0.03 MiB/s 0.03 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 485.7ms 563.7ms 0.86x 255.33 MiB 301.33 MiB 1.18x 2.07 GiB/s 1.79 GiB/s
codex --offline --json 1.01 GiB 357.0ms 361.9ms 0.99x 62.95 MiB 66.08 MiB 1.05x 2.82 GiB/s 2.78 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB -0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@github-actions
Copy link
Copy Markdown

ccusage performance comparison

PR SHA: 04599a8330e5
Base SHA: bf84d4bc1ce8

This compares the Rust PR release binary against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new bf84d4bc1ce8 588.5ms 427.9ms 35.9ms 3
PR pkg.pr.new 04599a8330e5 472.0ms 511.8ms 35.3ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: bf84d4bc1ce8; PR package: 04599a8330e5. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 500.4ms 567.7ms 0.88x 270.20 MiB 299.33 MiB 1.11x 2.01 GiB/s 1.77 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 364.2ms 373.7ms 0.97x 51.58 MiB 53.45 MiB 1.04x 2.76 GiB/s 2.69 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 573.8ms 1.75 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 527.7ms 1.91 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 363.0ms 2.77 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 334.6ms 3.01 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 32.0ms 4.3ms 7.41x 43.36 MiB 2.83 MiB 0.07x 0.05 MiB/s 0.36 MiB/s
claude session --offline --json 0.00 MiB 32.7ms 4.3ms 7.56x 43.48 MiB 2.83 MiB 0.07x 0.05 MiB/s 0.36 MiB/s
codex daily --offline --json 0.00 MiB 32.1ms 4.1ms 7.84x 43.48 MiB 2.83 MiB 0.07x 0.03 MiB/s 0.21 MiB/s
codex session --offline --json 0.00 MiB 31.9ms 4.1ms 7.86x 43.48 MiB 2.83 MiB 0.07x 0.03 MiB/s 0.21 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 494.8ms 536.1ms 0.92x 259.20 MiB 305.58 MiB 1.18x 2.03 GiB/s 1.88 GiB/s
codex --offline --json 1.01 GiB 358.4ms 336.4ms 1.07x 60.70 MiB 51.45 MiB 0.85x 2.81 GiB/s 2.99 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB -0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@github-actions
Copy link
Copy Markdown

ccusage performance comparison

PR SHA: 04599a8330e5
Base SHA: bf84d4bc1ce8

This compares the PR package against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new bf84d4bc1ce8 496.6ms 849.9ms 36.4ms 3
PR pkg.pr.new 04599a8330e5 540.2ms 706.9ms 35.6ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: bf84d4bc1ce8; PR package: 04599a8330e5. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 522.4ms 576.1ms 0.91x 269.20 MiB 303.20 MiB 1.13x 1.93 GiB/s 1.75 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 364.9ms 370.8ms 0.98x 63.33 MiB 61.33 MiB 0.97x 2.76 GiB/s 2.71 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 578.6ms 1.74 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 549.4ms 1.83 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 371.1ms 2.71 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 345.8ms 2.91 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 32.4ms 32.1ms 1.01x 43.48 MiB 43.61 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
claude session --offline --json 0.00 MiB 32.3ms 32.0ms 1.01x 43.48 MiB 43.48 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
codex daily --offline --json 0.00 MiB 31.7ms 32.3ms 0.98x 43.48 MiB 43.48 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
codex session --offline --json 0.00 MiB 32.4ms 32.7ms 0.99x 43.48 MiB - - 0.03 MiB/s 0.03 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 494.0ms 556.3ms 0.89x - - - 2.04 GiB/s 1.81 GiB/s
codex --offline --json 1.01 GiB 357.7ms 359.3ms 1.00x 51.70 MiB 51.83 MiB 1.00x 2.81 GiB/s 2.80 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB -0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@ryoppippi ryoppippi merged commit cb26b5c into main May 25, 2026
40 checks passed
@ryoppippi ryoppippi deleted the codex/fix-claude-sidechain-costs branch May 25, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Are Claude Code /btw (aside_question) sidechain costs real or over-counted?

1 participant