Skip to content

fix(init): pin the package runner to the registry for formatter and skills#377

Merged
rafa-thayto merged 1 commit into
mainfrom
rafa-thayto/node-modules-bin-prettier-bug
Jul 10, 2026
Merged

fix(init): pin the package runner to the registry for formatter and skills#377
rafa-thayto merged 1 commit into
mainfrom
rafa-thayto/node-modules-bin-prettier-bug

Conversation

@rafa-thayto

@rafa-thayto rafa-thayto commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What

clerk init runs the project's formatter (prettier/biome) and the skills CLI through a package runner (bunx / npx / pnpm dlx / yarn dlx). Because bunx/npx resolve a project-local node_modules/.bin/<tool> before the registry, a bare bunx prettier could run a project-local binary instead of the published tool.

Change

Pin every runner invocation to the registry through a shared runnerCommand change:

  • bunx / npx: --package <pkg>@latest -- <bin> …. An explicit version spec is required — a bare --package <pkg> (no version) still resolves the local install. This also handles @biomejs/biome, whose bin name is biome (--package @biomejs/biome@latest -- biome).
  • pnpm / yarn dlx: dlx <pkg>@latest …. dlx already fetches into an isolated store; the spec is passed for consistency.

Both spawn sites — the formatter (format.ts) and skills (skills.ts) — go through the same runnerCommand, so cwd stays the project and the skills CLI's agent detection and project-scoped installs keep working.

Testing

  • bun run test — 1890 pass, 0 fail; typecheck, lint, format:check clean.
  • Unit tests assert the exact argv per runner (bunx/npx --package <pkg>@latest -- <bin>, pnpm/yarn dlx <pkg>@latest), including the @biomejs/biome name ≠ bin case.
  • Verified end-to-end that a bare --package <pkg> (no version) still runs a project-local bin while <pkg>@latest fetches from the registry, and that runFormatters still formats the file via the registry tool.

@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5e04fa8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
clerk Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Updates runner command construction to pin formatter and skills packages to registry versions via <pkg>@latest``, preventing execution of attacker-controlled binaries in project-local node_modules/.bin/ directories. The `runnerCommand` signature now accepts explicit package names and builds pinned argv for `bunx`/`npx` and `pnpm`/`yarn` `dlx`. Formatter configuration, skills execution, tests, documentation, and the changeset are updated accordingly.

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

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
Title check ✅ Passed The title clearly matches the main change: pinning formatter and skills runners to registry packages.
Description check ✅ Passed The description accurately explains the registry-pinning change and testing for formatter and skills runners.

Warning

Review ran into problems

🔥 Problems

Linked repositories: Your configuration references 7 linked repositories, but your current plan allows 1. Analyzed clerk/clerk_go, skipped clerk/dashboard, clerk/accounts, clerk/backoffice, clerk/clerk, clerk/clerk-docs, clerk/cloudflare-workers.


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

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

🧹 Nitpick comments (2)
packages/cli-core/src/lib/runners.ts (1)

154-170: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Solid isolation helper; cleanup failures are silently swallowed.

The create/run/cleanup lifecycle is correct — errors from fn propagate via the finally-protected rm, and callback return values pass through. One nit: rm(...).catch(() => {}) discards any cleanup failure with no signal, so leaked temp dirs (e.g., due to permission issues) would go unnoticed.

♻️ Optional: surface cleanup failures via debug logging
   } finally {
-    await rm(dir, { recursive: true, force: true }).catch(() => {});
+    await rm(dir, { recursive: true, force: true }).catch((err) => {
+      log.debug?.(`Failed to clean up isolated runner dir ${dir}: ${err}`);
+    });
   }
🤖 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 `@packages/cli-core/src/lib/runners.ts` around lines 154 - 170,
withIsolatedRunnerDir currently swallows cleanup errors from rm(...), so any
temp-dir removal failure is invisible. Update the cleanup path in
withIsolatedRunnerDir to surface or log the rm failure instead of catching and
ignoring it, while still preserving the fn result/exception behavior and keeping
the isolation helper’s lifecycle intact.
packages/cli-core/src/lib/skills.ts (1)

