Skip to content

build(perf): migrate benchmark harness to Babashka - #1432

Merged
ryoppippi merged 7 commits into
mainfrom
codex/migrate-performance-harness-to-babashka
Jul 12, 2026
Merged

build(perf): migrate benchmark harness to Babashka#1432
ryoppippi merged 7 commits into
mainfrom
codex/migrate-performance-harness-to-babashka

Conversation

@ryoppippi

@ryoppippi ryoppippi commented Jul 12, 2026

Copy link
Copy Markdown
Member

Summary

Migrate the PR performance benchmark harness from Nushell to Babashka after parity testing showed the data-heavy reporting flow was substantially smaller and easier to test. The implementation is split into focused modules under compare_pr_performance/, while executable entry points keep their Nix dependencies self-contained.

What Changed

  • replace the 1,053-line Nushell harness with a 17-line entry point and focused Babashka modules
  • preserve package acquisition, hyperfine, memory, artifact-size, progress, fallback, and Markdown behavior
  • add 34 focused assertions for CLI, formatting, command quoting, measurement normalization, fallback, and rendering
  • migrate the CI caller and profiling guidance
  • document repository language-selection guidance

Testing

  • just ccusage::test-performance-harness
  • apps/ccusage/scripts/compare-pr-performance.bb --help
  • lightweight committed-fixture parity runs with and without RSS measurement
  • unavailable package URL, invalid runtime, missing fixture, and child-command failure checks
  • just typecheck
  • just test
  • just check

View with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is enabled.


Summary by cubic

Migrated the PR performance benchmark harness from Nushell to Babashka. CI and docs now use the .bb entry, run the harness tests, and reports stay complete via local sizing fallbacks when preview packages aren’t ready.

  • Refactors

    • Replaced the 1,053-line Nushell script with a 17-line Babashka entry and small modules for data, system, benchmark, report, and orchestration.
  • Bug Fixes

    • Normalized Windows os.name to win32 so native and package paths resolve correctly.
    • Resolved relative pnpm pack tarball filenames against the temp destination; preserved absolute paths.
    • Sized remote tarballs only after a successful preview install; otherwise size the local checkout.

Written for commit 6c90fc2. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added a Babashka-based PR performance comparison with timing, throughput, peak RSS, runtime diagnostics, and artifact size summaries.
    • CI now runs the Babashka performance harness test after the main Rust/JS checks, and the PR comparison step uses the Babashka script.
    • Added a new justfile recipe to run the performance harness.
  • Bug Fixes
    • Improved CLI validation and more reliable parsing/normalization of benchmark output.
  • Tests
    • Added comprehensive Babashka tests covering parsing, measurements, reporting, and skipped-output rendering.
  • Documentation
    • Updated automation guidance and benchmark instructions to reference the new Babashka script (and removed the prior Nushell script).

Replace the large Nushell PR benchmark script with a Babashka implementation split by data, system, benchmark, report, and orchestration responsibilities. The new process boundary keeps argv, environment, and working-directory data explicit while preserving hyperfine, package installation, memory, size, and Markdown behavior.

Move the CI caller and profiling guidance to the executable Babashka entry point. Add focused tests behind their own Nix shebang so contributors can run the harness suite without adding Babashka to the full development shell.
Route small command-oriented automation to Nushell and data-heavy, testable automation to Babashka. Keep production binaries in Rust and npm-integrated APIs in TypeScript so future tooling changes follow the same criteria used by the benchmark migration.
Copilot AI review requested due to automatic review settings July 12, 2026 11:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai review
@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai review
@cubic-dev-ai review

@ryoppippi I have started the AI code review. It will take a few minutes to complete.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

@ryoppippi I'll review the changes now.

✅ Action performed

Review finished.

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.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR replaces the Nushell performance comparison script with a Babashka implementation split into CLI/data, system, benchmarking, reporting, and orchestration modules. It updates CI and documentation references, adds a just recipe, and introduces focused Babashka tests.

Changes

Performance comparison harness

Layer / File(s) Summary
CLI and system foundation
apps/ccusage/scripts/compare_pr_performance/{data,system}.clj
Adds CLI validation, formatting, measurement helpers, subprocess execution, package installation, binary discovery, and artifact-size utilities.
Benchmark execution
apps/ccusage/scripts/compare_pr_performance/benchmark.clj
Runs hyperfine comparisons, optionally measures peak RSS, aggregates fixture results, and reports runtime diagnostics.
Orchestration and reporting
apps/ccusage/scripts/compare_pr_performance/{main,report}.clj, apps/ccusage/scripts/compare-pr-performance.bb
Adds the Babashka entrypoint, benchmark setup and execution flow, Markdown report generation, and skipped-report handling.
Validation and integration
apps/ccusage/scripts/compare-pr-performance_test.clj, apps/ccusage/justfile, .github/workflows/ci.yaml, AGENTS.md, apps/ccusage/AGENTS.md, .agents/skills/profile/references/rust.md
Adds focused harness tests, a just recipe, updated CI invocation, and updated tooling guidance and script references. The Nushell implementation is removed.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant compare_pr_performance_main
  participant benchmark
  participant report
  participant Output
  CLI->>compare_pr_performance_main: -main arguments
  compare_pr_performance_main->>benchmark: run-benchmark-suites
  benchmark-->>compare_pr_performance_main: measurements and sections
  compare_pr_performance_main->>report: render-report
  report-->>compare_pr_performance_main: Markdown output
  compare_pr_performance_main->>Output: write-output!
Loading

Possibly related PRs

Suggested reviewers: pullfrog

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: migrating the performance benchmark harness to Babashka.
✨ 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/migrate-performance-harness-to-babashka

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.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 12, 2026

Copy link
Copy Markdown

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 6c90fc2 Commit Preview URL

Branch Preview URL
Jul 12 2026, 12:24 PM

Execute the self-contained benchmark harness test entry point in the CI test job so changes to CLI parsing, normalization, fallback decisions, and report rendering cannot bypass pull request validation.
@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai @cubic-dev-ai Added CI execution for the Babashka harness tests in cf46b61. Local validation: 10 tests, 24 assertions passed. Please review the latest commit.

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai @cubic-dev-ai Added CI execution for the Babashka harness tests in cf46b61. Local validation: 10 tests, 24 assertions passed. Please review the latest commit.

