Skip to content

refactor(nix): manage Nix-built JS tooling with bun2nix - #1489

Merged
ryoppippi merged 13 commits into
mainfrom
refactor/bun2nix-js-tools
Jul 26, 2026
Merged

refactor(nix): manage Nix-built JS tooling with bun2nix#1489
ryoppippi merged 13 commits into
mainfrom
refactor/bun2nix-js-tools

Conversation

@ryoppippi

@ryoppippi ryoppippi commented Jul 25, 2026

Copy link
Copy Markdown
Member

Summary

The Nix side of this repository built JS tooling by hand-maintaining dependency
metadata inside Nix expressions. nix/publint.nix carried a full
pnpm-lock.yaml as a heredoc fed to fetchPnpmDeps, and
nix/models-dev-pricing.nix vendored remeda and zod through fetchurl
calls whose integrity hashes were transcribed out of the pinned models-dev
input's lockfile. Both are now resolved by bun2nix
from real bun.lock files, and each tool is a self-contained directory under
nix/tools/.

changelogithub moves there too, which — together with running pkg-pr-new
via pnpm dlx and relocating @types/node — leaves the root package.json
with no devDependencies at all and removes 774 lines from pnpm-lock.yaml.

The pnpm workspace itself, package publishing, and the pnpm dlx ccusage
end-user documentation and E2E matrix are untouched.

What Changed

Each tool directory holds its package.json, the bun.lock that bun install
resolved from it, the bun.nix that bun2nix derived from that lockfile, and
its own Nix expression:

  • nix/tools/publint/ — replaces the inline pnpm-lock.yaml + fetchPnpmDeps
  • nix/tools/models-dev-gen/ — replaces the hand-pinned fetchurl tarballs;
    also absorbs models-dev-gen.ts (now gen.ts) and models-dev-compact.ts
  • nix/tools/changelogithub/ — new; release.yaml now runs
    nix run .#changelogithub instead of nix develop --command pnpm changelogithub

Shared pieces:

  • nix/bun-node-modules.nix turns a tool manifest into a node_modules tree
  • nix/bun-cli.nix wraps a CLI from one, so the non-obvious part is written once:
    bun2nix bakes bun-with-fake-node into the shebangs of the dependencies it
    stages, so a Node CLI must be repointed at real Node or it runs under Bun's
    emulation and drags bun into the runtime closure
  • A bun-nix flake check re-derives each bun.nix from its bun.lock and fails
    on drift, because Renovate bumps bun.lock without knowing bun.nix exists.
    just gen-bun-nix is the fix it points at
  • bun and the bun2nix CLI join the dev shell

