Repository navigation
build: add publint flake check - #1312
Conversation
Package publint through Nix using the repository pnpm lockfile so the dev shell and flake checks do not depend on a local pnpm install for this tool. Remove clean-pkg-json from package scripts and workspace dependencies because the package manifests now only need publint validation before publish. The new flake check enumerates every package.json and runs publint for each package root, seeding placeholder files for generated publish artifacts so metadata checks can run without a full package build.
…ke-check # Conflicts: # apps/ccusage/package.json # justfile
|
no API key found — this repo is configured to use To fix: add the key as a GitHub Actions secret (referenced from your workflow's Open repo secrets → · Configure model → · Setup docs → · Ask in Discord →
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthroughPackages publint in Nix, adds it to the dev shell and repo checks, removes the workspace ChangesPublint Integration and clean-pkg-json Removal
Sequence Diagram(s)No sequence diagrams generated. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
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 unit tests (beta)
Comment |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ccusage-guide | b486a97 | Commit Preview URL Branch Preview URL |
Jun 13 2026, 12:52 PM |
Co-authored-by: Codesmith <[email protected]>
ccusage
@ccusage/ccusage-darwin-arm64
@ccusage/ccusage-darwin-x64
@ccusage/ccusage-linux-arm64
@ccusage/ccusage-linux-x64
@ccusage/ccusage-win32-x64
commit: |
There was a problem hiding this comment.
2 issues found and verified against the latest diff
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. 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 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. |
Co-authored-by: Codesmith <[email protected]>
|
no API key found — this repo is configured to use To fix: add the key as a GitHub Actions secret (referenced from your workflow's Open repo secrets → · Configure model → · Setup docs → · Ask in Discord →
|
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. 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 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. |
Build the Nix publint tool from a synthetic pnpm project instead of the repository workspace manifests and lockfile. This keeps the tool package independent from apps/ccusage/package.json while still using pnpm to fetch and install publint.
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. 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 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. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
nix/checks.nix (1)
140-181:⚠️ Potential issue | 🟡 MinorLimit
publintinputs to pnpm workspace packages (exclude repo rootpackage.json)
fd --type f '^package\.json$' .matches./package.json(repo root) in addition to the pnpm workspace globs (apps/*,docs,packages/*). If CI is intended to lint only workspace package roots, filterpackageManifeststo those globs (or explicitly exclude the repo root) before runningpublint.🤖 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 `@nix/checks.nix` around lines 140 - 181, The package discovery currently collects the repo root package.json because mapfile into packageManifests uses fd --type f '^package\.json$' ., so update the discovery to only include workspace package roots (or explicitly drop the repo root) before running publint: either change the fd invocation to search only the workspace globs (e.g., restrict to apps/*, docs, packages/*) or post-filter the packageManifests array to remove "./package.json" (or the repo-root path); ensure the rest of the script (the for loop iterating packageManifests and the publint run "$packageDir" --pack false invocation) remains unchanged so generatedArtifacts handling and touchGeneratedFile behavior still apply.
🧹 Nitpick comments (1)
nix/checks.nix (1)
146-173: ⚡ Quick winDerive placeholder executables from each manifest instead of package-name switches.
generatedArtifactsduplicates the publish contract that already lives inpackage.json, so a package rename orbinpath change now needs a second edit here or CI starts failing. Readingbinfrom the manifest keeps the check aligned automatically.♻️ Suggested direction
- const generatedArtifacts = new Map([ - ["`@ccusage/ccusage-darwin-arm64`", ["bin/ccusage"]], - ["`@ccusage/ccusage-darwin-x64`", ["bin/ccusage"]], - ["`@ccusage/ccusage-linux-arm64`", ["bin/ccusage"]], - ["`@ccusage/ccusage-linux-x64`", ["bin/ccusage"]], - ["`@ccusage/ccusage-win32-arm64`", ["bin/ccusage.exe"]], - ["`@ccusage/ccusage-win32-x64`", ["bin/ccusage.exe"]], - ]); + function manifestBinPaths(packageJson) { + if (typeof packageJson.bin === "string") { + return [packageJson.bin]; + } + + if (packageJson.bin && typeof packageJson.bin === "object") { + return Object.values(packageJson.bin); + } + + return []; + } function touchGeneratedFile(packageDir, relativePath) { const targetPath = path.join(packageDir, relativePath); fs.mkdirSync(path.dirname(targetPath), { recursive: true }); if (!fs.existsSync(targetPath)) { fs.writeFileSync(targetPath, ""); } if (!relativePath.endsWith(".exe")) { fs.chmodSync(targetPath, 0o755); } } for (const manifestPath of process.argv.slice(2)) { const packageDir = path.dirname(manifestPath); const packageJson = JSON.parse(fs.readFileSync(manifestPath, "utf8")); const files = new Set(packageJson.files ?? []); - for (const relativePath of generatedArtifacts.get(packageJson.name) ?? []) { - if (files.has(relativePath)) { + for (const relativePath of manifestBinPaths(packageJson)) { + if (files.size === 0 || files.has(relativePath)) { touchGeneratedFile(packageDir, relativePath); } } }🤖 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 `@nix/checks.nix` around lines 146 - 173, The code currently hardcodes generatedArtifacts and duplicates the package.json publish contract; replace that with logic that reads packageJson.bin from each manifest and derives the relative executable paths dynamically. In the loop that processes each manifestPath (the block using packageDir, packageJson and files), remove the generatedArtifacts.get(...) lookup and instead: inspect packageJson.bin (handle string form and object form), collect the bin target paths (the values when bin is an object, or the single string when bin is a string), then for each derived relativePath call touchGeneratedFile(packageDir, relativePath) only if files.has(relativePath) (same gating as before). Keep touchGeneratedFile and its chmod behavior 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.
Outside diff comments:
In `@nix/checks.nix`:
- Around line 140-181: The package discovery currently collects the repo root
package.json because mapfile into packageManifests uses fd --type f
'^package\.json$' ., so update the discovery to only include workspace package
roots (or explicitly drop the repo root) before running publint: either change
the fd invocation to search only the workspace globs (e.g., restrict to apps/*,
docs, packages/*) or post-filter the packageManifests array to remove
"./package.json" (or the repo-root path); ensure the rest of the script (the for
loop iterating packageManifests and the publint run "$packageDir" --pack false
invocation) remains unchanged so generatedArtifacts handling and
touchGeneratedFile behavior still apply.
---
Nitpick comments:
In `@nix/checks.nix`:
- Around line 146-173: The code currently hardcodes generatedArtifacts and
duplicates the package.json publish contract; replace that with logic that reads
packageJson.bin from each manifest and derives the relative executable paths
dynamically. In the loop that processes each manifestPath (the block using
packageDir, packageJson and files), remove the generatedArtifacts.get(...)
lookup and instead: inspect packageJson.bin (handle string form and object
form), collect the bin target paths (the values when bin is an object, or the
single string when bin is a string), then for each derived relativePath call
touchGeneratedFile(packageDir, relativePath) only if files.has(relativePath)
(same gating as before). Keep touchGeneratedFile and its chmod behavior
unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 336405f6-c79a-434b-aa58-8c81d9c9f263
📒 Files selected for processing (3)
nix/checks.nixnix/packages.nixnix/publint.nix
ccusage performance comparisonPR SHA: This compares the PR package against the configured base package on the same CI runner. 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 Rust PR release binary against the configured base package on the same CI runner. 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. |
Co-authored-by: Codesmith <[email protected]>
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. 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 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. |

Packages publint through Nix and adds a flake check that runs publint across every package.json in the workspace. Removes clean-pkg-json from package scripts and lockfile now that the manifests only need publint validation. Validated with nix build .#publint, nix build .#checks.aarch64-darwin.publint, nix develop --ignore-environment --command publint --version, nix fmt, and git diff --cached --check.
Need help on this PR? Tag
/codesmithwith what you need. Autofix is enabled.Summary by cubic
Package
publintvia Nix and add a flake check that runs it across every workspace package to validate publish metadata without a full build. Removeclean-pkg-json, switch scripts to the Nix-providedpublint, and allow thesadepackage name in typos config.New Features
publintbuilt from a small syntheticpnpmproject (independent of the workspace lockfile); available in the dev shell and as a flake check; wrapper addsnodeto PATH.package.jsonfiles, seeds placeholder binaries for native packages, and runspublintper package root without packing.Refactors
clean-pkg-jsonfrom scripts and workspace catalogs; lockfile entries pruned.publintinjust/package scripts and dev shell; dev shell no longer auto-runspnpm install(runpnpm install --frozen-lockfilewhen needed).sadetotypos.tomlto avoid false rewrites.Written for commit b486a97. Summary will update on new commits.
Summary by CodeRabbit
New Features
Documentation
Chores