Skip to content

Prefer pnpm for init and typegen#261

Merged
eluce2 merged 4 commits into
mainfrom
feature/pnpm-init-typegen
May 14, 2026
Merged

Prefer pnpm for init and typegen#261
eluce2 merged 4 commits into
mainfrom
feature/pnpm-init-typegen

Conversation

@eluce2
Copy link
Copy Markdown
Collaborator

@eluce2 eluce2 commented May 14, 2026

Summary

  • prefer pnpm when init is launched via npm, with a prompt fallback if pnpm is missing
  • warn npm users to move to pnpm 11+ in init next steps and scaffold output
  • switch generated typegen scripts to package-manager exec commands and rewrite scaffold placeholders during init
  • add/adjust tests for package-manager resolution, plan output, scaffold contracts, and executor behavior

Testing

  • Not run (PR content only)
  • Covered by updated unit tests in resolve-init, planner, executor, and scaffold contract suites

Summary by CodeRabbit

  • New Features

    • CLI now prefers and recommends pnpm (11+) when npm is requested, shows a clear warning with abort/continue, and uses package-manager-specific execute commands in generated next steps and scripts.
    • Generated projects declare package-manager info under a devEngines section instead of a packageManager string.
  • Tests

    • Added/updated tests verifying package manager resolution, pnpm warning behavior, execution-command substitution, and generated package.json shape.
  • Documentation

    • Changesets updated describing the package-manager and execution-command changes.

Review Change Stack

- warn npm users to switch to pnpm 11+
- use manager-specific exec commands in scaffolded scripts
- keep packageManager metadata and tests aligned
@vercel
Copy link
Copy Markdown

vercel Bot commented May 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
proofkit-docs Ready Ready Preview, Comment May 14, 2026 2:39pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 14, 2026

🦋 Changeset detected

Latest commit: 2bf8bfb

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

This PR includes changesets to release 1 package
Name Type
@proofkit/cli 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
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 04e5706d-e56d-4ce8-9a30-f9adbfb843ab

📥 Commits

Reviewing files that changed from the base of the PR and between 64b43aa and 2bf8bfb.

📒 Files selected for processing (3)
  • .github/workflows/release.yml
  • packages/cli/src/core/executeInitPlan.ts
  • packages/cli/tests/executor.test.ts
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/release.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/cli/tests/executor.test.ts

📝 Walkthrough

Walkthrough

The init flow now resolves the effective package manager (preferring pnpm when npm is requested and available), computes a package-manager-specific exec command, substitutes a PNPM_EXECUTE_COMMAND placeholder into templates, and records package-manager version under packageJson.devEngines instead of packageManager.

Changes

NPM to PNPM Smart Switching and Exec Command Templating

Layer / File(s) Summary
Type contracts and helper function
packages/cli/src/core/types.ts, packages/cli/src/cli/init.ts, packages/cli/src/utils/projectFiles.ts, packages/cli/src/utils/sortPackageJson.ts
InitPlan gains packageManagerExecuteCommand; generated packageJson shape replaces packageManager string with optional devEngines.packageManager (name/version/onFail). Adds getTemplatePackageExecuteCommand and includes devEngines in package.json sort order.
Package manager resolution with npm→pnpm detection
packages/cli/src/core/resolveInitRequest.ts
New resolvePackageManager queries PackageManagerService and uses PromptService: when request.packageManager === npm prefer pnpm if available; otherwise prompt (interactive abort throws UserCancelledError) or keep npm in non-interactive/CI.
Init planning with exec command computation and npm warning
packages/cli/src/core/planInit.ts
planInit computes packageManagerExecuteCommand, populates packageJson.devEngines.packageManager with caret-prefixed version and onFail: "download", and conditionally prepends an NPM→pnpm warning to nextSteps when request.packageManager is npm. Replaces hardcoded npx next-steps with the computed exec command.
runInit: write devEngines into generated package.json
packages/cli/src/cli/init.ts
runInit clears pkgJson.packageManager for non-Bun projects and writes pkgJson.devEngines.packageManager with detected name, ^<version>, and onFail: "download".
Init execution with placeholder rewriting and warning output
packages/cli/src/core/executeInitPlan.ts
executeInitPlan rewrites the __PNPM_EXECUTE_COMMAND__ scaffold placeholder using plan.packageManagerExecuteCommand; renderNextSteps appends the PNPM 11+ warning when the plan request uses npm.
Template scaffold update to use exec command placeholder
packages/cli/template/vite-wv/package.json
Template typegen and typegen:ui scripts use __PNPM_EXECUTE_COMMAND__ @proofkit/typegen`` placeholder instead of npx.
Test infra: failure injection and coverage
packages/cli/tests/test-layer.ts, packages/cli/tests/resolve-init.test.ts, packages/cli/tests/planner.test.ts, packages/cli/tests/executor.test.ts, packages/cli/tests/init-scaffold-contract.test.ts, packages/cli/tests/webviewer-apps.test.ts, packages/cli/tests/integration.test.ts
Test-layer supports per-package-manager getVersion failures. Tests added/updated to cover pnpm auto-selection, interactive abort/continue flows, non-interactive fallback, planner/executor warnings, placeholder substitution, and devEngines packageJson assertions.
Changeset documentation
.changeset/npm-pnpm-warning.md, .changeset/typegen-exec-command.md, .changeset/package-manager-dev-engines.md, .changeset/intent-package-manager-next-step.md
Patch-level changesets documenting the npm→pnpm guidance, typegen exec-command placeholder, and devEngines packageManager wiring.
CI workflow
.github/workflows/release.yml
Adds PROOFKIT_BINARY_TARGETS: bun-linux-x64 env to the Changesets action step.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI as CLI (resolveInitRequest / planInit / executeInitPlan)
  participant PMS as PackageManagerService
  participant Prompt as PromptService
  participant FS as FileSystem

  User->>CLI: start init (requested packageManager: npm)
  CLI->>PMS: detect pnpm version
  PMS-->>CLI: pnpm available? (version or error)
  alt pnpm available
    CLI->>CLI: set packageManager = pnpm
  else pnpm missing & interactive
    CLI->>Prompt: show npm→pnpm warning (abort/continue)
    Prompt-->>CLI: user choice (abort / continue)
    alt abort
      CLI-->>User: throw UserCancelledError
    else continue
      CLI->>CLI: keep packageManager = npm
    end
  else non-interactive
    CLI->>CLI: keep packageManager = npm
  end
  CLI->>CLI: planInit computes packageManagerExecuteCommand
  CLI->>FS: executeInitPlan replaces __PNPM_EXECUTE_COMMAND__ in scaffold
  FS-->>CLI: scaffold files updated
  CLI-->>User: renderNextSteps (includes PNPM warning when npm)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly reflects the main objective: preferring pnpm for init and typegen commands, which is the core change across multiple files in the PR.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 feature/pnpm-init-typegen

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

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

Inline comments:
In `@packages/cli/src/cli/init.ts`:
- Line 289: The packageManager value is being written with a range
(`${pkgManager}>=${stdout.trim()}`) which Corepack rejects; update the
assignment for pkgJson.packageManager to use an exact specifier by concatenating
the package manager name and the exact version (use `@${stdout.trim()}`), i.e.
set pkgJson.packageManager to `${pkgManager}@${stdout.trim()}` so Corepack can
resolve it correctly; change the assignment near where pkgJson, pkgManager, and
stdout.trim() are used.

In `@packages/cli/src/core/planInit.ts`:
- Line 185: Replace the hardcoded "npx `@tanstack/intent`@latest install" entry in
the nextSteps array with a package-manager-aware invocation: use the existing
packageManagerExecuteCommand variable (the same helper used by
formatPackageManagerCommand) to build the command string so it works for
npm/yarn/pnpm/bun, e.g. construct the entry as `${packageManagerExecuteCommand}
`@tanstack/intent`@latest install` where the current literal appears (look for the
"npx `@tanstack/intent`@latest install" string in planInit.ts and update it).

