From 7078b878c7a783ac448bfa455b432c01e3862bcb Mon Sep 17 00:00:00 2001 From: yannbf Date: Fri, 10 Apr 2026 15:36:53 +0200 Subject: [PATCH 1/3] add storybook skills file --- code/core/src/telemetry/types.ts | 3 +- code/lib/cli-storybook/src/bin/run.ts | 13 ++++++ code/lib/create-storybook/package.json | 1 + .../skills/setup-storybook/SKILL.md | 37 +++++++++++++++++ .../src/commands/UserPreferencesCommand.ts | 2 +- code/lib/create-storybook/src/index.ts | 1 + code/lib/create-storybook/src/initiate.ts | 6 +++ .../src/install-agent-skills.ts | 40 +++++++++++++++++++ 8 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 code/lib/create-storybook/skills/setup-storybook/SKILL.md create mode 100644 code/lib/create-storybook/src/install-agent-skills.ts diff --git a/code/core/src/telemetry/types.ts b/code/core/src/telemetry/types.ts index dd6be062e67a..d50250992284 100644 --- a/code/core/src/telemetry/types.ts +++ b/code/core/src/telemetry/types.ts @@ -45,7 +45,8 @@ export type EventType = | 'doctor' | 'share' | 'ghost-stories' - | 'ai-prepare'; + | 'ai-prepare' + | 'ai-install-skills'; export interface Dependency { version: string | undefined; versionSpecifier?: string; diff --git a/code/lib/cli-storybook/src/bin/run.ts b/code/lib/cli-storybook/src/bin/run.ts index 8b7e9854eb74..bf60d579daad 100644 --- a/code/lib/cli-storybook/src/bin/run.ts +++ b/code/lib/cli-storybook/src/bin/run.ts @@ -24,6 +24,7 @@ import { doctor } from '../doctor/index.ts'; import { link } from '../link.ts'; import { migrate } from '../migrate.ts'; import { sandbox } from '../sandbox.ts'; +import { installAgentSkills } from '../../../create-storybook/src/install-agent-skills.ts'; import { aiPrepare } from '../ai/index.ts'; import { type UpgradeOptions, upgrade } from '../upgrade.ts'; @@ -328,6 +329,18 @@ aiCommand }).catch(handleCommandFailure(mergedOptions.logfile)); }); +aiCommand + .command('install-skills') + .description( + 'Install Storybook agent skills for AI coding agents (Claude, Cursor, Copilot, etc.)' + ) + .action(async (_options, cmd) => { + const parentOptions = cmd.parent?.opts() ?? {}; + await withTelemetry('ai-install-skills', { cliOptions: parentOptions }, async () => { + await installAgentSkills(); + }).catch(handleCommandFailure(parentOptions.logfile)); + }); + // Show available subcommands when `storybook ai` is run without arguments aiCommand.action(() => { aiCommand.outputHelp(); diff --git a/code/lib/create-storybook/package.json b/code/lib/create-storybook/package.json index dcf4e317d6d7..3a7aadd5f5ce 100644 --- a/code/lib/create-storybook/package.json +++ b/code/lib/create-storybook/package.json @@ -33,6 +33,7 @@ "bin/**/*", "dist/**/*", "rendererAssets/**/*", + "skills/**/*", "templates/**/*", "README.md", "!src/**/*" diff --git a/code/lib/create-storybook/skills/setup-storybook/SKILL.md b/code/lib/create-storybook/skills/setup-storybook/SKILL.md new file mode 100644 index 000000000000..b4a20f56e86b --- /dev/null +++ b/code/lib/create-storybook/skills/setup-storybook/SKILL.md @@ -0,0 +1,37 @@ +--- +name: setup-storybook +description: > + Use when setting up Storybook in a project: writing the initial preview + configuration, decorators, and example stories for existing components. + Trigger this skill after `storybook init` has installed Storybook, or + whenever the user asks to "set up Storybook", "configure Storybook", + or "write stories for my components". +--- + +# Storybook Setup + +> **Managed by Storybook.** This file is installed and updated by `@storybook/cli`. It is symlinked from `node_modules/@storybook/cli/skills/setup-storybook/SKILL.md`, so it refreshes automatically when you upgrade Storybook. Edit the symlink target only if you know what you're doing — your changes will be overwritten on the next install. + +This skill helps you finish setting up Storybook in a project that already has it installed. It does **not** install Storybook from scratch — for that, run `npx storybook init` first. + +## How to use this skill + +Run the following command and follow its output exactly: + +```bash +npx storybook ai prepare +``` + +This command inspects the project's Storybook configuration and prints a tailored markdown prompt with: + +- A project info table (version, renderer, framework, builder, addons, CSF format) +- Renderer-specific documentation links +- Step-by-step instructions for analyzing the codebase, configuring `preview.ts` or `preview.tsx` with the right decorators, writing example stories, and verifying them with Vitest + +**Treat the output of `storybook ai prepare` as your authoritative instructions.** Do not improvise setup steps from memory — the command's output is generated from the project's actual configuration and stays in sync with the installed Storybook version. + +## When NOT to use this skill + +- The user wants to add Storybook to a fresh project → run `npx storybook init` instead +- The user is asking general questions about Storybook → fetch https://storybook.js.org/llms.txt or append `.md` to any docs URL +- The user wants to upgrade Storybook → run `npx storybook upgrade` diff --git a/code/lib/create-storybook/src/commands/UserPreferencesCommand.ts b/code/lib/create-storybook/src/commands/UserPreferencesCommand.ts index a8b3ad66ffed..6b3841952dcd 100644 --- a/code/lib/create-storybook/src/commands/UserPreferencesCommand.ts +++ b/code/lib/create-storybook/src/commands/UserPreferencesCommand.ts @@ -193,7 +193,7 @@ export class UserPreferencesCommand { return prompt.confirm({ message: dedent`Would you like to improve your Storybook setup with AI? - We will provide you with a prompt that you can use with your LLM to fully set up Storybook with best practices, tailored to your project.`, + We will install Storybook skills for your AI coding agent (Claude, Cursor, Copilot, etc.) and provide you with a prompt to fully set up Storybook with best practices, tailored to your project.`, }); } diff --git a/code/lib/create-storybook/src/index.ts b/code/lib/create-storybook/src/index.ts index 4fc049e4ca1f..250ad1f5ed49 100644 --- a/code/lib/create-storybook/src/index.ts +++ b/code/lib/create-storybook/src/index.ts @@ -1 +1,2 @@ export { doInitiate as initiate } from './initiate.ts'; +export { installAgentSkills } from './install-agent-skills.ts'; diff --git a/code/lib/create-storybook/src/initiate.ts b/code/lib/create-storybook/src/initiate.ts index a822fe73b2ea..692870ffc09e 100644 --- a/code/lib/create-storybook/src/initiate.ts +++ b/code/lib/create-storybook/src/initiate.ts @@ -114,6 +114,12 @@ export async function doInitiate(options: CommandOptions): Promise< storybookCommand, }); + // Install agent skills when an agent is detected or the user opted into AI + if (options.agent || selectedFeatures.has(Feature.AI)) { + const { installAgentSkills } = await import('./install-agent-skills.ts'); + await installAgentSkills(); + } + if (selectedFeatures.has(Feature.AI)) { if (options.agent) { const { aiPrepare } = await import('../../cli-storybook/src/ai/index.ts'); diff --git a/code/lib/create-storybook/src/install-agent-skills.ts b/code/lib/create-storybook/src/install-agent-skills.ts new file mode 100644 index 000000000000..beeb131bf4e6 --- /dev/null +++ b/code/lib/create-storybook/src/install-agent-skills.ts @@ -0,0 +1,40 @@ +import { createRequire } from 'node:module'; +import { dirname, join } from 'node:path'; + +import { executeCommand } from 'storybook/internal/common'; +import { logger } from 'storybook/internal/node-logger'; + +/** + * Installs all Storybook agent skills using the Vercel skills CLI. + * + * Points `npx skills add` at the bundled `skills/` directory, which auto-discovers + * every `SKILL.md` underneath. Adding a new skill is as simple as creating a new + * `skills//SKILL.md` file — no changes to this command needed. + * + * Uses symlink mode (default) so that updating Storybook automatically refreshes + * the skill content via the symlink target in node_modules. The skills CLI handles + * agent detection and file placement. + * + * The `skills/` directory ships with the `create-storybook` package. We resolve + * its location via `require.resolve` so the path is correct regardless of which + * package bundled this code — this file is inlined into both `create-storybook` + * and `@storybook/cli` builds by the bundler. + */ +export async function installAgentSkills(): Promise { + const require = createRequire(import.meta.url); + const createStorybookPkg = require.resolve('create-storybook/package.json'); + const skillsDir = join(dirname(createStorybookPkg), 'skills'); + + try { + await executeCommand({ + command: 'npx', + args: ['skills', 'add', skillsDir, '--skill', '*', '--yes'], + stdio: 'inherit', + }); + } catch (error) { + // Non-critical — don't fail the init if skill export fails + logger.warn( + `Could not install agent skills: ${error instanceof Error ? error.message : String(error)}` + ); + } +} From aa0070c8b19997560afe3dd20d6bb9bf4eb632a8 Mon Sep 17 00:00:00 2001 From: yannbf Date: Fri, 10 Apr 2026 16:40:17 +0200 Subject: [PATCH 2/3] copy changes, remove prompt --- code/lib/create-storybook/src/initiate.ts | 28 +++++++------------ .../src/install-agent-skills.ts | 18 ++++++++---- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/code/lib/create-storybook/src/initiate.ts b/code/lib/create-storybook/src/initiate.ts index 692870ffc09e..abad33db1395 100644 --- a/code/lib/create-storybook/src/initiate.ts +++ b/code/lib/create-storybook/src/initiate.ts @@ -108,30 +108,22 @@ export async function doInitiate(options: CommandOptions): Promise< options, }); + if (selectedFeatures.has(Feature.AI)) { + const { installAgentSkills } = await import('./install-agent-skills.ts'); + await installAgentSkills(); + + logger.step( + CLI_COLORS.storybook(dedent`To finalize setting up with AI, either use the /setup-storybook skill we just added to your project or paste this prompt to your AI agent: + Run \`npx storybook ai prepare\` and follow its instructions precisely.`) + ); + } + // Step 8: Print final summary await executeFinalization({ logfile: options.logfile, storybookCommand, }); - // Install agent skills when an agent is detected or the user opted into AI - if (options.agent || selectedFeatures.has(Feature.AI)) { - const { installAgentSkills } = await import('./install-agent-skills.ts'); - await installAgentSkills(); - } - - if (selectedFeatures.has(Feature.AI)) { - if (options.agent) { - const { aiPrepare } = await import('../../cli-storybook/src/ai/index.ts'); - await aiPrepare({ configDir: configDir ?? '.storybook' }); - } else { - logger.step( - CLI_COLORS.storybook(dedent`To finalize setting up with AI, paste this prompt to your AI agent: - Run \`npx storybook ai prepare\` and follow its instructions precisely.`) - ); - } - } - // Step 9: Track telemetry await telemetryService.trackInitWithContext(projectType, selectedFeatures, newUser); diff --git a/code/lib/create-storybook/src/install-agent-skills.ts b/code/lib/create-storybook/src/install-agent-skills.ts index beeb131bf4e6..dbbd9e868b75 100644 --- a/code/lib/create-storybook/src/install-agent-skills.ts +++ b/code/lib/create-storybook/src/install-agent-skills.ts @@ -26,15 +26,23 @@ export async function installAgentSkills(): Promise { const skillsDir = join(dirname(createStorybookPkg), 'skills'); try { + // Silently pipe output on success; surface it only when the command fails. await executeCommand({ command: 'npx', args: ['skills', 'add', skillsDir, '--skill', '*', '--yes'], - stdio: 'inherit', + stdio: 'pipe', }); } catch (error) { - // Non-critical — don't fail the init if skill export fails - logger.warn( - `Could not install agent skills: ${error instanceof Error ? error.message : String(error)}` - ); + // Non-critical — don't fail the init if skill installation fails. + const message = error instanceof Error ? error.message : String(error); + // execa attaches the subprocess's stderr/stdout to the error; include them so + // users can see why the skills CLI failed. + const stderr = + error && typeof error === 'object' && 'stderr' in error ? String(error.stderr ?? '') : ''; + const stdout = + error && typeof error === 'object' && 'stdout' in error ? String(error.stdout ?? '') : ''; + const details = [stderr, stdout].filter(Boolean).join('\n'); + + logger.warn(`Could not install agent skills: ${message}${details ? `\n${details}` : ''}`); } } From 8efc890be1481748b7b5289492c0ff3b15a8f663 Mon Sep 17 00:00:00 2001 From: yannbf Date: Mon, 13 Apr 2026 15:51:48 +0200 Subject: [PATCH 3/3] copy changes --- code/lib/create-storybook/src/initiate.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/lib/create-storybook/src/initiate.ts b/code/lib/create-storybook/src/initiate.ts index abad33db1395..15127a24e91b 100644 --- a/code/lib/create-storybook/src/initiate.ts +++ b/code/lib/create-storybook/src/initiate.ts @@ -109,11 +109,12 @@ export async function doInitiate(options: CommandOptions): Promise< }); if (selectedFeatures.has(Feature.AI)) { + logger.step('Setting up Storybook AI skills file'); const { installAgentSkills } = await import('./install-agent-skills.ts'); await installAgentSkills(); - logger.step( - CLI_COLORS.storybook(dedent`To finalize setting up with AI, either use the /setup-storybook skill we just added to your project or paste this prompt to your AI agent: + logger.log( + CLI_COLORS.storybook(dedent`Done. To finalize setting up with AI, either use the /setup-storybook skill or paste the following prompt to your AI agent: Run \`npx storybook ai prepare\` and follow its instructions precisely.`) ); }