@ryoppippi I have started the AI code review. It will take a few minutes to complete.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

@ryoppippi Thanks for the update — I'll review the latest commit (cf46b61) that adds CI execution for the Babashka harness tests now.

✅ Action performed

Review finished.

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.

@pkg-pr-new

pkg-pr-new Bot commented Jul 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

ccusage

npx https://pkg.pr.new/ccusage@1432

@ccusage/ccusage-darwin-arm64

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

@ccusage/ccusage-darwin-x64

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

@ccusage/ccusage-linux-arm64

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

@ccusage/ccusage-linux-x64

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

@ccusage/ccusage-win32-x64

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

commit: 6c90fc2

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 0310c78c0633
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 325.0ms 3.10 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 297.4ms 3.39 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 116.5ms 8.64 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 83.4ms 12.06 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 native ccusage binary 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 25.0ms 3.7ms 6.79x 53.50 MiB 10.45 MiB 0.20x 0.06 MiB/s 0.42 MiB/s
claude session --offline --json 0.00 MiB 27.2ms 2.7ms 10.12x 53.75 MiB 10.45 MiB 0.19x 0.06 MiB/s 0.58 MiB/s
codex daily --offline --json 0.00 MiB 25.0ms 2.1ms 12.14x 53.75 MiB 8.44 MiB 0.16x 0.03 MiB/s 0.42 MiB/s
codex session --offline --json 0.00 MiB 22.6ms 2.1ms 10.81x 53.50 MiB 8.44 MiB 0.16x 0.04 MiB/s 0.41 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published native ccusage binary 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 353.5ms 311.3ms 1.14x 958.59 MiB 960.58 MiB 1.00x 2.85 GiB/s 3.23 GiB/s
codex --offline --json 1.01 GiB 107.4ms 86.2ms 1.25x 427.29 MiB 421.29 MiB 0.99x 9.37 GiB/s 11.69 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.70 KiB -0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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
Contributor

ccusage performance comparison