In `@packages/cli/tests/executor.test.ts`:
- Around line 368-370: The test's exact-string assertion for the pnpm warning is
brittle; update the assertion in packages/cli/tests/executor.test.ts (the
expect(console.info.join("\n")) line) to check intent instead of exact
copy—match a regex or use includes that looks for the invariant parts like
"pnpm" and "11" (e.g. a case-insensitive regex matching "pnpm.*11" or "pnpm.*11
or greater") so the test passes even if surrounding phrasing changes.

In `@packages/cli/tests/planner.test.ts`:
- Around line 128-130: The test asserts an exact warning string on
plan.nextSteps which is brittle; update the assertion to match more loosely
(e.g., use a regex or Jest matchers) so it only checks for the presence of
"pnpm" and "11" case-insensitively. Locate the expect against plan.nextSteps in
the planner.test.ts and replace the exact .toContain(...) string check with a
regex-based check (e.g.,
expect(plan.nextSteps).toEqual(expect.arrayContaining([expect.stringMatching(/pnpm.*11/i)]))
or equivalent) to avoid failures due to minor copy/casing changes.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f4b19d58-a7c5-4607-9789-739c755f1fb1

📥 Commits

Reviewing files that changed from the base of the PR and between aca7e89 and f1dd2c5.

📒 Files selected for processing (15)
  • .changeset/npm-pnpm-warning.md
  • .changeset/typegen-exec-command.md
  • packages/cli/src/cli/init.ts
  • packages/cli/src/core/executeInitPlan.ts
  • packages/cli/src/core/planInit.ts
  • packages/cli/src/core/resolveInitRequest.ts
  • packages/cli/src/core/types.ts
  • packages/cli/src/utils/projectFiles.ts
  • packages/cli/template/vite-wv/package.json
  • packages/cli/tests/executor.test.ts
  • packages/cli/tests/init-scaffold-contract.test.ts
  • packages/cli/tests/planner.test.ts
  • packages/cli/tests/resolve-init.test.ts
  • packages/cli/tests/test-layer.ts
  • packages/cli/tests/webviewer-apps.test.ts

Comment thread packages/cli/src/cli/init.ts Outdated
cwd: projectDir,
});
pkgJson.packageManager = `${pkgManager}@${stdout.trim()}`;
pkgJson.packageManager = `${pkgManager}>=${stdout.trim()}`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does the packageManager field in package.json support version range syntax like >= or does it require exact versions?

💡 Result:

No, the packageManager field in package.json does not support full version range syntax like >=1.0.0 or ^1.0.0; it requires an exact version specifier that resolves to a single specific version.[1][2][3][4] The field follows the format (npm|yarn|pnpm)@Version, where "version" must be a specifier that Corepack can resolve to exactly one version, such as a full semver version (e.g., "pnpm@8.15.4"), a tag like "latest", or a range like "7.x" when used in CLI commands like corepack use pnpm@7.x (which then pins to an exact version in package.json).[1][2][5] Examples from official Node.js Corepack docs show ranges in CLI but resolve to exact versions: corepack use pnpm@7.x sets "packageManager": "pnpm@7.x.x.x" (exact).[2][5] Ranges like "*" or "^1.0.0" in the field itself are rejected, as confirmed in Corepack issues: the field expects a resolved version, not unresolved ranges.[3][4][6] It can include a hash suffix for integrity (e.g., pnpm@10.4.0+sha512....) or direct tarball URLs (with env flags), but still resolves to exact binaries.[7][8] This design ensures deterministic package manager versions across environments via Corepack, unlike dependency fields which use semver ranges.[9][10]

Citations:


The packageManager field does not support >= range syntax; Corepack requires exact version specifiers.

The packageManager field in package.json follows the Corepack specification and only accepts exact version specifiers (e.g., pnpm@8.15.4), not version ranges like >=. Range syntax (>=, ^, *) is rejected by Corepack and will not resolve correctly. Change line 289 to use the exact version format: pkgJson.packageManager = ${pkgManager}@${stdout.trim()} instead of ${pkgManager}>=${stdout.trim()}.