Dependency cleanup:

  • pkg-pr-newpnpm dlx [email protected] at its single call site. Renovate
    does not update dlx specifiers, which is noted next to the call
  • The changelogithub>c12 pnpm override is retired. It existed only to keep
    chokidar 4.0.3 out of pnpm-lock.yaml under trustPolicy: no-downgrade
    (fix(deps): avoid c12 chokidar trust downgrade #1159); bun resolves c12 3.3.4 and chokidar 5.0.0 unaided
  • @types/node moves to nix/tools/models-dev-gen, which is where the last
    nix/**/*.ts files live. The root tsconfig.json existed only to cover them,
    so it becomes that directory's tsconfig.json
  • just install consolidates setup: the workspace install plus a
    bun install for each tool directory that carries a tsconfig. Those
    directories are outside the pnpm workspace, so without it just typecheck
    which CONTRIBUTING tells contributors to run — fails on a fresh checkout.
    git wt's hook calls the recipe

Incidental Fixes

Three pre-existing problems surfaced while getting the above to pass:

  • zizmor never audited ci.yaml. 1.26.1 predates the background:/wait-all:
    parallel-step keys, so it rejected the file at schema validation. That was
    invisible because treefmt batches files and a batch containing any other
    workflow still exits zero. nixpkgs now carries 1.27.0, which added experimental
    parallel-step support; ci.yaml audits clean, so an unaudited workflow becomes
    an audited one.
  • oxlint failed on wholly-ignored treefmt batches, same root cause — fixed
    with its own --no-error-on-unmatched-pattern.
  • The nix-store cache had no fallback restore key, so any flake change sent
    CI to a cold store even when it only added developer tooling.

Testing

  • nix flake check passes, including the new bun-nix check
  • nix/tools/models-dev-gen emits byte-identical models-dev-pricing.json and
    codex-auto-review-fallbacks.json to the committed snapshots
  • publint's runtime closure is bash + nodejs only, with no bun reference
  • changelogithub --dry resolves tags, reaches the GitHub API and renders notes
  • pnpm dlx [email protected] was checked against this repository's own pnpm
    settings, so strictDepBuilds/blockExoticSubdeps do not reject it
  • just typecheck and just test-node pass; several were verified negatively
    too — a deliberate type error in compact.test.ts is caught, a corrupted
    bun.nix fails the drift check, and removing the tool's node_modules
    reproduces the fresh-checkout failure that just install fixes
  • The intermediate commit was checked out in a scratch worktree to confirm it
    evaluates on its own

Summary by CodeRabbit

  • New Features
    • Added Bun-to-Nix packaging for tool CLIs and their dependencies, including git-aware release tooling.
    • Added reproducible generation and consistency checking for compacted model pricing snapshot artifacts.
  • Bug Fixes
    • Improved Nix cache warmup behavior to restore more compatible prior builds.
    • Updated dev/test tooling paths and git hooks after the tool reorganization.
    • Updated the default dev workflow to use just install.
  • Chores
    • Pinned on-demand publish tooling in CI and adjusted the release workflow to run the packaged release tool via Nix.
    • Added/updated helper commands (just install, just fmt guidance, and Bun/Nix generation support).

ryoppippi added 11 commits July 25, 2026 21:11
`restore-prefixes-first-match` only carried the prefix that embeds the
deps hash, so any change to flake.nix, flake.lock or nix/packages.nix
sent the job to a completely cold Nix store even when the change merely
added developer tooling and left every Cargo artefact untouched.

Add a second, hashless prefix after it. The hashed prefix still wins
when it matches, and otherwise the newest prior entry warms the deps
instead of forcing a full rebuild.
nix/publint.nix carried a full pnpm-lock.yaml as a heredoc inside a Nix
string, fed to fetchPnpmDeps. Bumping publint meant hand-editing that
embedded lockfile and its fetcherVersion/hash pair, which is how the
lockfile drifted from the workspace catalogue in the first place.

Move the dependency set into nix/tools/publint as real files instead:
package.json, the bun.lock that `bun install` resolved from it, and the
bun.nix that `bun2nix` derived from that lockfile. The Nix expression
lives next to them as default.nix, so the tool is self-contained.

nix/bun-node-modules.nix is the shared piece: it turns one of those
manifests into a node_modules tree via bun2nix's setup hook, scoping src
to just package.json and bun.lock so neither the sibling Nix expression
nor a tool's own scripts force the dependency tree to rebuild.

Two wrinkles worth recording:

  - bun2nix stages each dependency through its own derivation and patches
    shebangs there against bun's `bun-with-fake-node` shim, so publint
    arrives bound to Bun's Node emulation. dontPatchShebangs cannot undo
    that, since the path is already baked into the cached package, so the
    install phase repoints it at real Node. publint is a Node packaging
    linter, and the baked-in path would otherwise keep bun in the runtime
    closure, which is now just bash and nodejs.
  - The hook only honours a wholesale replacement of its default install
    flags, so the linker and backend are restated alongside
    --frozen-lockfile.

The publint flake check now skips nix/tools/*/package.json: those are
dependency manifests for Nix-built tooling, not publishable packages.
treefmt matches files against a formatter's `includes` and passes them as
arguments, so a batch can consist entirely of paths that
nix/oxlint-check.json ignores. oxlint exits non-zero with "No files found
to lint" in that case, which treefmt reports as a formatting failure for a
file that was deliberately excluded.

Pass --no-error-on-unmatched-pattern, oxlint's own switch for exactly this
situation, mirroring the flag oxfmt is already given here.
The generator's two runtime dependencies were vendored by hand: two
pkgs.fetchurl calls with npm integrity strings copied out of the pinned
models-dev input's bun.lock, extracted into a flat node_modules with tar.
Bumping the input meant transcribing hashes between two lockfiles.

Resolve them through bun2nix instead, from a package.json that pins the
same remeda 2.33.7 and zod 3.24.2 that input's lockfile records. The
generated bun.nix carries hashes identical to the fetchurl calls it
replaces, and both snapshots the build emits are unchanged.

Also move the tool into nix/tools/models-dev-gen so its Nix expression,
the scripts it copies into the workspace and its dependency manifests sit
together: models-dev-pricing.nix becomes default.nix, models-dev-gen.ts
becomes gen.ts, and models-dev-compact.ts drops its now-redundant prefix.
The remaining references follow: the node test invocation in the justfile
and in the git hook, the tsconfig exclude and the oxlint ignore pattern.
Each tool under nix/tools now carries a bun.lock and the bun.nix that
bun2nix derived from it. Nothing tied the two together: Renovate bumps
bun.lock without knowing bun.nix exists, and a stale pair only shows up
as a confusing "install wants the network" failure inside the sandbox.

Add a bun-nix flake check that re-derives bun.nix from each committed
bun.lock and diffs the result. bun2nix only parses the lockfile, so this
needs no network access and runs in the sandbox like the other checks.

`just gen-bun-nix` is the fix the check points at: it re-resolves every
tool and regenerates its bun.nix. Both bun and the bun2nix CLI join the
dev shell so that recipe can run.
23b7d24 moved nix/models-dev-gen.ts to
nix/tools/models-dev-gen/gen.ts and updated nix/oxlint-check.json, but
.oxlintrc.json carries its own copy of the same ignore list and was left
pointing at the old path.

`just typecheck` therefore started type-checking the generator, which
imports `./packages/core/src/generate.ts` from the upstream models.dev
worktree it is copied into at build time. That module does not exist in
this repository, so the file cannot type-check here by construction.
nix/tools/publint/default.nix held the whole recipe for turning a
bun2nix-resolved node_modules tree into a wrapped CLI, including the
non-obvious part: bun2nix bakes `bun-with-fake-node` into the shebangs of
the dependencies it stages, so a Node CLI has to be repointed at real Node
or it runs under Bun's emulation and drags bun into the runtime closure.

That is exactly the kind of detail the next tool would silently omit, so
move it into nix/bun-cli.nix. The tool's own expression shrinks to the
package name and its metadata.

`runtimeInputs` is there for CLIs that shell out to other programs; publint
does not need it.
changelogithub was a root devDependency purely so the release workflow
could reach it through `nix develop --command pnpm changelogithub`: a full
dev shell plus a pnpm workspace install, to run one CLI that touches
nothing in this repository's source.

Move it to nix/tools/changelogithub and run it as `nix run
.#changelogithub`. It shells out to git to resolve the release tag, so git
is wired into the wrapper instead of being inherited from the runner.

This also retires the `changelogithub>c12` pnpm override. That existed
only to keep chokidar 4.0.3 out of pnpm-lock.yaml, which pnpm rejected
under `trustPolicy: no-downgrade` (see f7f7be5). bun resolves c12 3.3.4
and chokidar 5.0.0 on its own, so the constraint is satisfied by plain
resolution rather than by an override. Dropping the dependency removes 751
lines from pnpm-lock.yaml.
zizmor 1.26.1 predates the parallel-step keys GitHub Actions shipped on
2026-06-25, so it failed schema validation on ci.yaml and audited nothing
there. That gap was invisible: treefmt hands the matched files to zizmor in
batches, and a batch containing any other workflow still exits zero, so the
warning about ci.yaml scrolled past while its findings went uncollected.
A batch consisting of ci.yaml alone exits non-zero instead, which is how it
finally surfaced.

zizmor 1.27.0 added experimental support for parallel steps, and nixpkgs now
carries it. ci.yaml audits clean with no findings, so this turns an
unaudited workflow into an audited one rather than merely quieting an error.
pkg-pr-new was a root devDependency, so every workspace install carried it
even though the preview-release CI job is the only thing that runs it and it
resolves nothing against the workspace.

Fetch it with `pnpm dlx` at the point of use instead. The version is pinned
in the workflow because Renovate does not update `dlx` specifiers, which is
noted next to the call so the pin does not quietly rot.
The root package.json carried @types/node solely so the root tsconfig could
set `types: ["node"]`, and that tsconfig existed solely to cover
`nix/**/*.ts`. With the last of those files now living under
nix/tools/models-dev-gen, both belonged there rather than at the root: no
`*.ts` file sits at the repository root, and apps/ccusage and docs each
declare @types/node themselves.

So the tool directory gets its own tsconfig, standalone like the other two
in this repository, and pins @types/node next to the dependencies it already
pins. gen.ts stays excluded for the same reason the oxlint config ignores
it. The root package.json is left with no devDependencies at all.

`just typecheck` still resolves node types for compact.test.ts, now out of
nix/tools/models-dev-gen/node_modules, which `just gen-bun-nix` populates.
Copilot AI review requested due to automatic review settings July 25, 2026 20:56

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.

@socket-security

socket-security Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​publint@​0.3.121001008188100
Addednpm/​remeda@​2.33.71001008396100
Addednpm/​zod@​3.24.210010010093100

View full report

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 25, 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 1fdc668 Commit Preview URL

Branch Preview URL
Jul 25 2026, 09:11 PM

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR relocates models.dev generation into a Bun-backed Nix tool, adds shared Bun dependency and CLI builders, exposes new package outputs, and updates development, validation, release, publishing, formatting, and cache workflows.

Changes

Nix and Bun tooling migration

Layer / File(s) Summary
Models.dev generator relocation and selection logic
nix/tools/models-dev-gen/*, justfile, nix/git-hooks.nix, .oxlintrc.json, nix/oxlint-check.json
Pricing-key selection and candidate comparison helpers are added, generator files move under nix/tools/models-dev-gen, and related tests, manifests, hooks, and lint paths are updated.
Shared Bun dependency and CLI packaging
flake.nix, nix/bun-*.nix, nix/tools/changelogithub/*, nix/tools/publint/*, nix/dev-shell.nix
bun2nix is added as a flake input; shared derivations package Bun dependencies and wrap changelogithub and publint CLIs.
Bun lockfile generation and repository checks
justfile, nix/checks.nix
Installation and generation recipes plus a flake check keep Bun dependency mappings synchronized.
Package outputs and workflow migration
nix/packages.nix, .github/workflows/*, .github/actions/setup-nix-cache/action.yaml, package.json, pnpm-workspace.yaml, nix/treefmt.nix, CONTRIBUTING.md
Package wiring and workflow commands use the new Nix tools, root release dependencies are removed, formatting exclusions are updated, and cache restoration gains a fallback prefix.

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

Possibly related PRs

Suggested reviewers: copilot, pullfrog

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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 summarizes the main change: refactoring Nix-built JS tooling to use bun2nix.
✨ 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 refactor/bun2nix-js-tools

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.

@pullfrog pullfrog 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.

ℹ️ Minor suggestions only.

Reviewed changes — refactors Nix-built JS tooling (publint, models-dev-pricing generator, changelogithub) from hand-maintained Nix dependency expressions to bun2nix with real bun.lock/bun.nix files.

  • Add nix/bun-node-modules.nix and nix/bun-cli.nix — shared builders that turn nix/tools/* manifests into reproducible node_modules trees and CLI wrappers, with shebang repointing to keep bun out of runtime closures.
  • Restructure tooling under nix/tools/publint, models-dev-gen, and changelogithub each get a self-contained directory with package.json, bun.lock, bun.nix, and default.nix; the old nix/publint.nix and nix/models-dev-pricing.nix are removed.
  • Add bun-nix flake check — fails on bun.lock/bun.nix drift, paired with just gen-bun-nix for regeneration.
  • Remove root devDependencieschangelogithub, pkg-pr-new, and @types/node move out of the pnpm workspace; pkg-pr-new is now fetched via pnpm dlx.
  • Clean up pnpm-lock.yaml — removes the release catalog, the changelogithub>c12 override, and 774 lines of changelogithub/changelogen transitive dependencies.
  • Move @types/node and tsconfig.json to nix/tools/models-dev-gen/ where the last nix/**/*.ts files live; root tsconfig.json no longer includes nix/**/*.ts.
  • Incidental fixes: zizmor 1.27 (ci.yaml parallel-step support), oxlint --no-error-on-unmatched-pattern, nix-store cache fallback restore key.

ℹ️ Nitpicks

  • nix/tools/models-dev-gen/package.json:5 — the description field references the old file path nix/models-dev-gen.ts; after the move it should read gen.ts or nix/tools/models-dev-gen/gen.ts.

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

Comment thread nix/tools/models-dev-gen/package.json Outdated

@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: 2

🤖 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 @.github/workflows/ci.yaml:
- Around line 278-282: Add pkg-pr-new as a root devDependency so it is recorded
in pnpm-lock.yaml, then update the workflow command in the publish step to
invoke it through pnpm exec rather than pnpm dlx, preserving the existing
publish arguments.

In `@nix/tools/models-dev-gen/package.json`:
- Around line 6-12: Move the runtime libraries remeda and zod from dependencies
into devDependencies in the package manifest, keeping their existing versions
and retaining `@types/node` alongside them.
🪄 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: ba9a02e3-53a7-40a9-b214-5496535a919f

📥 Commits

Reviewing files that changed from the base of the PR and between 409b4a5 and f567bc5.

⛔ Files ignored due to path filters (5)
  • flake.lock is excluded by !**/*.lock
  • nix/tools/changelogithub/bun.lock is excluded by !**/*.lock
  • nix/tools/models-dev-gen/bun.lock is excluded by !**/*.lock
  • nix/tools/publint/bun.lock is excluded by !**/*.lock
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (31)
  • .github/actions/setup-nix-cache/action.yaml
  • .github/workflows/ci.yaml
  • .github/workflows/release.yaml
  • .oxlintrc.json
  • flake.nix
  • justfile
  • nix/bun-cli.nix
  • nix/bun-node-modules.nix
  • nix/checks.nix
  • nix/dev-shell.nix
  • nix/git-hooks.nix
  • nix/models-dev-pricing.nix
  • nix/oxlint-check.json
  • nix/packages.nix
  • nix/publint.nix
  • nix/tools/changelogithub/bun.nix
  • nix/tools/changelogithub/default.nix
  • nix/tools/changelogithub/package.json
  • nix/tools/models-dev-gen/bun.nix
  • nix/tools/models-dev-gen/compact.test.ts
  • nix/tools/models-dev-gen/compact.ts
  • nix/tools/models-dev-gen/default.nix
  • nix/tools/models-dev-gen/gen.ts
  • nix/tools/models-dev-gen/package.json
  • nix/tools/models-dev-gen/tsconfig.json
  • nix/tools/publint/bun.nix
  • nix/tools/publint/default.nix
  • nix/tools/publint/package.json
  • nix/treefmt.nix
  • package.json
  • pnpm-workspace.yaml
💤 Files with no reviewable changes (4)
  • nix/publint.nix
  • package.json
  • pnpm-workspace.yaml
  • nix/models-dev-pricing.nix

Comment thread .github/workflows/ci.yaml
Comment thread nix/tools/models-dev-gen/package.json
Both nix/tools manifests described themselves in terms of the file layout
that existed before the move: models-dev-gen pointed at `nix/models-dev-gen.ts`
and publint at `nix/publint.nix`. Neither path exists any more; each tool's
Nix expression and scripts are siblings of the manifest now.

Reported on #1489 by pullfrog for the first of the two; the second is the
same mistake, found by grepping for the pre-rename paths.
Copilot AI review requested due to automatic review settings July 25, 2026 21:03

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.

@pkg-pr-new

pkg-pr-new Bot commented Jul 25, 2026

Copy link
Copy Markdown

Open in StackBlitz

ccusage

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

@ccusage/ccusage-darwin-arm64

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

@ccusage/ccusage-darwin-x64

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

@ccusage/ccusage-linux-arm64

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

@ccusage/ccusage-linux-x64

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

@ccusage/ccusage-win32-x64

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

commit: 1fdc668

@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

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

Comment thread nix/packages.nix
Comment thread nix/tools/publint/package.json
@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: f567bc53ee1b
Base SHA: 409b4a530f05

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 339.6ms 2.96 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 300.1ms 3.35 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 104.7ms 9.62 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 84.7ms 11.89 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 29.4ms 5.1ms 5.77x 54.75 MiB 12.46 MiB 0.23x 0.05 MiB/s 0.30 MiB/s
claude session --offline --json 0.00 MiB 28.7ms 3.0ms 9.73x 55.00 MiB 12.46 MiB 0.23x 0.05 MiB/s 0.52 MiB/s
codex daily --offline --json 0.00 MiB 22.7ms 2.5ms 9.28x 55.00 MiB 10.46 MiB 0.19x 0.04 MiB/s 0.35 MiB/s
codex session --offline --json 0.00 MiB 22.6ms 2.3ms 9.82x 55.00 MiB 10.46 MiB 0.19x 0.04 MiB/s 0.37 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 354.9ms 314.8ms 1.13x 930.59 MiB 954.60 MiB 1.03x 2.84 GiB/s 3.20 GiB/s
codex --offline --json 1.01 GiB 107.2ms 86.6ms 1.24x 430.93 MiB 418.91 MiB 0.97x 9.39 GiB/s 11.63 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 4134.75 KiB 4134.69 KiB -0.06 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: f567bc53ee1b
Base SHA: 409b4a530f05

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 343.5ms 2.93 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 325.3ms 3.09 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 110.0ms 9.15 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 82.9ms 12.15 GiB/s 1

Committed fixture performance

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

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

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 29.7ms 27.3ms 1.09x 55.00 MiB 55.00 MiB 1.00x 0.05 MiB/s 0.06 MiB/s
claude session --offline --json 0.00 MiB 24.8ms 26.2ms 0.95x 55.00 MiB 55.00 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
codex daily --offline --json 0.00 MiB 26.2ms 24.5ms 1.07x 55.25 MiB 55.00 MiB 1.00x 0.03 MiB/s 0.04 MiB/s
codex session --offline --json 0.00 MiB 22.1ms 23.2ms 0.95x 55.25 MiB 55.00 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 380.1ms 361.6ms 1.05x 952.59 MiB 946.60 MiB 0.99x 2.65 GiB/s 2.78 GiB/s
codex --offline --json 1.01 GiB 119.3ms 105.7ms 1.13x 440.92 MiB 418.91 MiB 0.95x 8.44 GiB/s 9.52 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 4134.75 KiB 4134.69 KiB -0.06 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.

CONTRIBUTING tells contributors to run `just typecheck`, and moving
@types/node into nix/tools/models-dev-gen broke that on a fresh checkout:
oxlint resolves that directory's types out of its own node_modules, which
nothing created. `pnpm install` does not cover it, since the tool
directories sit outside the pnpm workspace.

Consolidate setup into `just install`: the workspace install plus a
`bun install --frozen-lockfile` for every tool directory carrying a
tsconfig. Nix builds each tool's dependencies itself, so the ones with no
TypeScript in them need nothing locally and are skipped.

`git wt`'s hook now calls the recipe instead of running pnpm directly, so
new worktrees stay usable without a manual step, and CONTRIBUTING lists it
ahead of the checks it is a prerequisite for.
Copilot AI review requested due to automatic review settings July 25, 2026 21:10

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.

@pullfrog pullfrog 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 new issues found.

Reviewed changes — one new commit adds a just install recipe and integrates it into the contributor workflow.

  • Added just install recipe — runs pnpm install --frozen-lockfile plus bun install --frozen-lockfile for each nix/tools/*/tsconfig.json directory, so just typecheck works on a fresh checkout.
  • Updated CONTRIBUTING.mdjust install is now the first step in the pre-submit checklist, with a note that it's only needed once per checkout and that git wt runs it automatically.
  • Expanded git wt hook in nix/dev-shell.nix — changed from bare pnpm install to just install, so worktrees created by git wt are typecheck-ready.

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 1697e0f1166d
Base SHA: 409b4a530f05

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 358.2ms 2.81 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 304.4ms 3.31 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 116.2ms 8.66 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 86.3ms 11.66 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.6ms 5.0ms 5.33x 55.00 MiB 12.46 MiB 0.23x 0.06 MiB/s 0.31 MiB/s
claude session --offline --json 0.00 MiB 27.7ms 2.9ms 9.66x 55.00 MiB 12.45 MiB 0.23x 0.06 MiB/s 0.54 MiB/s
codex daily --offline --json 0.00 MiB 23.8ms 2.5ms 9.60x 55.00 MiB 10.46 MiB 0.19x 0.04 MiB/s 0.35 MiB/s
codex session --offline --json 0.00 MiB 25.7ms 2.4ms 10.51x 55.25 MiB 10.46 MiB 0.19x 0.03 MiB/s 0.35 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 370.2ms 322.3ms 1.15x 938.59 MiB 954.59 MiB 1.02x 2.72 GiB/s 3.12 GiB/s
codex --offline --json 1.01 GiB 115.1ms 90.3ms 1.28x 438.92 MiB 426.91 MiB 0.97x 8.74 GiB/s 11.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 4134.75 KiB 4134.69 KiB -0.06 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: 1697e0f1166d
Base SHA: 409b4a530f05

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 363.9ms 2.77 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 340.0ms 2.96 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 113.2ms 8.89 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 93.7ms 10.74 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.8ms 26.5ms 1.09x 55.00 MiB 55.00 MiB 1.00x 0.05 MiB/s 0.06 MiB/s
claude session --offline --json 0.00 MiB 28.1ms 25.9ms 1.08x 55.25 MiB 55.00 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
codex daily --offline --json 0.00 MiB 23.9ms 24.4ms 0.98x 55.00 MiB 55.00 MiB 1.00x 0.04 MiB/s 0.04 MiB/s
codex session --offline --json 0.00 MiB 23.2ms 23.7ms 0.98x 55.00 MiB 55.25 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 388.9ms 356.7ms 1.09x 932.59 MiB 948.60 MiB 1.02x 2.59 GiB/s 2.82 GiB/s
codex --offline --json 1.01 GiB 109.9ms 115.8ms 0.95x 444.91 MiB 442.93 MiB 1.00x 9.16 GiB/s 8.69 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 4134.75 KiB 4134.69 KiB -0.06 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: 1fdc6681d0bb
Base SHA: 409b4a530f05

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 353.1ms 2.85 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 335.9ms 3.00 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 118.4ms 8.50 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 89.6ms 11.23 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.7ms 4.1ms 6.56x 54.75 MiB 12.46 MiB 0.23x 0.06 MiB/s 0.38 MiB/s
claude session --offline --json 0.00 MiB 24.5ms 2.7ms 9.02x 55.25 MiB 12.45 MiB 0.23x 0.06 MiB/s 0.57 MiB/s
codex daily --offline --json 0.00 MiB 24.1ms 3.2ms 7.55x 55.00 MiB 10.46 MiB 0.19x 0.04 MiB/s 0.27 MiB/s
codex session --offline --json 0.00 MiB 23.8ms 2.4ms 9.96x 55.00 MiB 10.46 MiB 0.19x 0.04 MiB/s 0.36 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 370.0ms 336.5ms 1.10x 946.60 MiB 948.60 MiB 1.00x 2.72 GiB/s 2.99 GiB/s
codex --offline --json 1.01 GiB 109.7ms 90.5ms 1.21x 416.91 MiB 412.92 MiB 0.99x 9.17 GiB/s 11.12 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 4134.75 KiB 4134.69 KiB -0.06 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: 1fdc6681d0bb
Base SHA: 409b4a530f05

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 347.7ms 2.90 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 334.6ms 3.01 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 107.1ms 9.40 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 83.4ms 12.07 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 25.3ms 25.2ms 1.00x 55.00 MiB 55.25 MiB 1.00x 0.06 MiB/s 0.06 MiB/s
claude session --offline --json 0.00 MiB 25.1ms 24.8ms 1.01x 54.75 MiB 55.25 MiB 1.01x 0.06 MiB/s 0.06 MiB/s
codex daily --offline --json 0.00 MiB 26.4ms 22.7ms 1.16x 55.00 MiB 55.00 MiB 1.00x 0.03 MiB/s 0.04 MiB/s
codex session --offline --json 0.00 MiB 25.8ms 24.0ms 1.08x 55.00 MiB 55.00 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 364.6ms 359.3ms 1.01x 954.60 MiB 948.59 MiB 0.99x 2.76 GiB/s 2.80 GiB/s
codex --offline --json 1.01 GiB 109.3ms 114.4ms 0.95x 456.93 MiB 436.92 MiB 0.96x 9.21 GiB/s 8.80 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 4134.75 KiB 4134.69 KiB -0.06 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 df89eb7 into main Jul 26, 2026
37 checks passed
@ryoppippi
ryoppippi deleted the refactor/bun2nix-js-tools branch July 26, 2026 20:25
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.

2 participants