83-85: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add runSkillsAdd coverage for both execution paths
packages/cli-core/src/lib/skills.test.ts covers buildSkillsArgs, but there’s no test for runSkillsAdd’s interactive ? spawnSkills(cwd) : withIsolatedRunnerDir(...) branch. Add coverage for both paths.

🤖 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 `@packages/cli-core/src/lib/skills.ts` around lines 83 - 85, Add test coverage
for runSkillsAdd in skills.test.ts to exercise both branches of the interactive
conditional in runSkillsAdd: one test should verify spawnSkills(cwd) is used
when interactive is true, and another should verify withIsolatedRunnerDir is
used to invoke spawnSkills(runnerCwd) when interactive is false. Use the
runSkillsAdd, spawnSkills, and withIsolatedRunnerDir symbols to locate the
behavior and assert the expected execution path in each case.

Source: Path instructions

🤖 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 `@packages/cli-core/src/commands/init/format.ts`:
- Around line 48-64: The best-effort error handling in runFormatters only covers
the formatter spawn loop, but withIsolatedRunnerDir can still throw during
temp-dir setup and abort init. Update runFormatters to wrap the
withIsolatedRunnerDir invocation itself in the same catch-and-skip behavior used
for Bun.spawn, so mkdtemp or runner dir creation failures are ignored just like
formatter execution failures. Keep the change localized around runFormatters and
withIsolatedRunnerDir so the init command remains non-fatal on formatting
errors.

---

Nitpick comments:
In `@packages/cli-core/src/lib/runners.ts`:
- Around line 154-170: withIsolatedRunnerDir currently swallows cleanup errors
from rm(...), so any temp-dir removal failure is invisible. Update the cleanup
path in withIsolatedRunnerDir to surface or log the rm failure instead of
catching and ignoring it, while still preserving the fn result/exception
behavior and keeping the isolation helper’s lifecycle intact.

In `@packages/cli-core/src/lib/skills.ts`:
- Around line 83-85: Add test coverage for runSkillsAdd in skills.test.ts to
exercise both branches of the interactive conditional in runSkillsAdd: one test
should verify spawnSkills(cwd) is used when interactive is true, and another
should verify withIsolatedRunnerDir is used to invoke spawnSkills(runnerCwd)
when interactive is false. Use the runSkillsAdd, spawnSkills, and
withIsolatedRunnerDir symbols to locate the behavior and assert the expected
execution path in each case.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fa250b58-9ec1-4ea0-b50f-a5f7b611ec48

📥 Commits

Reviewing files that changed from the base of the PR and between f0f8d23 and bb025d8.

📒 Files selected for processing (6)
  • .changeset/node-modules-bin-prettier-bug.md
  • packages/cli-core/src/commands/init/format.test.ts
  • packages/cli-core/src/commands/init/format.ts
  • packages/cli-core/src/lib/runners.test.ts
  • packages/cli-core/src/lib/runners.ts
  • packages/cli-core/src/lib/skills.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go (manual)

Comment thread packages/cli-core/src/commands/init/format.ts Outdated
…kills

`clerk init` runs the project's formatter (prettier/biome) and the skills CLI
through a package runner. Pin every runner invocation to the registry via a
shared `runnerCommand` change so it fetches the published tool rather than a
project-local `node_modules/.bin` binary:

- bunx / npx: `--package <pkg>@latest -- <bin> …` (an explicit version spec is
  required; a bare `--package <pkg>` still resolves the local install)
- pnpm / yarn: `dlx <pkg>@latest …` (dlx already fetches into an isolated store)

Covers both the formatter (`format.ts`) and skills (`skills.ts`) spawn sites,
including the `@biomejs/biome` package whose bin name is `biome`.
@rafa-thayto rafa-thayto force-pushed the rafa-thayto/node-modules-bin-prettier-bug branch from 0bbc0d4 to 5e04fa8 Compare July 10, 2026 19:58
@rafa-thayto rafa-thayto changed the title fix(init): run formatter and skills package runner from an isolated dir fix(init): pin the package runner to the registry for formatter and skills Jul 10, 2026
@rafa-thayto rafa-thayto merged commit 6256c57 into main Jul 10, 2026
10 checks passed
@rafa-thayto rafa-thayto deleted the rafa-thayto/node-modules-bin-prettier-bug branch July 10, 2026 22:27
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