🧰 Tools
🪛 GitHub Actions: Release / Deterministic Contract Tests

[error] Command failed: pnpm build && node ./scripts/build-current-binary.mjs && PROOFKIT_DISABLE_BUNDLED_BINARY=1 vitest run (followed by write-cli-version.mjs, tsdown, publint). vitest run exited with code 1 due to failing tests.

🤖 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/src/cli/init.ts` at line 289, The packageManager value is being
written with a range (`${pkgManager}>=${stdout.trim()}`) which Corepack rejects;
update the assignment for pkgJson.packageManager to use an exact specifier by
concatenating the package manager name and the exact version (use
`@${stdout.trim()}`), i.e. set pkgJson.packageManager to
`${pkgManager}@${stdout.trim()}` so Corepack can resolve it correctly; change
the assignment near where pkgJson, pkgManager, and stdout.trim() are used.

Comment thread packages/cli/src/core/planInit.ts Outdated
Comment on lines +368 to +370
expect(console.info.join("\n")).toContain(
"Warning: We strongly suggest using pnpm 11 or greater as your package manager for security reasons.",
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use an intent-based warning assertion instead of exact copy

Line 368 is currently failing because warning text changed slightly. Match invariant intent (pnpm 11+ warning) rather than full sentence.

Proposed fix
-    expect(console.info.join("\n")).toContain(
-      "Warning: We strongly suggest using pnpm 11 or greater as your package manager for security reasons.",
-    );
+    expect(console.info.join("\n")).toMatch(/warning:.*pnpm 11 or greater/i);
📝 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.

Suggested change
expect(console.info.join("\n")).toContain(
"Warning: We strongly suggest using pnpm 11 or greater as your package manager for security reasons.",
);
expect(console.info.join("\n")).toMatch(/warning:.*pnpm 11 or greater/i);
🧰 Tools
🪛 GitHub Actions: Release / Deterministic Contract Tests

[error] Command failed: pnpm build && node ./scripts/build-current-binary.mjs && PROOFKIT_DISABLE_BUNDLED_BINARY=1 vitest run (followed by write-cli-version.mjs, tsdown, publint). vitest run exited with code 1 due to failing tests.

🪛 GitHub Check: Deterministic Contract Tests

[failure] 368-368: tests/executor.test.ts > executeInitPlan command paths > prints pnpm warning in npm next steps
AssertionError: expected 'Scaffolding in /tmp/proofkit-new-npm-…' to contain 'Warning: We strongly suggest using pn…'

  • Expected
  • Received
  • Warning: We strongly suggest using pnpm 11 or greater as your package manager for security reasons.
  • Scaffolding in /tmp/proofkit-new-npm-warning-8PPYq7/npm-app
  • Next steps:
  • Project root: cd npm-app
  • Agent setup:
  • Have your agent run this in the new project and complete the interactive prompt so it can load the right skills:
  • npx @tanstack/intent@latest install
  • Install dependencies:
  • npm install
  • Warning: We strongly suggest using PNPM 11 or greater as your package manager to better protect your computer and your app.
  • Start the app:
  • npm run dev
  • More ProofKit commands:
  • npm run proofkit

❯ tests/executor.test.ts:368:37

🤖 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/tests/executor.test.ts` around lines 368 - 370, The test's
exact-string assertion for the pnpm warning is brittle; update the assertion in
packages/cli/tests/executor.test.ts (the expect(console.info.join("\n")) line)
to check intent instead of exact copy—match a regex or use includes that looks
for the invariant parts like "pnpm" and "11" (e.g. a case-insensitive regex
matching "pnpm.*11" or "pnpm.*11 or greater") so the test passes even if
surrounding phrasing changes.

Comment thread packages/cli/tests/planner.test.ts Outdated
- write pnpm into `devEngines.packageManager`
- drop top-level `packageManager`
- update init warnings and tests
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 14, 2026

