Repository navigation
perf(release): publish without the Nix dev shell - #1257
Conversation
The publish build ran `generate:schema`, which compiles and runs the Rust `generate-config-schema` binary on every `pnpm publish` and pkg-pr-new pack. The committed apps/ccusage/config-schema.json is already kept in sync with the Rust source by the `nix flake check` schema-drift check, so regenerating it during packaging is redundant: it adds cargo build time and a hard Rust toolchain dependency to the publish path. `build` now runs only `tsdown` and `ensure:native-binary`. The `generate:schema` script stays for local regeneration (`pnpm --filter ccusage run generate:schema` and `just schema`).
The npm publish job runs on a GitHub-hosted runner (required for npm provenance, which rejects self-hosted/Blacksmith runners), so it never gets the Blacksmith sticky-disk Nix cache and re-downloaded the full dev shell (Rust toolchain, litellm, etc.) from cache.nixos.org on every release — ~5 minutes of the ~7-minute job for a task that only needs node, pnpm and bun. Now that the publish build no longer invokes cargo, drop `nix develop` and set up the toolchain directly: pnpm/action-setup (reads packageManager), setup-node, then `pnpm install --frozen-lockfile`, which downloads the bun runtime declared in engines.runtime so the `ensure:native-binary` script resolves it from node_modules/.bin during packaging.
The sticky-disk key was shared across every Linux job of the same arch. A sticky disk clones the last committed snapshot and re-commits on completion, so jobs that realize different Nix closures (a full dev shell vs. a single `nix build`) overwrote each other's store on the shared key, forcing cold re-downloads from cache.nixos.org — the source of the large run-to-run variance in pkg-pr-new (149s vs 388s). Key the disk by `github.job` so each closure stays warm independently.
📝 WalkthroughWalkthroughThe PR updates CI/build infra: per-job Blacksmith sticky disk cache keying, the npm release job now installs pnpm via Nix and publishes directly with pnpm, and the ccusage build script removes schema generation. ChangesCI/CD and build infrastructure updates
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ccusage-guide | e4b2d57 | Commit Preview URL Branch Preview URL |
Jun 10 2026, 10:40 PM |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/release.yaml:
- Line 104: The workflow step using actions/setup-node is configured with
registry-url which causes an .npmrc to be written with
//_authToken=${NODE_AUTH_TOKEN}, breaking OIDC Trusted Publishing when
NODE_AUTH_TOKEN is unset; to fix, stop writing that token by removing the
registry-url input (or otherwise avoid creating an authToken entry) from the
actions/setup-node step so the publish run (pnpm ... publish --provenance) can
use OIDC id-token authentication; update the setup-node configuration (the
actions/setup-node invocation) and ensure the publish run command (the pnpm
--filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance
--no-git-checks --access public line) remains unchanged.
🪄 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: 5edd1fa4-82a8-4cc9-830c-dd8c937d19c9
📒 Files selected for processing (3)
.github/actions/setup-linux-blacksmith-sticky-disk/action.yaml.github/workflows/release.yamlapps/ccusage/package.json
| tar -xf "$archive" | ||
| done | ||
| - run: nix develop --command pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance --no-git-checks --access public | ||
| - run: pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance --no-git-checks --access public |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show relevant parts of release workflow around the publish step
ls -la .github/workflows || true
sed -n '1,220p' .github/workflows/release.yaml | nl -ba | sed -n '60,180p'
# Check for other publish/auth wiring in the repo (other workflows)
rg -n --hidden --glob '!.git/*' "setup-node|registry-url|NODE_AUTH_TOKEN|NPM_TOKEN|NPM_AUTH_TOKEN|npmrc|auth" .github/workflows
# Show pnpm config if present (may affect auth)
ls -la . || true
ls -la .npmrc pnpm-workspace.yaml package.json . || true
test -f .npmrc && nl -ba .npmrc || true
test -f pnpm-workspace.yaml && nl -ba pnpm-workspace.yaml || trueRepository: ccusage/ccusage
Length of output: 826
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== release.yaml (relevant sections) =="
# Show workflow with line numbers using cat -n (preferred over nl)
cat -n .github/workflows/release.yaml | sed -n '1,220p'
echo
echo "== Search for npm auth wiring in workflows =="
rg -n --hidden --glob '!.git/*' \
"setup-node|registry-url|NODE_AUTH_TOKEN|NPM_TOKEN|NPM_AUTH_TOKEN|npmrc|auth" \
.github/workflows
echo
echo "== Show any .npmrc in repo root =="
ls -la .npmrc || true
test -f .npmrc && cat -n .npmrc || true
echo
echo "== Check pnpm publish config/package.json for npm auth hints =="
ls -la package.json || true
test -f package.json && rg -n "publish|access|provenance|npm|registry" package.json || trueRepository: ccusage/ccusage
Length of output: 5783
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Search release.yaml for NODE_AUTH_TOKEN / NPM_TOKEN =="
rg -n "NODE_AUTH_TOKEN|NPM_TOKEN|NPM_AUTH_TOKEN|provenance|trusted" .github/workflows/release.yaml
echo "== Inspect actions/ setup-nix (in case it sets npm auth) =="
rg -n "npm|pnpm.*config|NODE_AUTH_TOKEN|NPM_TOKEN|registry.npmjs.org" .github/actions -S || true
# Show the setup-nix action entrypoint files
fd -td f "setup-nix" .github/actions || true
ls -la .github/actions || true
find .github/actions -maxdepth 2 -type f -print | head -n 80Repository: ccusage/ccusage
Length of output: 1652
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== package.json publishConfig (if any) =="
cat package.json | sed -n '1,120p'
rg -n "\"publishConfig\"|registry|access|provenance|token|auth" package.json
echo
echo "== release.yaml npm job full permissions/steps (around pnpm publish) =="
# print the npm job only, roughly lines 70-120
cat -n .github/workflows/release.yaml | sed -n '70,140p'
echo
echo "== Inspect .github/actions/setup-nix/action.yaml =="
cat .github/actions/setup-nix/action.yaml
echo
echo "== Search for npm auth usage in actions (NODE_AUTH_TOKEN/NPM_TOKEN/token usage) =="
rg -n "NODE_AUTH_TOKEN|NPM_TOKEN|NPM_AUTH_TOKEN|npmrc|authToken|provenance|id-token|registry.npmjs.org|setup-node" .github/actions -SRepository: ccusage/ccusage
Length of output: 722
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== release.yaml npm job excerpt (lines ~70-130) =="
cat -n .github/workflows/release.yaml | sed -n '70,130p' || true
echo
echo "== release.yaml npm job permissions/steps detail (search for env) =="
cat -n .github/workflows/release.yaml | sed -n '70,120p' | rg -n "env:|secrets\.|NPM|NODE|token|registry-url|provenance|id-token" || true
echo
echo "== Inspect .github/actions/setup-nix/action.yaml =="
cat .github/actions/setup-nix/action.yaml
echo
echo "== Search for npm/pnpm auth related strings in actions/setup-nix =="
rg -n "NODE_AUTH_TOKEN|NPM_TOKEN|NPM_AUTH_TOKEN|authToken|registry.npmjs.org|npmrc|provenance|id-token|pnpm config set" .github/actions/setup-nix/action.yaml || trueRepository: ccusage/ccusage
Length of output: 3538
🌐 Web query:
actions/setup-node registry-url trusted publishing OIDC NODE_AUTH_TOKEN required
💡 Result:
When using Trusted Publishing (OIDC) with actions/setup-node to publish to npm, you do not need to provide a NODE_AUTH_TOKEN [1][2]. In fact, configuring a NODE_AUTH_TOKEN is specifically intended for classic token-based authentication and is not required for OIDC flows [1][2]. Key implementation details: 1. Requirements: You must use Node.js 24 or newer (which includes npm ≥ 11.5.1), as older versions may lack native support for the OIDC flow [1][2]. 2. OIDC Permissions: Your workflow must explicitly grant the id-token: write permission [1]. 3. Interaction with registry-url: When you use the registry-url input in actions/setup-node, the action automatically writes a line to the local.npmrc file that uses the ${NODE_AUTH_TOKEN} environment variable [3][4]. 4. Troubleshooting: Because this.npmrc configuration exists, some users report that if NODE_AUTH_TOKEN is unset, the npm CLI may incorrectly attempt classic authentication with empty credentials instead of triggering the OIDC flow, leading to ENEEDAUTH or 404 errors [3][4]. If you encounter these errors despite correct OIDC configuration, the recommended workaround is to explicitly unset or clear the NODE_AUTH_TOKEN environment variable for the specific step where you run npm publish [5][2]. You can do this by running: - run: NODE_AUTH_TOKEN="" npm publish [5] This ensures that the npm CLI does not mistakenly detect an empty token and instead proceeds to use the OIDC flow [5][2].
Citations:
- 1: actions/setup-node@670825a
- 2: Don't default NPM_AUTH_TOKEN to support NPM OIDC actions/setup-node#1440
- 3: actions/setup-node registry-url interferes with OIDC trigger — example workflow fails with ENEEDAUTH when no NODE_AUTH_TOKEN npm/documentation#1960
- 4: registry-url writes _authToken line that breaks npm Trusted Publisher OIDC when no NODE_AUTH_TOKEN is set actions/setup-node#1551
- 5: Don't default NPM_AUTH_TOKEN to support NPM OIDC actions/setup-node#1440
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Search for publishConfig/authToken/NODE_AUTH_TOKEN usage in repo =="
rg -n --hidden --glob '!.git/*' \
"publishConfig|authToken|NODE_AUTH_TOKEN|NPM_TOKEN|NPM_AUTH_TOKEN|registry\.npmjs\.org|_authToken" \
apps packages .github || true
echo
echo "== Search for provenance usage in pnpm/yaml/package files =="
rg -n --hidden --glob '!.git/*' \
"provenance" \
apps packages .github || true
echo
echo "== List package.json files under packages/ccusage-* (top-level excerpt only) =="
fd -e package.json "packages/ccusage-" -a || true
# fallback: just search by filename
fd -td f "package.json" packages | head -n 50Repository: ccusage/ccusage
Length of output: 1430
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== apps/ccusage/package.json (publishConfig excerpt) =="
cat apps/ccusage/package.json | sed -n '1,120p' | rg -n "publishConfig|registry|access|provenance|authToken|token" -n || true
cat apps/ccusage/package.json | sed -n '1,80p'
echo
echo "== packages/ccusage-linux-x64/package.json (publishConfig excerpt) =="
cat packages/ccusage-linux-x64/package.json | sed -n '1,120p' | rg -n "publishConfig|registry|access|provenance|authToken|token" -n || true
cat packages/ccusage-linux-x64/package.json | sed -n '1,80p'
echo
echo "== packages/ccusage-win32-x64/package.json (publishConfig excerpt) =="
cat packages/ccusage-win32-x64/package.json | sed -n '1,120p' | rg -n "publishConfig|registry|access|provenance|authToken|token" -n || true
cat packages/ccusage-win32-x64/package.json | sed -n '1,80p'Repository: ccusage/ccusage
Length of output: 4447
🌐 Web query:
actions/setup-node trusted publishing provenance NODE_AUTH_TOKEN unset .npmrc ${NODE_AUTH_TOKEN} behavior
💡 Result:
When using actions/setup-node with the registry-url input, the action automatically generates an .npmrc file containing a placeholder for authentication: //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN} [1][2][3]. This behavior is designed to support classic token-based authentication [1]. However, this can interfere with npm Trusted Publishing (OIDC) workflows [1][2]. When NODE_AUTH_TOKEN is not explicitly set (which is the intended state for Trusted Publishing), the ${NODE_AUTH_TOKEN} placeholder expands to an empty string [2]. Some versions of the npm CLI interpret the presence of the _authToken= line in .npmrc as evidence that auth is already configured, causing the CLI to attempt a classic publish with empty credentials rather than initiating the OIDC token exchange, often resulting in ENEEDAUTH or E404 errors [1][2]. To address this, the following approaches are recommended: 1. Unset or clear the token: You can explicitly unset the NODE_AUTH_TOKEN environment variable before running npm publish to ensure the npm CLI does not see it as configured [4]. run: NODE_AUTH_TOKEN="" npm publish 2. Use a modern npm version: npm versions 11.5.1 and higher (typically bundled with Node.js 24+) have improved support for the OIDC flow, which may mitigate or resolve the conflict depending on the exact environment and CLI version [4][5]. 3. Avoid registry-url if not required: If you do not need the action to configure your registry and auth settings for other steps, omitting the registry-url input prevents the automatic creation of the .npmrc file [6]. For ongoing updates, the actions/setup-node maintainers have discussed refining this behavior to avoid setting dummy tokens by default, aiming to better support OIDC workflows [7]. Always ensure you have the id-token: write permission configured in your workflow for Trusted Publishing to function [8][5].
Citations:
- 1: registry-url writes _authToken line that breaks npm Trusted Publisher OIDC when no NODE_AUTH_TOKEN is set actions/setup-node#1551
- 2: actions/setup-node registry-url interferes with OIDC trigger — example workflow fails with ENEEDAUTH when no NODE_AUTH_TOKEN npm/documentation#1960
- 3: https://github.com/actions/setup-node/blob/main/src/authutil.ts
- 4: Don't default NPM_AUTH_TOKEN to support NPM OIDC actions/setup-node#1440
- 5: actions/setup-node@670825a
- 6: https://github.com/actions/setup-node/blob/main/README.md
- 7: Don't default NPM_AUTH_TOKEN to support NPM OIDC actions/setup-node#1440
- 8: https://github.com/npm/documentation/blob/main/content/packages-and-modules/securing-your-code/trusted-publishers.mdx
Fix possible npm Trusted Publishing (OIDC) breakage in release.yaml publish step
The workflow grants id-token: write and publishes with --provenance, so it’s set up for npm Trusted Publishing (no token should be required). However, actions/setup-node is configured with registry-url, which creates an .npmrc containing //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}; since NODE_AUTH_TOKEN isn’t set, npm can fall back to classic auth with empty credentials and the publish may fail.
🔧 Proposed fix
- - run: pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance --no-git-checks --access public
+ - run: pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance --no-git-checks --access public
+ env:
+ NODE_AUTH_TOKEN: ""📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - run: pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance --no-git-checks --access public | |
| - run: pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance --no-git-checks --access public | |
| env: | |
| NODE_AUTH_TOKEN: "" |
🤖 Prompt for 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.
In @.github/workflows/release.yaml at line 104, The workflow step using
actions/setup-node is configured with registry-url which causes an .npmrc to be
written with //_authToken=${NODE_AUTH_TOKEN}, breaking OIDC Trusted Publishing
when NODE_AUTH_TOKEN is unset; to fix, stop writing that token by removing the
registry-url input (or otherwise avoid creating an authToken entry) from the
actions/setup-node step so the publish run (pnpm ... publish --provenance) can
use OIDC id-token authentication; update the setup-node configuration (the
actions/setup-node invocation) and ensure the publish run command (the pnpm
--filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance
--no-git-checks --access public line) remains unchanged.
ccusage
@ccusage/ccusage-darwin-arm64
@ccusage/ccusage-linux-arm64
@ccusage/ccusage-linux-x64
@ccusage/ccusage-win32-x64
commit: |
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. Package runner startupExecution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one
Cached bunx execution performanceRuns the same large fixture through Fixtures: Claude
Package runtime diagnosticsCompares 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
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated 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
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
ccusage performance comparisonPR SHA: This compares the PR package against the configured base package on the same CI runner. Package runner startupExecution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one
Cached bunx execution performanceRuns the same large fixture through Fixtures: Claude
Package runtime diagnosticsCompares 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
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated 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
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
Replace pnpm/action-setup with `nix profile install --inputs-from . nixpkgs#pnpm` so the publish toolchain is pinned to the flake's locked nixpkgs (pnpm 11.1.1, identical to the dev shell) instead of a separate action's resolution, while still avoiding the full `nix develop` dev shell that made the job slow. setup-node stays solely for the npm publish configuration (registry + OIDC provenance .npmrc wiring); the locked nixpkgs node is below the engines floor, so node is sourced from setup-node. bun is not installed here — `pnpm install` downloads it via engines.runtime into node_modules/.bin, where the prepack `ensure:native-binary` script resolves it.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
.github/workflows/release.yaml (1)
105-105:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix possible npm Trusted Publishing (OIDC) breakage in release.yaml publish step
The workflow grants
id-token: writeand publishes with--provenance, indicating npm Trusted Publishing (OIDC) is intended. However,actions/setup-nodeis configured withregistry-url(line 90), which creates an.npmrccontaining//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}. SinceNODE_AUTH_TOKENis not set, npm may fall back to classic authentication with empty credentials, causing the publish to fail withENEEDAUTHorE404errors instead of using the OIDC flow.🔧 Proposed fix
- - run: pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance --no-git-checks --access public + - run: pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance --no-git-checks --access public + env: + NODE_AUTH_TOKEN: ""🤖 Prompt for 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. In @.github/workflows/release.yaml at line 105, The publish step is set to use OIDC (--provenance + id-token: write) but actions/setup-node is configured with registry-url which causes an .npmrc to be written with //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}, breaking OIDC; update the workflow to stop creating an authToken entry by removing or not setting the registry-url input on actions/setup-node (or set its npmAlwaysAuth / always-auth equivalent to false) so the OIDC flow is used, and keep the publish command (the pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*' publish --provenance --no-git-checks --access public) unchanged.
🤖 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/release.yaml:
- Line 91: The release workflow uses node-version: lts/* which can drift and may
not satisfy the project's engines.runtime[].node.version (^24.15.0) in
package.json; update the release workflow's node-version setting (the
node-version key in the release workflow) to a pinned 24 series (e.g., '24' or
'24.x') so the CI runs on Node 24 and aligns with
engines.runtime[].node.version.
---
Duplicate comments:
In @.github/workflows/release.yaml:
- Line 105: The publish step is set to use OIDC (--provenance + id-token: write)
but actions/setup-node is configured with registry-url which causes an .npmrc to
be written with //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}, breaking
OIDC; update the workflow to stop creating an authToken entry by removing or not
setting the registry-url input on actions/setup-node (or set its npmAlwaysAuth /
always-auth equivalent to false) so the OIDC flow is used, and keep the publish
command (the pnpm --filter='./apps/ccusage' --filter='./packages/ccusage-*'
publish --provenance --no-git-checks --access public) unchanged.
🪄 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: 55a1baf3-d6a4-4f15-b881-fae7fa42fcc6
📒 Files selected for processing (1)
.github/workflows/release.yaml
| @@ -90,6 +90,8 @@ jobs: | |||
| registry-url: 'https://registry.npmjs.org' | |||
| node-version: lts/* | |||
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check package.json engines field and verify Node LTS compatibility
echo "== Project Node version requirements =="
rg -n "\"engines\":" -A 5 package.json apps/ccusage/package.json
echo ""
echo "== Current Node LTS version (for reference) =="
echo "As of June 2026, Node LTS is 22.x; Node 24 is recommended for OIDC provenance"Repository: ccusage/ccusage
Length of output: 427
Align Node version in release workflow with engines.node (^24.15.0)
.github/workflows/release.yamlusesnode-version: lts/*(line 91), butpackage.jsondeclaresengines.runtime[].node.version: ^24.15.0; LTS may not satisfy it.- Pin the workflow to
node-version: '24'(or24.x) instead oflts/*to match the project requirement.
🤖 Prompt for 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.
In @.github/workflows/release.yaml at line 91, The release workflow uses
node-version: lts/* which can drift and may not satisfy the project's
engines.runtime[].node.version (^24.15.0) in package.json; update the release
workflow's node-version setting (the node-version key in the release workflow)
to a pinned 24 series (e.g., '24' or '24.x') so the CI runs on Node 24 and
aligns with engines.runtime[].node.version.
Code Coverage OverviewLanguages: Rust Rust / code-coverage/cargo-llvm-covThe overall coverage in the Show a code coverage summary of the most covered files.
Code Coverage is in Public Preview. Learn more and provide us with your feedback. |
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. Package runner startupExecution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one
Cached bunx execution performanceRuns the same large fixture through Fixtures: Claude
Package runtime diagnosticsCompares 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
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated 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
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
ccusage performance comparisonPR SHA: This compares the PR package against the configured base package on the same CI runner. Package runner startupExecution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one
Cached bunx execution performanceRuns the same large fixture through Fixtures: Claude
Package runtime diagnosticsCompares 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
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated 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
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
Summary
The
npm publishrelease job took ~7m, of which ~5m wasnix developre-downloading the entire dev shell (Rust toolchain, litellm, typescript-go, …) from cache.nixos.org just to runpnpm publish. That job runs on a GitHub-hosted runner — required for npm provenance, which rejects self-hosted/Blacksmith runners — so it can never get the Blacksmith sticky-disk Nix cache and pays the full download every release. This PR removes the dev shell from the publish path and fixes a sticky-disk key collision that caused the same cold re-downloads (and large variance) on the Blacksmithpkg-pr-newjob.What changed
apps/ccusage/package.json).buildno longer runsgenerate:schema, which compiled and ran the Rustgenerate-config-schemabinary on every publish / pkg-pr-new pack. The committedconfig-schema.jsonis already kept in sync with the Rust source by thenix flake checkschema-drift check, so regenerating it during packaging is redundant — and it was the only Rust dependency left in the publish path.buildnow runs onlytsdownandensure:native-binary; thegenerate:schemascript stays for local use (just schema)..github/workflows/release.yaml). Instead ofnix develop --command pnpm … publish(full dev shell), keep the lightweightsetup-nix(Nix install only) and provision just pnpm withnix profile install --inputs-from . nixpkgs#pnpm— pinned to the flake's locked nixpkgs (11.1.1, same as the dev shell).setup-nodestays only for the npm publish configuration (registry + OIDC provenance.npmrcwiring): the locked nixpkgs node is below theenginesfloor, so node is sourced fromsetup-node.bunis not installed explicitly —pnpm installdownloads it viaengines.runtimeintonode_modules/.bin, where the prepackensure:native-binaryscript resolves it..github/actions/setup-linux-blacksmith-sticky-disk/action.yaml). The key was shared across every Linux job of the same arch; a sticky disk clones the last committed snapshot and re-commits on completion, so jobs with different Nix closures overwrote each other's store, forcing cold re-downloads. This was the source of thepkg-pr-newrun-to-run variance (149s vs 388s). Keying bygithub.jobkeeps each closure warm independently.pkg-pr-newkeeps its Nix dev shell but no longer recompiles Rust during prepack (first change) and gets a stable warm cache.Why
pnpm publishonly needs node, pnpm and bun. Pulling a full Rust dev shell — or recompiling the config schema — on the publish path was pure overhead, and no caching backend helps because the cost is the size of the closure on a cold miss, not where it's cached. A minimalnix profile install nixpkgs#pnpmkeeps the version pinned to the same nixpkgs as the dev shell while making the job consistently fast.Testing / validation
actionlintandzizmorclean onrelease.yaml(only the 2 pre-existingexcessive-permissionswarnings remain);treefmtclean; pre-commit hooks pass.nix profile install-style provisioning resolves against the locked nixpkgs:nixpkgs#pnpm→ 11.1.1 (==pnpm_11),nixpkgs#bun→ 1.3.13,nixpkgs#nodejs_24→ 24.14.1 (belowengines^24.15.0 — hence node stays onsetup-node).ensure:native-binaryexits before its cargo fallback when the native artifacts are restored (linux-arm64 binary present, correct version, static) — so the publish path needs no cargo.Note
release.yamlonly runs on tag push, so this path is not exercised by PR CI — it will be validated on the next release. The sticky-disk key change makes all Blacksmith jobs cold once (one-time re-warm).Summary by CodeRabbit