Skip to content

CLI: Use detected package manager instead of npx for remote commands - #35409

Merged
ndelangen merged 4 commits into
nextfrom
fix/dispatcher-package-manager-aware-cli
Jul 9, 2026
Merged

ndelangen merged 4 commits into
nextfrom
fix/dispatcher-package-manager-aware-cli

Conversation

@ghengeveld

@ghengeveld ghengeveld commented Jul 8, 2026 •

Copy link
Copy Markdown
Member

Closes #

What I did

Storybook's CLI dispatcher always fell back to npx when @storybook/cli / create-storybook was not available locally. That invokes npm, which fails in pnpm-only repos that enforce devEngines.packageManager (reported in Chromatic Slack while running pnpm dlx storybook@next upgrade and npx storybook ai setup).

  • Route remote CLI packages through the detected package manager (pnpm dlx, bunx, etc.) instead of hardcoded npx
  • Emit package-manager-aware Vitest/MSW/Storybook commands in storybook ai setup prompts
  • Pass a package-manager-aware storybook ai setup command from storybook init finalization

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

Caution

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

No manual testing required beyond automated coverage: the regression is in CLI dispatch and prompt string generation, both covered by unit tests. A maintainer can optionally verify in a pnpm monorepo with devEngines.packageManager set to pnpm by running pnpm dlx storybook@next upgrade --package-manager pnpm --yes and confirming it no longer invokes npm.

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Declare whether manual QA will be needed for this PR during the next release, through qa:needed or qa:skip

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

  • New Features

    • Setup and verification instructions now generate Storybook, Vitest, and MSW commands using your detected package manager.
    • AI setup flows now display the correct “run Storybook AI setup” command for your environment.
  • Bug Fixes

    • CLI fallback execution no longer relies on a fixed npx approach; external tool routing now respects the detected package manager, reducing incorrect copy/paste instructions.
  • Tests

    • Added unit tests covering package-manager-specific command and runner argument generation.

pnpm-only repos with devEngines fail when Storybook upgrade or setup
instructions invoke npm via npx. Route remote CLI packages through the
detected package manager and emit matching commands in AI setup prompts.
@ghengeveld ghengeveld added bug ci:normal Run our default set of CI jobs (choose this for most PRs). qa:skip Pull Requests that do not need any QA. (e.g. documentation) labels Jul 8, 2026
@Sidnioulz Sidnioulz added the upgrade:10.5 Issues/PRs found during 10.5 upgrade QA and post-release regressions label Jul 8, 2026
Comment thread code/core/src/cli/ai/setup-prompts/partials/dod.ts Outdated
Comment thread code/core/src/cli/ai/setup-prompts/pattern-copy-play.ts Outdated
Comment thread code/core/src/cli/ai/setup-prompts/setup.ts Outdated
ndelangen and others added 2 commits July 9, 2026 09:19
The setup-prompt files imported getVitestStorybookRunCommand/getMswInitCommand
relatively from common/js-package-manager/util.ts, so the helper params resolved
to the src JsPackageManager while the passed packageManager was typed from the
built dist (storybook/internal/common). The two nominally-incompatible classes
caused TS2345 and broke typecheck. Export util.ts through the common barrel and
import the helpers from storybook/internal/common so both sides share one type.