Open in StackBlitz

@proofkit/better-auth

pnpm add https://pkg.pr.new/proofsh/proofkit/@proofkit/better-auth@261

@proofkit/cli

pnpm add https://pkg.pr.new/proofsh/proofkit/@proofkit/cli@261

create-proofkit

pnpm add https://pkg.pr.new/proofsh/proofkit/create-proofkit@261

@proofkit/fmdapi

pnpm add https://pkg.pr.new/proofsh/proofkit/@proofkit/fmdapi@261

@proofkit/fmodata

pnpm add https://pkg.pr.new/proofsh/proofkit/@proofkit/fmodata@261

@proofkit/typegen

pnpm add https://pkg.pr.new/proofsh/proofkit/@proofkit/typegen@261

@proofkit/webviewer

pnpm add https://pkg.pr.new/proofsh/proofkit/@proofkit/webviewer@261

commit: 2bf8bfb

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
packages/cli/src/core/planInit.ts (1)

191-191: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the resolved execute runner for @tanstack/intent in next steps.

Line 191 is still hardcoded to npx, which is inconsistent with the package-manager-aware init flow and can mislead pnpm/yarn/bun users.

Suggested fix
-      "npx `@tanstack/intent`@latest install",
+      `${packageManagerExecuteCommand} `@tanstack/intent`@latest install`,
#!/bin/bash
# Verify nextSteps currently hardcodes npx and that packageManagerExecuteCommand is available.
rg -n "packageManagerExecuteCommand|tanstack/intent|nextSteps" packages/cli/src/core/planInit.ts -C2
sed -n '184,196p' packages/cli/src/core/planInit.ts
🤖 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/src/core/planInit.ts` at line 191, nextSteps currently hardcodes
"npx `@tanstack/intent`@latest install"; replace that element to use the resolved
package manager command (packageManagerExecuteCommand) so the init flow respects
pnpm/yarn/bun. Update the nextSteps entry that references
"@tanstack/intent@latest install" to build the command using
packageManagerExecuteCommand (same variable used earlier in this function)
instead of the literal "npx", keeping the package spec "@tanstack/intent@latest
install" intact.
🤖 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.

Duplicate comments:
In `@packages/cli/src/core/planInit.ts`:
- Line 191: nextSteps currently hardcodes "npx `@tanstack/intent`@latest install";
replace that element to use the resolved package manager command
(packageManagerExecuteCommand) so the init flow respects pnpm/yarn/bun. Update
the nextSteps entry that references "@tanstack/intent@latest install" to build
the command using packageManagerExecuteCommand (same variable used earlier in
this function) instead of the literal "npx", keeping the package spec
"@tanstack/intent@latest install" intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ee519862-388f-4b43-9a43-ae4163ebb707

📥 Commits

Reviewing files that changed from the base of the PR and between f1dd2c5 and e13c759.

📒 Files selected for processing (9)
  • .changeset/package-manager-dev-engines.md
  • packages/cli/src/cli/init.ts
  • packages/cli/src/core/planInit.ts
  • packages/cli/src/core/types.ts
  • packages/cli/src/utils/sortPackageJson.ts
  • packages/cli/tests/executor.test.ts
  • packages/cli/tests/init-scaffold-contract.test.ts
  • packages/cli/tests/integration.test.ts
  • packages/cli/tests/planner.test.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/cli/src/utils/sortPackageJson.ts
  • .changeset/package-manager-dev-engines.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/cli/tests/planner.test.ts
  • packages/cli/tests/executor.test.ts

- update init next step to use PM-specific exec
- add tests for npm, pnpm, yarn, bun
- include cli patch changeset
- print plan package manager execute command
- cover pnpm agent setup path
- set release binary targets for bun
@eluce2 eluce2 merged commit 93b3231 into main May 14, 2026
20 checks passed
@eluce2 eluce2 deleted the feature/pnpm-init-typegen branch May 14, 2026 14:44
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.

1 participant