PR SHA: 0310c78c0633
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 303.3ms 3.32 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 293.1ms 3.43 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 141.3ms 7.12 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 97.3ms 10.35 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 27.7ms 30.1ms 0.92x 54.00 MiB 53.75 MiB 1.00x 0.06 MiB/s 0.05 MiB/s
claude session --offline --json 0.00 MiB 30.5ms 27.4ms 1.11x 53.75 MiB 53.75 MiB 1.00x 0.05 MiB/s 0.06 MiB/s
codex daily --offline --json 0.00 MiB 29.5ms 26.2ms 1.13x 53.75 MiB 53.75 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
codex session --offline --json 0.00 MiB 26.1ms 26.9ms 0.97x 54.25 MiB 54.00 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 343.8ms 318.2ms 1.08x 938.58 MiB 964.58 MiB 1.03x 2.93 GiB/s 3.16 GiB/s
codex --offline --json 1.01 GiB 115.8ms 113.1ms 1.02x 413.29 MiB 417.29 MiB 1.01x 8.70 GiB/s 8.90 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.70 KiB -0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/ccusage/scripts/compare_pr_performance/benchmark.clj`:
- Around line 21-38: Update the unsupported-platform branch in measure-memory so
it writes a warning with write-progress and returns nil instead of calling
fail!. Warn once before or outside the per-sample keep iteration when
timed-command cannot produce an argv, then skip memory measurement gracefully
while preserving the existing non-zero-exit and parse-error handling.

In `@apps/ccusage/scripts/compare_pr_performance/system.clj`:
- Around line 1-9: Update run-process to accept and enforce a cancellable
timeout, terminating the underlying process and returning a timeout result when
it expires so all callers remain bounded by --package-runner-timeout-ms. Pass
that timeout through the package URL, install, packing, and git revision flows,
and configure the curl probe with explicit connection and read limits.
- Around line 19-20: Update platform-name to recognize os.name values beginning
with “Windows” (including version-qualified values such as Windows 10 and
Windows 11) and return “win32”; preserve the existing Mac OS X and Linux
mappings and lowercase fallback for other platforms.
- Around line 93-110: The packed tarball filename from `packed-tarball-size` is
relative to the temporary destination, but it is currently passed directly to
`optional-file-size`. Join `destination` with `filename` before sizing the file,
preserving the existing missing-file handling and cleanup behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0f1cf3a0-401b-44ed-9af7-6039dd3c3471

📥 Commits

Reviewing files that changed from the base of the PR and between 997ad7f and 0310c78.

📒 Files selected for processing (13)
  • .agents/skills/profile/references/rust.md
  • .github/workflows/ci.yaml
  • AGENTS.md
  • apps/ccusage/AGENTS.md
  • apps/ccusage/justfile
  • apps/ccusage/scripts/compare-pr-performance.bb
  • apps/ccusage/scripts/compare-pr-performance.nu
  • apps/ccusage/scripts/compare-pr-performance_test.clj
  • apps/ccusage/scripts/compare_pr_performance/benchmark.clj
  • apps/ccusage/scripts/compare_pr_performance/data.clj
  • apps/ccusage/scripts/compare_pr_performance/main.clj
  • apps/ccusage/scripts/compare_pr_performance/report.clj
  • apps/ccusage/scripts/compare_pr_performance/system.clj
💤 Files with no reviewable changes (1)
  • apps/ccusage/scripts/compare-pr-performance.nu

Comment thread apps/ccusage/scripts/compare_pr_performance/benchmark.clj
Comment thread apps/ccusage/scripts/compare_pr_performance/system.clj
Comment thread apps/ccusage/scripts/compare_pr_performance/system.clj Outdated
Comment thread apps/ccusage/scripts/compare_pr_performance/system.clj
@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: cf46b6182335
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 341.8ms 2.95 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 303.1ms 3.32 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 120.0ms 8.39 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 80.1ms 12.56 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 native ccusage binary 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 23.9ms 2.5ms 9.72x 53.50 MiB 10.45 MiB 0.20x 0.06 MiB/s 0.63 MiB/s
claude session --offline --json 0.00 MiB 24.5ms 2.4ms 10.22x 53.50 MiB 10.45 MiB 0.20x 0.06 MiB/s 0.65 MiB/s
codex daily --offline --json 0.00 MiB 24.2ms 2.3ms 10.59x 53.75 MiB 8.44 MiB 0.16x 0.04 MiB/s 0.38 MiB/s
codex session --offline --json 0.00 MiB 21.8ms 2.1ms 10.22x 53.75 MiB 8.44 MiB 0.16x 0.04 MiB/s 0.40 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published native ccusage binary 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 346.2ms 301.9ms 1.15x 940.58 MiB 946.58 MiB 1.01x 2.91 GiB/s 3.33 GiB/s
codex --offline --json 1.01 GiB 105.4ms 84.4ms 1.25x 421.29 MiB 419.29 MiB 1.00x 9.55 GiB/s 11.92 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.71 KiB +0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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
Contributor

ccusage performance comparison

PR SHA: cf46b6182335
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 346.5ms 2.91 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 314.1ms 3.21 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 111.6ms 9.02 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 88.9ms 11.32 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 27.9ms 25.0ms 1.11x 53.75 MiB 53.75 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
claude session --offline --json 0.00 MiB 25.8ms 24.8ms 1.04x 53.75 MiB 53.75 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
codex daily --offline --json 0.00 MiB 23.9ms 22.5ms 1.06x 53.75 MiB 53.75 MiB 1.00x 0.04 MiB/s 0.04 MiB/s
codex session --offline --json 0.00 MiB 22.5ms 22.5ms 1.00x 53.75 MiB 53.75 MiB 1.00x 0.04 MiB/s 0.04 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 346.7ms 345.1ms 1.00x 946.58 MiB 954.58 MiB 1.01x 2.90 GiB/s 2.92 GiB/s
codex --offline --json 1.01 GiB 103.0ms 106.6ms 0.97x 431.29 MiB 427.29 MiB 0.99x 9.78 GiB/s 9.44 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.71 KiB +0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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.

Normalize version-qualified Windows os.name values to win32 so native executable and package paths use the expected suffixes. Resolve relative pnpm pack filenames against the temporary destination while preserving the absolute paths emitted by current pnpm versions.

Add regression coverage for both platform normalization and relative or absolute tarball filenames.
@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai @cubic-dev-ai Addressed the actionable review findings in b8dbb41 and replied to each CodeRabbit thread. Validation: 12 tests, 30 assertions, and local packed-tarball smoke passed. Please review the latest commit.

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai @cubic-dev-ai Addressed the actionable review findings in b8dbb41 and replied to each CodeRabbit thread. Validation: 12 tests, 30 assertions, and local packed-tarball smoke passed. Please review the latest commit.

@ryoppippi I have started the AI code review. It will take a few minutes to complete.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

@ryoppippi Thanks for the update — I'll review the latest commit (b8dbb41) that addresses the actionable findings now.

✅ Action performed

Review finished.

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.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

@ryoppippi Thanks for the update — I'll review the latest commit now.

✅ Action performed

Review finished.

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.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

@ryoppippi Thanks for the update — I'll review the latest commit (cf46b61) that adds CI execution for the Babashka harness tests now.

✅ Action performed

Review finished.

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.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 13 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread apps/ccusage/scripts/compare-pr-performance_test.clj
Comment thread apps/ccusage/scripts/compare_pr_performance/main.clj Outdated
Comment thread apps/ccusage/scripts/compare_pr_performance/data.clj
@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: b8dbb4182501
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 343.3ms 2.93 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 307.1ms 3.28 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 109.1ms 9.22 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 80.2ms 12.55 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 native ccusage binary 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 28.2ms 4.1ms 6.80x 53.50 MiB 10.45 MiB 0.20x 0.05 MiB/s 0.37 MiB/s
claude session --offline --json 0.00 MiB 26.3ms 2.6ms 10.07x 53.50 MiB 10.45 MiB 0.20x 0.06 MiB/s 0.59 MiB/s
codex daily --offline --json 0.00 MiB 23.3ms 2.6ms 8.78x 53.75 MiB 8.44 MiB 0.16x 0.04 MiB/s 0.32 MiB/s
codex session --offline --json 0.00 MiB 22.8ms 2.1ms 10.73x 53.75 MiB 8.43 MiB 0.16x 0.04 MiB/s 0.40 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published native ccusage binary 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 348.6ms 321.1ms 1.09x 934.58 MiB 956.58 MiB 1.02x 2.89 GiB/s 3.14 GiB/s
codex --offline --json 1.01 GiB 107.9ms 82.9ms 1.30x 421.29 MiB 409.28 MiB 0.97x 9.33 GiB/s 12.15 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.71 KiB +0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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
Contributor

ccusage performance comparison

PR SHA: b8dbb4182501
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 338.4ms 2.98 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 305.8ms 3.29 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 100.8ms 9.99 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 86.6ms 11.62 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 26.6ms 24.4ms 1.09x 53.75 MiB 53.75 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
claude session --offline --json 0.00 MiB 24.7ms 23.3ms 1.06x 53.50 MiB 53.75 MiB 1.00x 0.06 MiB/s 0.07 MiB/s
codex daily --offline --json 0.00 MiB 24.4ms 22.4ms 1.09x 53.75 MiB 53.75 MiB 1.00x 0.04 MiB/s 0.04 MiB/s
codex session --offline --json 0.00 MiB 22.0ms 23.5ms 0.93x 53.75 MiB 53.75 MiB 1.00x 0.04 MiB/s 0.04 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 355.9ms 332.2ms 1.07x 962.58 MiB 948.59 MiB 0.99x 2.83 GiB/s 3.03 GiB/s
codex --offline --json 1.01 GiB 106.6ms 104.8ms 1.02x 415.28 MiB 409.29 MiB 0.99x 9.44 GiB/s 9.61 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.71 KiB +0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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.

Use remote tarball sizing only after the corresponding preview package was installed successfully. When either package URL times out, benchmark and size the available local checkout so fallback runs can still produce a complete report.

Cover base and head source selection and verify both unavailable URLs through a committed-fixture smoke run.
@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai @cubic-dev-ai Addressed the valid fallback review finding in bf40013 and replied to all Cubic threads. Validation: 12 tests, 34 assertions, plus unavailable base/head URL fallback integration smoke. Please review the latest commit.

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai @cubic-dev-ai Addressed the valid fallback review finding in bf40013 and replied to all Cubic threads. Validation: 12 tests, 34 assertions, plus unavailable base/head URL fallback integration smoke. Please review the latest commit.

@ryoppippi I have started the AI code review. It will take a few minutes to complete.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

@ryoppippi Thanks for the update — I'll review the latest commit (bf40013) that addresses the fallback handling finding now.

✅ Action performed

Review finished.

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.

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: bf40013631ef
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 337.7ms 2.98 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 301.8ms 3.34 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 108.3ms 9.30 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 85.2ms 11.82 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 28.3ms 25.1ms 1.13x 53.75 MiB 53.75 MiB 1.00x 0.05 MiB/s 0.06 MiB/s
claude session --offline --json 0.00 MiB 25.5ms 24.6ms 1.04x 53.75 MiB 53.75 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
codex daily --offline --json 0.00 MiB 23.0ms 22.9ms 1.00x 53.75 MiB 53.50 MiB 1.00x 0.04 MiB/s 0.04 MiB/s
codex session --offline --json 0.00 MiB 23.4ms 22.4ms 1.05x 53.50 MiB 53.75 MiB 1.00x 0.04 MiB/s 0.04 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 343.8ms 327.1ms 1.05x 948.58 MiB 938.58 MiB 0.99x 2.93 GiB/s 3.08 GiB/s
codex --offline --json 1.01 GiB 103.1ms 106.5ms 0.97x 429.29 MiB 419.29 MiB 0.98x 9.76 GiB/s 9.46 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.70 KiB -0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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
Contributor

ccusage performance comparison

PR SHA: bf40013631ef
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 346.0ms 2.91 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 303.0ms 3.32 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 108.1ms 9.31 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 85.4ms 11.79 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 native ccusage binary 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 28.6ms 4.2ms 6.85x 53.75 MiB 10.45 MiB 0.19x 0.05 MiB/s 0.37 MiB/s
claude session --offline --json 0.00 MiB 26.4ms 3.1ms 8.50x 53.50 MiB 10.45 MiB 0.20x 0.06 MiB/s 0.50 MiB/s
codex daily --offline --json 0.00 MiB 23.3ms 2.1ms 10.85x 53.75 MiB 8.44 MiB 0.16x 0.04 MiB/s 0.40 MiB/s
codex session --offline --json 0.00 MiB 25.4ms 2.2ms 11.72x 53.75 MiB 8.43 MiB 0.16x 0.03 MiB/s 0.40 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published native ccusage binary 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 350.8ms 306.1ms 1.15x 930.58 MiB 960.58 MiB 1.03x 2.87 GiB/s 3.29 GiB/s
codex --offline --json 1.01 GiB 102.5ms 86.6ms 1.18x 433.29 MiB 415.29 MiB 0.96x 9.82 GiB/s 11.63 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.70 KiB -0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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.

codesmith-bot and others added 2 commits July 12, 2026 12:22
…platforms

Add a cancellable timeout to run-process and thread --package-runner-timeout-ms through the package URL probe, install, pnpm pack, and git rev-parse flows so a stalled child cannot outlive the deadline; give the curl probe and download explicit connect and read limits.

measure-memory now warns once and skips gracefully when /usr/bin/time is unavailable (unsupported platforms) instead of throwing and aborting the entire benchmark run.

Co-authored-by: Codesmith <[email protected]>
@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai @cubic-dev-ai Reverted the Codesmith auto-fix in 6c90fc2 because it reintroduced the two review suggestions already withdrawn for Nushell parity (global child timeouts and skipping unsupported RSS). The validated fallback fix in bf40013 remains. Tests: 12 tests, 34 assertions passed. Please review the latest commit.

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai @cubic-dev-ai Reverted the Codesmith auto-fix in 6c90fc2 because it reintroduced the two review suggestions already withdrawn for Nushell parity (global child timeouts and skipping unsupported RSS). The validated fallback fix in bf40013 remains. Tests: 12 tests, 34 assertions passed. Please review the latest commit.

@ryoppippi I have started the AI code review. It will take a few minutes to complete.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

@ryoppippi Understood — I'll review the latest commit that reverts the Codesmith auto-fix, keeping the validated fallback fix from bf40013 intact.

✅ Action performed

Review finished.

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.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 13 files

Re-trigger cubic

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 9140a99057ba
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 333.2ms 3.02 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 310.0ms 3.25 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 106.2ms 9.48 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 81.7ms 12.33 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 native ccusage binary 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 24.5ms 4.0ms 6.16x 53.75 MiB 10.45 MiB 0.19x 0.06 MiB/s 0.39 MiB/s
claude session --offline --json 0.00 MiB 25.9ms 3.0ms 8.75x 53.50 MiB 10.45 MiB 0.20x 0.06 MiB/s 0.52 MiB/s
codex daily --offline --json 0.00 MiB 22.9ms 2.7ms 8.48x 53.50 MiB 8.43 MiB 0.16x 0.04 MiB/s 0.32 MiB/s
codex session --offline --json 0.00 MiB 23.6ms 2.1ms 11.30x 53.75 MiB 8.43 MiB 0.16x 0.04 MiB/s 0.41 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published native ccusage binary 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 352.8ms 314.2ms 1.12x 954.58 MiB 1016.59 MiB 1.06x 2.85 GiB/s 3.20 GiB/s
codex --offline --json 1.01 GiB 108.8ms 90.4ms 1.20x 429.29 MiB 409.28 MiB 0.95x 9.26 GiB/s 11.14 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.71 KiB +0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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
Contributor

ccusage performance comparison

PR SHA: 9140a99057ba
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 346.3ms 2.91 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 315.2ms 3.19 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 104.6ms 9.62 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 80.0ms 12.58 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 24.0ms 25.4ms 0.94x 53.75 MiB 53.75 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
claude session --offline --json 0.00 MiB 26.5ms 25.6ms 1.03x 53.75 MiB 53.50 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
codex daily --offline --json 0.00 MiB 22.4ms 23.0ms 0.97x 54.00 MiB 53.75 MiB 1.00x 0.04 MiB/s 0.04 MiB/s
codex session --offline --json 0.00 MiB 23.2ms 24.5ms 0.95x 53.75 MiB 53.50 MiB 1.00x 0.04 MiB/s 0.04 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 353.5ms 334.6ms 1.06x 946.59 MiB 958.58 MiB 1.01x 2.85 GiB/s 3.01 GiB/s
codex --offline --json 1.01 GiB 107.3ms 108.0ms 0.99x 425.29 MiB 403.29 MiB 0.95x 9.39 GiB/s 9.32 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.71 KiB +0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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
Contributor

ccusage performance comparison

PR SHA: 6c90fc26fd28
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 340.8ms 2.95 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 318.9ms 3.16 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 101.6ms 9.91 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 79.8ms 12.62 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 native ccusage binary 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 26.9ms 3.0ms 8.82x 53.75 MiB 10.45 MiB 0.19x 0.06 MiB/s 0.51 MiB/s
claude session --offline --json 0.00 MiB 23.6ms 3.7ms 6.29x 53.50 MiB 10.45 MiB 0.20x 0.07 MiB/s 0.41 MiB/s
codex daily --offline --json 0.00 MiB 23.6ms 2.3ms 10.28x 53.75 MiB 8.44 MiB 0.16x 0.04 MiB/s 0.37 MiB/s
codex session --offline --json 0.00 MiB 22.2ms 2.0ms 10.85x 53.50 MiB 8.44 MiB 0.16x 0.04 MiB/s 0.42 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published native ccusage binary 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 355.4ms 316.2ms 1.12x 944.58 MiB 924.58 MiB 0.98x 2.83 GiB/s 3.18 GiB/s
codex --offline --json 1.01 GiB 108.2ms 86.1ms 1.26x 411.29 MiB 419.29 MiB 1.02x 9.30 GiB/s 11.70 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.70 KiB -0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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
Contributor

ccusage performance comparison

PR SHA: 6c90fc26fd28
Base SHA: 997ad7f90189

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 321.4ms 3.13 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 296.1ms 3.40 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 103.2ms 9.75 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 82.7ms 12.18 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 24.4ms 24.4ms 1.00x 53.75 MiB 53.75 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
claude session --offline --json 0.00 MiB 25.2ms 23.3ms 1.08x 53.75 MiB 53.75 MiB 1.00x 0.06 MiB/s 0.07 MiB/s
codex daily --offline --json 0.00 MiB 23.7ms 21.6ms 1.10x 53.75 MiB 53.50 MiB 1.00x 0.04 MiB/s 0.04 MiB/s
codex session --offline --json 0.00 MiB 25.2ms 22.5ms 1.12x 53.50 MiB 53.50 MiB 1.00x 0.03 MiB/s 0.04 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 340.3ms 331.6ms 1.03x 954.59 MiB 950.59 MiB 1.00x 2.96 GiB/s 3.04 GiB/s
codex --offline --json 1.01 GiB 100.1ms 104.3ms 0.96x 405.29 MiB 401.29 MiB 0.99x 10.06 GiB/s 9.65 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 18.71 KiB 18.70 KiB -0.00 KiB 1.00x
installed native package binary 4083.81 KiB 4083.81 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 dad1b5d into main Jul 12, 2026
36 checks passed
@ryoppippi
ryoppippi deleted the codex/migrate-performance-harness-to-babashka branch July 12, 2026 12:31
axisrow added a commit to axisrow/ccusage that referenced this pull request Aug 12, 2026
* chore(ci): remove pullfrog because they dont serve free tokens anymore

* Restore `pullfrog.yml` workflow

* feat(statusline): show reasoning effort level next to model name (ccusage#1405)

* feat(statusline): show reasoning effort level next to model name

Claude Code 2.1.119+ includes an optional top-level effort.level field
(low, medium, high, xhigh, or max) in the statusline hook JSON,
reflecting the live /effort setting. Parse it from the hook input and
append it to the model segment, e.g. '🤖 Fable 5 (high)'.

The field is absent for models without the effort parameter and on
older Claude Code versions, in which case the statusline keeps showing
just the model label as before.

* test(statusline): add Fable 5 fixture with effort level

Adds a manual statusline fixture for the latest model shape, including
the effort.level field, plus a test-statusline-fable5 recipe wired into
test-statusline-all so the effort display can be smoke-tested from the
CLI.

* docs(statusline): document effort level next to the model name

Updates the statusline guide examples to the current model display
('Fable 5 (high)') and explains that the reasoning effort level comes
from Claude Code 2.1.119+, with a fallback example for models or
versions that do not report it.

* Revert "Restore `pullfrog.yml` workflow"

This reverts commit 04f45b0.

* fix(codex): skip forked session replay history (ccusage#1369)

* feat(json): emit modelBreakdowns in per-agent JSON reports (ccusage#1395)

Per-agent subcommands (ccusage pi|opencode|amp|hermes|... daily/weekly/
monthly/session --json) compute per-model cost breakdowns — the table
view renders them with --breakdown — but the shared per-agent JSON
serializer never emitted them, forcing JSON consumers to re-derive
model costs they cannot actually reconstruct.

Add "modelBreakdowns" to agent_summary_json, mirroring the unified
serializers (summary_json / session_summary_json). Purely additive:
every pre-existing key and value is unchanged; the codex-native
serializer (models object) is deliberately untouched.

Tests: shared-shape insta snapshot now shows populated breakdowns for
all four report kinds; pi daily JSON asserts a full single-element
breakdown array with non-zero cost (the motivating case); fixture-
driven copilot (real pricing via read_otel_file) and qwen (real JSONL
fixture line) assertions pin their entire breakdown arrays.

* fix(pi): align unified session date filtering (ccusage#1394)

* fix(pi): align unified session date filtering

Filter default pi unified session entries by date before summarizing, matching
`ccusage pi session --pi-path` behavior for inclusive `--until` days.

* style: apply treefmt formatting

---------

Co-authored-by: ryoppippi <[email protected]>

* feat(unified): --sections and --by-agent for single-invocation reporting (ccusage#1396)

* feat(unified): --sections and --by-agent for single-invocation reporting

Dashboards polling ccusage today need one unified invocation per section
plus one per-agent invocation per agent — every call re-scanning all
stores. Two additive flags on the unified commands (and the bare root
invocation) collapse that to a single call:

  ccusage daily --json --sections daily,monthly,session --by-agent

--sections <csv> emits each requested grouping in one envelope from at
most TWO store scans (daily/weekly/monthly share one Daily-kind base
load; session adds one Session-kind load), one process, one pricing
load. Every section is produced by exactly the code path its standalone
command uses — load_sections delegates to the same load_rows machinery,
so section output is identical to a standalone invocation by
construction (covered by fixture equivalence tests including claude
agent-progress usage lines and codex cross-session/model-alias dedupe
cases). Envelope order is deterministic via a local ordered serializer:
invoked section first, remaining sections in canonical order, totals
last; single-section envelopes use the unchanged existing path.

--by-agent adds an "agents" array to daily/weekly/monthly rows (the
internal per-agent breakdowns, now serialized: tokens, cost, and
modelBreakdowns per agent). Session rows are already per-agent, so the
flag is a no-op there. Per-agent costs sum exactly to the combined row.

Backward compatibility: without the new flags, JSON and table output
are byte-identical to before (verified against a 20-invocation golden
matrix on real stores). Tables render requested sections sequentially;
--by-agent is JSON-only.

* refactor(unified): address review feedback on duplication and detected agents

- row_json now composes agent_json and layers on the row-level fields
  (period, metadata, agents), so the shared row shape has a single
  serialization path; output unchanged.
- Extract parse_unified_report_arg so the root, unified-command, and
  top-level-session parse sites share one --all/--sections/--by-agent
  block; the root site keeps its mark_used bookkeeping.
- Carry daily-load and session-load detected agents separately so each
  --sections table header shows the same detected list as the
  equivalent standalone invocation.

* style: apply treefmt formatting

---------

Co-authored-by: ryoppippi <[email protected]>

* feat(pi): named pi-format stores as config-declared agents (ccusage#1397)

* feat(pi): named pi-format stores as config-declared agents

Tools built on pi (oh-my-pi and other forks) keep pi-format session
stores at their own paths. ccusage could only read one pi path universe
and labeled everything it found as agent "pi". Declare named extra
stores in the config file:

  { "pi": { "stores": [ { "name": "omp", "path": "~/.omp/agent/sessions" } ] } }

Each named store loads through the existing pi parser and surfaces as
its OWN agent in the unified reports: rows tagged in metadata.agents,
sessions with projectPath/lastActivity like pi, model labels prefixed
"[<name>] ". Named stores are additive to the default pi store and use
the same path-list semantics (comma-separated, ~-expansion, dedupe) and
the same date-window filtering as `ccusage pi ... --pi-path`.

Costs are computed from the unprefixed model name — the configurable
store name never participates in pricing lookup (a store named "o3"
cannot fabricate o3 pricing; regression-tested), while prefixed
pricingOverrides keys are consulted first and keep working.

Config validation: names match ^[a-z][a-z0-9_-]{0,31}$, reject
collisions with built-in agents (single source of truth asserted
against the unified loader's registry), duplicates, empty paths, and
stores whose resolved paths overlap the default pi store or another
store (silent double-counting is never possible). Invalid stores error
through the same config-error path as other invalid config content.
Absent store paths yield clean empty results, like default pi.

Backward compatibility: without pi.stores configured, all output is
byte-identical to before (verified against a golden matrix on real
stores, including a known pre-existing until-day session-window quirk
in the default pi unified path, deliberately preserved here and fixed
in a separate patch). Committed config schema regenerated.

No CLI surface changes: per-agent subcommands remain a closed set;
named stores appear in unified reports only.

* fix(pi): reject nested/partial named-store path overlaps, dedupe path parsing

- Session files are collected recursively, so a named store rooted at an
  ancestor or descendant of the default pi store (or another named
  store) would ingest the same files twice under different dedupe
  identities. The resolver now rejects any overlap — equal, ancestor,
  or descendant — and partial collisions error instead of silently
  dropping the colliding path, matching the documented contract.
  Regression tests for a store nested inside the default pi path and a
  partial overlap across two stores.
- Extract a shared existing_paths helper in pi/paths.rs; the default
  and named-store variants now differ only in their path mapper, with
  the deliberate ~-expansion difference documented.
- Update config/pi docs for the stricter overlap wording.

* docs(pi): move trailing space out of code spans (markdownlint MD038)

---------

Co-authored-by: ryoppippi <[email protected]>

* fix(kimi): support Kimi Code new wire format (ccusage#1362)

Kimi Code (`~/.kimi-code`) emits a new `wire.jsonl` schema that the old
adapter could not parse, so its usage was silently dropped (ccusage#1261).

- Detect `~/.kimi-code` and the deeper layout
  `sessions/<ws>/<session>/agents/<agent>/wire.jsonl` (5 path components)
  alongside the legacy 3-component layout.
- Parse top-level `type == "usage.record"` lines: camelCase token fields
  (`inputOther`, `inputCacheRead`, `inputCacheCreation`), `time` in
  milliseconds, and `model` prefixed with `kimi-code/` (stripped for
  pricing lookup). Skip cumulative `usageScope == "session"` records.
- Deserialize `time` leniently so a float- or string-encoded timestamp
  degrades to the file-mtime fallback instead of dropping the whole line.
- Walk the correct number of parents in `kimi_root_from_wire_path` for the
  deeper layout so config resolution looks at the right root.
- Keep full backward compatibility with the old StatusUpdate format.
- Update the Kimi guide and data-source docs for `~/.kimi-code`.

Fixes ccusage#1261

Co-authored-by: Claude Opus 4.8 <[email protected]>

* perf: cache PricingMap::find() results and skip redundant opencode pricing checks (ccusage#1407)

* perf(pricing): cache PricingMap::find() results to avoid repeated fuzzy matching

PricingMap::find() does an exact HashMap lookup followed by expensive
fuzzy matching through all ~2,200 pricing entries when the exact model
name is not in the map. When adapters repeatedly query the same model
names, a large fraction of lookups miss the HashMap and trigger a full
scan of the pricing table for every call.

Add a OnceLock&lt;Mutex&lt;FxHashMap&gt;&gt; cache that memoizes find()
results by model name (including None for models not found in pricing).
Once a model name has been resolved, future lookups complete in O(1)
instead of O(n) over the pricing table.

Also add clear_find_cache() called from load_json_with_overrides(),
load_models_dev_models(), and apply_overrides() so the cache stays
consistent when the pricing table is mutated.

* perf(opencode): skip redundant missing-pricing check when cost is known

calculate_open_code_cost and missing_open_code_pricing independently
iterate through the same model candidates. When the cost calculation
already found a valid positive cost (either from a stored cost_usd
field or from pricing lookup), skip the missing-pricing check entirely
since pricing was already resolved.

---------

Co-authored-by: turtton <[email protected]>

* ci(release): migrate from bumpp to tagpr (ccusage#1406)

* ci(release): add tagpr release PR automation

Introduce Songmu/tagpr to manage releases via an auto-generated
release PR: every push to main creates or updates a PR that bumps all
nine workspace package.json versions (tagpr versionFile) and syncs the
Rust workspace via the new `just sync-rust-version` recipe run as
postVersionCommand. Merging the PR tags the merge commit.

GitHub Release creation and CHANGELOG.md generation are disabled in
.tagpr because changelogithub keeps generating the release notes in
the existing style.

Tags pushed with GITHUB_TOKEN do not trigger `on: push: tags`
workflows, so tagpr.yaml dispatches release.yaml explicitly with
`gh workflow run --ref <tag>`; release.yaml gains a workflow_dispatch
trigger for that purpose.

* chore(release): drop bumpp local release flow

Releases are now driven by tagpr in CI, so the local `just release`
recipe and the bumpp dependency are no longer needed. bump.config.ts
is deleted because its cargo set-version hook moved to the
`just sync-rust-version` recipe that tagpr runs as postVersionCommand.

* docs(skills): document tagpr release flow

Replace the removed `just release` recipe in the development skill
command list with a note on the tagpr release PR flow and the
minor/major bump labels.

* ci(release): gate release jobs to tag refs and isolate actions:write

Gate release.yaml build/publish/release jobs behind startsWith(github.ref, 'refs/tags/') so a workflow_dispatch from a branch cannot bypass the tag-only release flow. tagpr dispatches with --ref <tag>, so the intended path is unaffected.

Move the release dispatch out of the tagpr job into a dependent dispatch-release job that alone holds actions: write, keeping tagpr on its documented least-privilege scopes (contents/pull-requests/issues).

Co-authored-by: Codesmith <[email protected]>

* ci(release): consolidate release pipeline into tagpr workflow

Move the build/publish/release jobs from release.yaml into tagpr.yaml,
gated on the tagpr job's tag output, and delete release.yaml. Running
everything in one workflow removes the workflow_dispatch chaining that
worked around GITHUB_TOKEN-pushed tags not triggering `push: tags`
workflows, along with the dispatch-release job and its `actions: write`
grant.

The release jobs check out the freshly created tag explicitly.
changelogithub resolves the release tag with `git tag --points-at
HEAD`, not GITHUB_REF, so it picks the right release even though the
run's ref is refs/heads/main.

A failed release is retried with "Re-run failed jobs"; a full re-run
finds no new tag and skips the release jobs.

---------

Co-authored-by: Codesmith <[email protected]>

* ci(release): use Conventional Commits title for tagpr release PRs (ccusage#1409)

tagpr titles its release PRs "Release for vX.Y.Z", which fails the
check-pr-title workflow because it has no Conventional Commits type
prefix (seen on PR ccusage#1408). tagpr takes the first line of the rendered
pull request template as the PR title, so point .tagpr at a custom
template whose first line is "chore: release {{.NextVersion}}". The
rest of the template mirrors tagpr's default body, minus the unused
tag-prefix placeholder.

The template is a Go text/template, and oxfmt's markdown rewrites
break its <details> block and nested list structure, so exclude it
from treefmt.

This also restores the title style used by the previous bumpp-based
release flow ("chore: release v20.0.14").

* feat(pricing): support OpenAI two-stage pricing and add the gpt-5.6 family (ccusage#1414)

* feat(pricing): add gpt-5.6 family and OpenAI long-context tier rates

OpenAI introduced two-stage (short/long context) pricing with gpt-5.6:
requests with more than 272K input tokens are billed at higher
long-context rates. The same tier also applies to gpt-5.5, gpt-5.5-pro,
gpt-5.4, and gpt-5.4-pro on the current pricing page.

The existing tier support hardcoded the LiteLLM 200K boundary, so
Pricing gains a per-model long_context_threshold (defaulting to 200K
for LiteLLM *_above_200k_tokens data) and tiered_cost takes the
threshold as a parameter.

New built-in entries cover gpt-5.6-sol, gpt-5.6-terra, and
gpt-5.6-luna, including their cache-write rates. Long-context tier
rates live in a builtin_long_context_rates overlay that is re-applied
after every pricing load: a live LiteLLM refresh replaces whole
entries, and LiteLLM currently publishes these models with flat rates
only, so tier rates set directly on built-in entries would be silently
dropped whenever a refresh succeeds. Entries that already carry tier
rates are left untouched so upstream data wins once it exists.
Date-pinned keys such as gpt-5.5-2026-04-23 share their base model's
overlay rates.

The gpt-5.6 context limits mirror the 1,050,000-token window of the
other long-context GPT-5 flagship models until upstream data lands.

* feat(codex): bill long-context requests at OpenAI two-stage rates

OpenAI decides the pricing tier per request: once a request's input
exceeds 272K tokens, every token of that request (input, cached input,
and output) is billed at the long-context rates. Codex cost calculation
runs on per-model sums aggregated across many requests, so the tier
cannot be recovered from the totals afterwards.

CodexModelUsage now tracks the portion of tokens that came from
long-context requests. The split is recorded while token_count events
are aggregated, where each event still represents a single request,
and merged across parallel shards like the other counters.

calculate_codex_model_cost prices the aggregated usage as two
independent buckets: the short bucket at the flat rates and the long
bucket at the *_above_200k rates, falling back to the flat rates for
models without a long-context tier so their costs are unchanged. The
existing fast-speed multiplier applies to both buckets.

Report JSON and table output are unchanged; only costUSD values for
long-context requests differ.

* docs(pricing): explain all-or-nothing long-context overlay check

Codex review suggested filling missing tier fields independently when a
refreshed LiteLLM entry carries partial *_above_200k_tokens data. That
would mix rates that assume the 200K LiteLLM boundary with built-in
rates that assume the OpenAI 272K boundary under a single per-model
threshold, mispricing both tiers, so the overlay defers to upstream
entirely once any tier rate exists. Record that rationale next to the
check.

* fix(pricing): apply two-stage rates to whole request and per-model split

Co-authored-by: Codesmith <[email protected]>

---------

Co-authored-by: Codesmith <[email protected]>

* chore: use black smith more

* chore: release v20.0.15 (ccusage#1408)

[tagpr] prepare for the next release

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* chore(ci): rename it back to releaese.yaml

* chore: release v20.0.16 (ccusage#1416)

[tagpr] prepare for the next release

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* docs: update Lineman affiliate links to CCUsage landing page (ccusage#1417)

Point GitHub README and docs site sponsor links at the dedicated
LinkJolt redirect for CCUsage traffic (free tier + voucher funnel).

Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: ryoppippi <[email protected]>

* docs: update Star History chart (ccusage#1419)

* docs: update Star History chart

Switch the README and sponsorship guide to the current Star History chart endpoint, including light and dark variants. Allowlist the public read-only sealed chart token so secret scanning does not report a false positive.

Co-authored-by: ryoppippi <[email protected]>

* chore: exclude sealed token from spellcheck

Mark the exact public Star History token allowlist line as a spellcheck exclusion so its random character sequence does not fail the documentation preflight.

Co-authored-by: ryoppippi <[email protected]>

* chore: format sealed token allowlist

Use the repository's TOML formatting and bracket the random token with the supported spellchecker block directives.

Co-authored-by: ryoppippi <[email protected]>

* style: align Gitleaks TOML indentation

Match the repository formatter's tab indentation for the multiline allowlist entry.

Co-authored-by: ryoppippi <[email protected]>

* fix: match full Star History token URL

Configure the global Gitleaks allowlist to evaluate the full finding match so the narrowly scoped sealed_token pattern suppresses the six intentional chart URLs.

Co-authored-by: ryoppippi <[email protected]>

---------

Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: ryoppippi <[email protected]>

* fix(claude): count advisor model usage (ccusage#1423)

* fix(claude): count advisor model usage

Expand advisor_message iterations into distinct usage entries so their tokens and model-specific costs are included in every report path. Keep main-model iteration totals unchanged and cover both standard and daily loaders.

Co-authored-by: ryoppippi <[email protected]>

* docs(claude): clarify advisor cost modes

Co-authored-by: ryoppippi <[email protected]>

---------

Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: ryoppippi <[email protected]>

* chore: release v20.0.17 (ccusage#1418)

[tagpr] prepare for the next release

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* perf(nix): keep dependency cache across releases (ccusage#1424)

* build(perf): migrate benchmark harness to Babashka (ccusage#1432)

* build(perf): migrate benchmark harness to Babashka

Replace the large Nushell PR benchmark script with a Babashka implementation split by data, system, benchmark, report, and orchestration responsibilities. The new process boundary keeps argv, environment, and working-directory data explicit while preserving hyperfine, package installation, memory, size, and Markdown behavior.

Move the CI caller and profiling guidance to the executable Babashka entry point. Add focused tests behind their own Nix shebang so contributors can run the harness suite without adding Babashka to the full development shell.

* docs(agents): document implementation language choices

Route small command-oriented automation to Nushell and data-heavy, testable automation to Babashka. Keep production binaries in Rust and npm-integrated APIs in TypeScript so future tooling changes follow the same criteria used by the benchmark migration.

* test(ci): run Babashka harness tests

Execute the self-contained benchmark harness test entry point in the CI test job so changes to CLI parsing, normalization, fallback decisions, and report rendering cannot bypass pull request validation.

* fix(perf): harden platform and tarball paths

Normalize version-qualified Windows os.name values to win32 so native executable and package paths use the expected suffixes. Resolve relative pnpm pack filenames against the temporary destination while preserving the absolute paths emitted by current pnpm versions.

Add regression coverage for both platform normalization and relative or absolute tarball filenames.

* fix(perf): size local package fallbacks

Use remote tarball sizing only after the corresponding preview package was installed successfully. When either package URL times out, benchmark and size the available local checkout so fallback runs can still produce a complete report.

Cover base and head source selection and verify both unavailable URLs through a committed-fixture smoke run.

* fix(perf): bound harness child processes and skip RSS on unsupported platforms

Add a cancellable timeout to run-process and thread --package-runner-timeout-ms through the package URL probe, install, pnpm pack, and git rev-parse flows so a stalled child cannot outlive the deadline; give the curl probe and download explicit connect and read limits.

measure-memory now warns once and skips gracefully when /usr/bin/time is unavailable (unsupported platforms) instead of throwing and aborting the entire benchmark run.

Co-authored-by: Codesmith <[email protected]>

* Revert "fix(perf): bound harness child processes and skip RSS on unsupported platforms"

This reverts commit 9140a99.

---------

Co-authored-by: Codesmith <[email protected]>

* build(perf): migrate fixture generator to Bun (ccusage#1433)

* build(perf): migrate fixture generator to Bun

Replace the Nushell fixture generator with a dependency-free Bun script.\n\nKeep the generated Claude and Codex fixture layouts and command-line\ninterface while using Bun file writers and Bun Shell for file operations.

* build(perf): type Bun fixture script

Add Bun development types so the fixture generator is checked alongside the package tooling.\n\nAwait file writer operations to preserve ordered writes and satisfy the\nrepository promise lint rule.

* build(perf): avoid Bun type dependency

Keep the fixture generator dependency-free by declaring its small Bun API surface locally.\n\nRemove the Bun type package and restore the package TypeScript configuration so\npublishing the fixture generator does not expand package dependencies.

* chroe(ci): fix nix cache

* ci: add GitHub-hosted runner fallback

Keep Blacksmith runners for the upstream repository while allowing forks\nto use hosted runners by default. Forks with a Blacksmith subscription can\nopt in through HAS_BLACKSMITH=true.

* ci: skip pkg-pr previews without the GitHub App

Forks do not inherit the pkg-pr-new GitHub App installation. Skip\npreview publishing and its dependent E2E and performance jobs unless a fork\nexplicitly opts in with HAS_PKG_PR_NEW=true.

* ci: keep Windows arm release runner defined

Supply both matrix runner fields so the release workflow resolves its\nWindows ARM runner consistently with the other native package targets.

---------

Co-authored-by: ryoppippi <[email protected]>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: sijie-ni-0214 <[email protected]>
Co-authored-by: Ben Vargas <[email protected]>
Co-authored-by: Mint Choco <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: turtton <[email protected]>
Co-authored-by: Codesmith <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: ryoppippi <[email protected]>
Co-authored-by: axisrow <[email protected]>
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.

3 participants