Also drop the unused getStorybookAiSetupCommand helper (its logic is inlined in
create-storybook's initiate.ts).

Co-authored-by: Cursor <cursoragent@cursor.com>
@ndelangen
ndelangen marked this pull request as ready for review July 9, 2026 07:33
Copilot AI review requested due to automatic review settings July 9, 2026 07:33
Comment thread code/core/src/bin/dispatcher.ts Outdated
Comment thread code/core/src/common/js-package-manager/util.ts Outdated
Comment thread code/lib/create-storybook/src/commands/FinalizationCommand.ts Outdated

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.

Pull request overview

Updates Storybook’s CLI dispatch and AI setup messaging to prefer the project’s detected package manager (pnpm/yarn/bun) instead of always falling back to npx, improving compatibility with repos that enforce non-npm package managers.

Changes:

  • Route dispatcher “remote” execution through the detected package manager (e.g. pnpm dlx, yarn dlx, bunx) rather than hardcoding npx.
  • Make create-storybook finalization and AI-agent instructions display a package-manager-aware storybook ai setup command.
  • Centralize package-manager-aware command string building for Vitest/MSW usage inside AI setup prompts.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
code/lib/create-storybook/src/initiate.ts Passes a package-manager-aware storybook ai setup command into finalization.
code/lib/create-storybook/src/commands/FinalizationCommand.ts Adds configurable aiSetupCommand and uses it in follow-up messaging/prompts.
code/lib/create-storybook/src/commands/FinalizationCommand.test.ts Updates test to assert the package-manager-aware setup command is shown.
code/core/src/shared/utils/ai-prompts.ts Refactors default executor constant for AI setup prompt generation.
code/core/src/common/js-package-manager/util.ts Adds helpers for remote runner args + package-manager-aware Vitest/MSW command strings.
code/core/src/common/js-package-manager/util.test.ts Adds unit coverage for the new js-package-manager util helpers.
code/core/src/common/js-package-manager/index.ts Re-exports util helpers for broader internal consumption.
code/core/src/cli/ai/setup-prompts/setup.ts Replaces hardcoded npx commands with package-manager-aware commands in instructions.
code/core/src/cli/ai/setup-prompts/pattern-copy-play.ts Same as above, plus MSW init command becomes package-manager-aware.
code/core/src/cli/ai/setup-prompts/partials/steps.ts Updates verification/MSW steps to use package-manager-aware commands.
code/core/src/cli/ai/setup-prompts/partials/rules.ts Strengthens “don’t use npx” rule and provides the correct Storybook command form.
code/core/src/cli/ai/setup-prompts/partials/dod.ts Updates DoD strings to match package-manager-aware Vitest commands.
code/core/src/bin/dispatcher.ts Switches remote fallback execution from npx to detected package manager execution.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread code/core/src/common/js-package-manager/util.ts Outdated
@storybook-app-bot

storybook-app-bot Bot commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

Package Benchmarks

Commit: 17f3732, ran on 9 July 2026 at 08:09:53 UTC

The following packages have significant changes to their size or dependencies:

@storybook/angular-vite

Before After Difference
Dependency count 32 33 🚨 +1 🚨
Self size 22.38 MB 22.48 MB 🚨 +94 KB 🚨
Dependency size 20.07 MB 20.07 MB 🚨 +491 B 🚨
Bundle Size Analyzer Link Link

@coderabbitai

coderabbitai Bot commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR replaces hardcoded npx command strings with package-manager-aware command generation across dispatcher fallback, AI setup prompts, and finalization output. It also adds shared helpers for remote package execution and command construction.

Changes

Package manager command generation

Layer / File(s) Summary
Command helper utilities and tests
code/core/src/common/js-package-manager/util.ts, code/core/src/common/js-package-manager/util.test.ts, code/core/src/common/js-package-manager/index.ts
Adds helpers for remote package runner args, Vitest command construction, and MSW init command construction; re-exports them and adds unit coverage.
CLI dispatcher fallback execution
code/core/src/bin/dispatcher.ts
Switches the fallback path from direct npx execution to package-manager-based remote package execution.
AI setup prompt command text
code/core/src/cli/ai/setup-prompts/partials/dod.ts, rules.ts, steps.ts, pattern-copy-play.ts, setup.ts
Builds Vitest, MSW, and Storybook command snippets from the detected package manager instead of hardcoded npx strings.
Finalization command AI setup wiring
code/lib/create-storybook/src/commands/FinalizationCommand.ts, FinalizationCommand.test.ts, code/lib/create-storybook/src/initiate.ts, code/core/src/shared/utils/ai-prompts.ts
Adds a configurable AI setup command to finalization output, passes it from initialization, and updates related tests and default prompt plumbing.

Estimated code review effort: 3 (Moderate) | ~30 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

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

🧹 Nitpick comments (3)
code/core/src/cli/ai/setup-prompts/setup.ts (1)

158-162: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the repeated command-derivation block into a shared helper.

The same vitestRunFile/vitestRunAll/storybookBuild/storybookDoctor derivation from packageManager appears here and in pattern-copy-play.ts (and a similar vitestRunAll/vitestRunFile pair in steps.ts's verifyStep). Consolidating into one helper (e.g. in util.ts or a shared setup-prompts util) would avoid drift when a command changes.

🤖 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 `@code/core/src/cli/ai/setup-prompts/setup.ts` around lines 158 - 162, Extract
the repeated packageManager command-derivation logic into a shared helper and
reuse it here, in pattern-copy-play.ts, and in steps.ts’s verifyStep so the
vitestRunFile/vitestRunAll/storybookBuild/storybookDoctor values come from one
place. Move the command-building into a common utility (for example in util.ts
or a shared setup-prompts helper) and update the affected call sites to import
and call that helper instead of duplicating the derivation.
code/lib/create-storybook/src/commands/FinalizationCommand.test.ts (1)

259-301: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for aiSetupCommand forwarding via executeFinalization.

Every other FinalizationCommandOptions field (showAgentFollowUp, showAiInstructions, storybookCommand) has a dedicated test in this block, but the new aiSetupCommand forwarding path isn't covered here.

✅ Suggested test
+    it('should forward aiSetupCommand to the command', async () => {
+      vi.mocked(find.up).mockReturnValue(undefined);
+
+      await executeFinalization({
+        showAgentFollowUp: true,
+        showAiInstructions: true,
+        logfile: undefined,
+        aiSetupCommand: 'pnpm exec storybook ai setup',
+      });
+
+      expect(logger.step).toHaveBeenCalledWith(
+        expect.stringContaining('pnpm exec storybook ai setup')
+      );
+    });
🤖 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 `@code/lib/create-storybook/src/commands/FinalizationCommand.test.ts` around
lines 259 - 301, The executeFinalization helper test block is missing coverage
for the new aiSetupCommand forwarding path. Add a dedicated test alongside the
existing showAgentFollowUp, showAiInstructions, and storybookCommand cases that
calls executeFinalization with aiSetupCommand set, then assert the command
receives or logs that value through the same forwarding behavior used by
FinalizationCommandOptions.
code/core/src/common/js-package-manager/util.test.ts (1)

107-114: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing coverage for getVitestStorybookRunCommand's file argument and getMswInitCommand with npm.

The new tests only exercise getVitestStorybookRunCommand(pkgManager) without the optional file parameter, even though steps.ts and pattern-copy-play.ts call it with a file path (e.g. getVitestStorybookRunCommand(packageManager, 'path/to/Foo.stories.tsx')). Similarly, getMswInitCommand is only tested with pnpm, not npm.

✅ Suggested additional assertions
   it('builds package-manager-aware setup commands', () => {
     const npm = new NPMProxy({ cwd: process.cwd(), configDir: '.storybook' });
     const pnpm = new PNPMProxy({ cwd: process.cwd(), configDir: '.storybook' });

     expect(getVitestStorybookRunCommand(npm)).toBe('npx vitest --project storybook run');
     expect(getVitestStorybookRunCommand(pnpm)).toBe('pnpm exec vitest --project storybook run');
+    expect(getVitestStorybookRunCommand(pnpm, 'path/to/Foo.stories.tsx')).toBe(
+      'pnpm exec vitest --project storybook run path/to/Foo.stories.tsx'
+    );
     expect(getMswInitCommand(pnpm)).toBe('pnpm exec msw init ./public --save');
+    expect(getMswInitCommand(npm)).toBe('npx msw init ./public --save');
   });
🤖 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 `@code/core/src/common/js-package-manager/util.test.ts` around lines 107 - 114,
Add coverage for the optional file-path behavior in getVitestStorybookRunCommand
and for npm in getMswInitCommand. Update util.test.ts to assert
getVitestStorybookRunCommand(NPMProxy, 'path/to/Foo.stories.tsx') and
getVitestStorybookRunCommand(PNPMProxy, 'path/to/Foo.stories.tsx') produce the
expected command including the file argument, and add an assertion for
getMswInitCommand(NPMProxy) alongside the existing PNPMProxy case. Use the
existing helpers getVitestStorybookRunCommand and getMswInitCommand so the tests
cover the call sites used by steps.ts and pattern-copy-play.ts.
🤖 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.

Nitpick comments:
In `@code/core/src/cli/ai/setup-prompts/setup.ts`:
- Around line 158-162: Extract the repeated packageManager command-derivation
logic into a shared helper and reuse it here, in pattern-copy-play.ts, and in
steps.ts’s verifyStep so the
vitestRunFile/vitestRunAll/storybookBuild/storybookDoctor values come from one
place. Move the command-building into a common utility (for example in util.ts
or a shared setup-prompts helper) and update the affected call sites to import
and call that helper instead of duplicating the derivation.

In `@code/core/src/common/js-package-manager/util.test.ts`:
- Around line 107-114: Add coverage for the optional file-path behavior in
getVitestStorybookRunCommand and for npm in getMswInitCommand. Update
util.test.ts to assert getVitestStorybookRunCommand(NPMProxy,
'path/to/Foo.stories.tsx') and getVitestStorybookRunCommand(PNPMProxy,
'path/to/Foo.stories.tsx') produce the expected command including the file
argument, and add an assertion for getMswInitCommand(NPMProxy) alongside the
existing PNPMProxy case. Use the existing helpers getVitestStorybookRunCommand
and getMswInitCommand so the tests cover the call sites used by steps.ts and
pattern-copy-play.ts.

In `@code/lib/create-storybook/src/commands/FinalizationCommand.test.ts`:
- Around line 259-301: The executeFinalization helper test block is missing
coverage for the new aiSetupCommand forwarding path. Add a dedicated test
alongside the existing showAgentFollowUp, showAiInstructions, and
storybookCommand cases that calls executeFinalization with aiSetupCommand set,
then assert the command receives or logs that value through the same forwarding
behavior used by FinalizationCommandOptions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 00b6171d-c5bd-4abb-86c8-82f303e8203c

📥 Commits

Reviewing files that changed from the base of the PR and between cbf8e4f and dcc6bb9.

📒 Files selected for processing (13)
  • code/core/src/bin/dispatcher.ts
  • code/core/src/cli/ai/setup-prompts/partials/dod.ts
  • code/core/src/cli/ai/setup-prompts/partials/rules.ts
  • code/core/src/cli/ai/setup-prompts/partials/steps.ts
  • code/core/src/cli/ai/setup-prompts/pattern-copy-play.ts
  • code/core/src/cli/ai/setup-prompts/setup.ts
  • code/core/src/common/js-package-manager/index.ts
  • code/core/src/common/js-package-manager/util.test.ts
  • code/core/src/common/js-package-manager/util.ts
  • code/core/src/shared/utils/ai-prompts.ts
  • code/lib/create-storybook/src/commands/FinalizationCommand.test.ts
  • code/lib/create-storybook/src/commands/FinalizationCommand.ts
  • code/lib/create-storybook/src/initiate.ts

…iSetupCommand

- getRemotePackageRunnerArgs: also pass npx's `--yes` for Yarn Classic. Yarn1
  runs remote packages through `npx` (Yarn1Proxy), so without `--yes` it would
  re-introduce the interactive install prompt/hang in CI that the pre-PR
  `npx --yes` fallback avoided. Documented why the flag is npx-only.
- dispatcher: import JsPackageManagerFactory and getRemotePackageRunnerArgs from
  storybook/internal/common instead of deep relative paths.
- FinalizationCommand: make aiSetupCommand required and drop the hardcoded
  `npx storybook ai setup` fallback, so a caller can't silently regress to npx —
  the sole caller (initiate.ts) already passes a package-manager-aware command.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

🧹 Nitpick comments (1)
code/lib/create-storybook/src/commands/FinalizationCommand.ts (1)

88-104: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse getAiSetupPromptText() in the agent follow-up message.

The inline text in printSuccessMessage (Lines 96-97) duplicates the intent of getAiSetupPromptText() with slightly different wording. Reusing the helper avoids the two messages drifting apart if the phrasing changes later.

♻️ Proposed refactor
   private printSuccessMessage(storybookCommand?: string | null): void {
     if (this.options.showAgentFollowUp) {
       logger.step(
         CLI_COLORS.storybook(
           dedent`Storybook is installed but is not entirely set up yet.
-          To finish setting up, now run \`${this.options.aiSetupCommand}\` and follow its instructions precisely.`
+          To finish setting up, now ${this.getAiSetupPromptText()}`
         )
       );
🤖 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 `@code/lib/create-storybook/src/commands/FinalizationCommand.ts` around lines
88 - 104, The agent follow-up message in printSuccessMessage duplicates the same
setup instruction already encapsulated by getAiSetupPromptText(). Update
printSuccessMessage to reuse getAiSetupPromptText() for the “run ... and follow
its instructions precisely” part, keeping the Storybook-specific lead-in but
removing the duplicated inline wording so FinalizationCommand stays consistent
if the prompt text changes.
🤖 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.

Nitpick comments:
In `@code/lib/create-storybook/src/commands/FinalizationCommand.ts`:
- Around line 88-104: The agent follow-up message in printSuccessMessage
duplicates the same setup instruction already encapsulated by
getAiSetupPromptText(). Update printSuccessMessage to reuse
getAiSetupPromptText() for the “run ... and follow its instructions precisely”
part, keeping the Storybook-specific lead-in but removing the duplicated inline
wording so FinalizationCommand stays consistent if the prompt text changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e1975800-62a3-4090-82e1-63d1e9daaec8

📥 Commits

Reviewing files that changed from the base of the PR and between dcc6bb9 and 17f3732.

📒 Files selected for processing (5)
  • code/core/src/bin/dispatcher.ts
  • code/core/src/common/js-package-manager/util.test.ts
  • code/core/src/common/js-package-manager/util.ts
  • code/lib/create-storybook/src/commands/FinalizationCommand.test.ts
  • code/lib/create-storybook/src/commands/FinalizationCommand.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • code/core/src/common/js-package-manager/util.test.ts
  • code/core/src/bin/dispatcher.ts
  • code/core/src/common/js-package-manager/util.ts
  • code/lib/create-storybook/src/commands/FinalizationCommand.test.ts

This was referenced Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug ci:normal Run our default set of CI jobs (choose this for most PRs). qa:skip Pull Requests that do not need any QA. (e.g. documentation) upgrade:10.5 Issues/PRs found during 10.5 upgrade QA and post-release regressions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants