Two files, one repository
storybookjs/storybook ships 3 formats across 4 indexed files. The question worth asking is whether the second one says anything the first does not.
| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 32 | 8 | 0% |
| Commands | 2 | 38 | 3 | 5% |
| Section tags | 5 | 8 | 0 | 38% |
What each file covers
Sections
0 shared · 32 only in A · 8 only in B- − Storybook Agent Instructions
- − Repository Overview
- − Repository Structure
- − Architecture
- − Renderer vs builder vs framework
- − Core package
- − Key flow
- − Open services and toolsets
- − Common Commands
- − Install and compile
- − Lint and typecheck
- − Development and tests
- − Common task scenarios
- − NX and `yarn task`
- − Compile all packages
- − Check all packages
- − Run E2E tests for a template
- − Jump to a later step
- − Sandbox Notes
- − Same sandbox step via NX
- − How To Work In This Repo
- − For normal code changes
- − For addon, framework, or renderer work
- − Testing Expectations
- − Filesystem tests with `memfs`
- − Globals in tests: never assign `globalThis.*` directly
- − Quality and Logging
- − Troubleshooting
- − Environment Variables
- − Commands To Avoid
- − Code Authoring Principles
- − Maintenance Rules For Agents
- + Test Configuration
- + Test Scripts
- + Test Directory Structure
- + Running Tests in Cursor
- + Vitest Configuration
- + Test Execution Context
- + Focused Test Patterns
- + Test Mocking Rules
Commands
2 shared · 38 only in A · 3 only in B- − yarn
- − yarn task compile
- − yarn nx run-many -t compile
- − yarn nx compile <nx-project-name>
- − yarn lint
- − yarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix
- − yarn task check
- − yarn nx run-many -t check
- − yarn storybook:vitest
- − yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto
- − yarn nx e2e-tests-dev react-vite/default-ts -c production
- − yarn task e2e-tests-dev --start-from e2e-tests --template react-vite/default-ts
- − yarn nx e2e-tests-dev -c production --exclude-task-dependencies
- − yarn task sandbox --template react-vite/default-ts --start-from auto
- − yarn nx sandbox react-vite/default-ts -c production
- − yarn install
- − yarn storybook
- − yarn task
- − eslint-plugin-storybook
- − node
- − node ./path/file.ts
- − yarn task test-runner-dev --template react-vite/default-ts --start-from auto
- − yarn workspace @storybook/docgen-harness bench:docgen-perf
- − yarn workspace @storybook/docgen-harness bench:docgen-memory
- − nx.json
- − yarn nx compile core
- − vitest run --config code/vitest.config.storybook.ts
- − yarn test <pattern>
- − yarn test csf-tools
- − yarn task e2e-tests --start-from auto
- − yarn task e2e-tests-dev --start-from auto
- − yarn task test-runner --start-from auto
- − yarn task test-runner-dev --start-from auto
- − yarn task smoke-test --start-from auto
- − vitest --config code/vitest.config.storybook.ts <story-file>
- − yarn vitest run --coverage <test-file>
- − node:fs
- − node:fs/promises
- + yarn test <test-name>
- + yarn test:watch <test-name>
- + yarn --cwd code test
- yarn test
- yarn test:watch
Section tags
5 shared · 8 only in A · 0 only in B- − setup
- − build
- − lint-format
- − testing-strategy
- − security
- − dependencies
- − monorepo
- − docs
- test
- code-style
- architecture
- do-not
- agent-behaviour
Line diff
storybookjs/storybook · AGENTS.md
@@ −1 @@
1# Storybook Agent Instructions
2
3Keep this file, `AGENTS.md`, up to date when Storybook's architecture, tooling, workflows, or contributor guidance changes.
4
5This file is the canonical instruction source for coding agents. Files like `CLAUDE.md` should point here instead of duplicating instructions.
6
7## Repository Overview
8
9Storybook is a large TypeScript monorepo. The git root is the repo root, the main code lives in `code/`, and build tooling lives in `scripts/`. The default branch is `next`.
10
11- **Base branch**: `next` (all PRs should target `next`, not `main`)
12- **Node.js**: `22.22.3` (see `.nvmrc`) — supports `.ts` natively via type stripping (no loader needed)
13- **Package Manager**: Yarn Berry
14- **Task orchestration**: NX plus the custom `yarn task` runner
15- **Linting**: oxlint (root `.oxlintrc.json`, extended by `code/.oxlintrc.json` and `scripts/.oxlintrc.json`; custom rules load via `jsPlugins`). ESLint is no longer used for repo linting — `code/lib/eslint-plugin` remains as the published `eslint-plugin-storybook` package.
16- **Formatting**: oxfmt (root `.oxfmtrc.json`)
17- **CI environment**: Linux and Windows
18- **TS execution**: Migrating from `jiti` to native `node` for running `.ts` files. New scripts should use `node ./path/file.ts` with explicit `.ts` import extensions (enabled by `allowImportingTsExtensions` in tsconfig). Legacy scripts still use `jiti` but should be migrated over time.
19- **Type checking**: Per-package checks (`yarn task check`, `scripts/check/check-package.ts`) run on the TypeScript 7 native compiler (the `typescript-native` npm alias); diagnostics are filtered to the checked package. `@storybook/vue3`, `@storybook/docgen-harness` (for its `.vue` fixtures), and `@storybook/svelte` use `vue-tsc` / `svelte-check` (TS 6 based). The workspace `typescript` dependency stays on TS 6 for IDEs and API consumers, so tsconfigs must remain valid for both (e.g. no `baseUrl`).
20
21## Repository Structure
22
23```text
24storybook/
25├── .github/ # GitHub configs and workflows
26├── .nx/ # NX workflow state
27├── code/ # Main codebase
28│ ├── .storybook/ # Internal Storybook UI config
29│ ├── core/ # Core package published as "storybook"
30│ ├── addons/ # Core addons
31│ ├── builders/ # Builder integrations
32│ ├── renderers/ # Renderer integrations
33│ ├── frameworks/ # Framework integrations
34│ ├── lib/ # Supporting libraries
35│ ├── presets/ # Webpack-oriented presets
36│ └── sandbox/ # Internal build artifacts
37├── scripts/ # Build and development scripts
38├── docs/ # Documentation
39├── test-storybooks/ # Test repos
40└── ../storybook-sandboxes/ # Generated sandboxes outside repo
41```
42
43## Architecture
44
45### Renderer vs builder vs framework
46
47| Concept | Role | Example |
48| --------- | ------------------------------------- | ------------------------- |
49| Renderer | Mounts UI framework to the DOM | `@storybook/react` |
50| Builder | Bundles and serves Storybook | `@storybook/builder-vite` |
51| Framework | Renderer + builder + framework config | `@storybook/react-vite` |
52
53### Core package
54
55The main package is `code/core/src/`. The most important areas are:
56
57- `core-server/` for dev server, static build, and presets
58- `manager/` and `manager-api/` for the Storybook UI
59- `preview/` and `preview-api/` for story rendering
60- `channels/` for manager <-> preview communication
61- `csf-tools/` for AST-based story indexing
62- `common/` for shared Node.js utilities
63- `test/` and `instrumenter/` for testing support
64
65Public exports include:
66
67- `storybook/actions`
68- `storybook/preview-api`
69- `storybook/manager-api`
70- `storybook/theming`
71- `storybook/test`
72
73Internal exports include:
74
75- `storybook/internal/core-server`
76- `storybook/internal/csf-tools`
77- `storybook/internal/common`
78- `storybook/internal/channels`
79
80### Key flow
81
82- `.storybook/main.ts` is loaded at startup
83- `.storybook/preview.ts` is bundled into preview (TSX for React-based frameworks)
84- `.storybook/manager.ts` is bundled into manager
85- `*.stories.*` files are indexed by AST before runtime
86- Story selection loads the module, prepares the story, and renders it
87
88AST indexing keeps the sidebar fast and prevents one broken story file from breaking the whole UI.
89
90### Open services and toolsets
91
92- OSA hosts two sibling constructs behind the `storybook/open-service` entry: **services**
93 (`defineService`/`registerService`) own internal state, synchronization, queries, commands, and
94 loading; **toolsets** (`defineToolset`/`registerToolset`) are the public agent surface for CLI/MCP.
95 They live in mirrored trees: `open-service/services/` and `open-service/toolsets/`.
96- All core OSA services are `internal: true` and may change without a public semver bump. Resolve
97 internal services with `getService(id, { internal: true })`. A plain `getService(id)` throws when
98 the service is internal.
99- A toolset has an `id`, description, and methods with only `schema`, `description`, and `handler`.
100- Toolsets register imperatively via `registerToolset`, called from the same place the paired
101 service registers (the `services` preset hook for core and addons; the mechanism itself does not
102 depend on the Node preset system). Feature gating is shared: a disabled feature registers neither
103 the service nor its toolset. Adapters read the set via `getRegisteredToolsets()`; nothing consumes
104 it before Milestone 4.
105- Handlers receive `(input, ctx)` with `consumer` (`'cli' | 'mcp'`), optional `origin`, required
106 `format` (`'markdown' | 'json'`), and `getService`. Methods never declare the output format;
107 adapters own the mapping (CLI `--json` flag, MCP `json` tool input).
108- The docs toolset's Markdown is a verbatim port of the `@storybook/mcp` manifest formatter
109 (`toolsets/docs/manifest-formatter/`); the two copies must not drift until Milestone 4 deletes the
110 original. MCP consumer + Markdown is the parity-tested cell.
111- The toolset surface remains experimental. Production MCP migration is Milestone 4. CLI generation
112 and production `storybook tools` wiring are Milestone 5. MCP tools remain hand-authored in
113 `addon-mcp` until Milestone 4.
114
115## Common Commands
116
117Run commands from the repository root unless stated otherwise.
118
119For routine agent work, prefer the faster non-production commands first. Add `-c production` only when you need sandbox-related NX tasks or you are explicitly matching CI behavior.
120
121### Install and compile
122
123```bash
124yarn
125yarn task compile
126yarn nx run-many -t compile
127yarn nx compile <nx-project-name>
128```
129
130### Lint and typecheck
131
132```bash
133yarn lint
134yarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix
135yarn task check
136yarn nx run-many -t check
137```
138
139### Development and tests
140
141```bash
142cd code && yarn storybook:ui
143cd code && yarn storybook:ui:build
144yarn test
145yarn test:watch
146yarn storybook:vitest
147```
148
149### Common task scenarios
150
151| Scenario | Command |
152| ------------------------------- | ------------------------------------------------------------------------------ |
153| Compile everything quickly | `yarn nx run-many -t compile` |
154| Compile one project | `yarn nx compile <nx-project-name>` |
155| Check TypeScript errors quickly | `yarn nx run-many -t check` |
156| Start the internal Storybook UI | `cd code && yarn storybook:ui` |
157| Build the internal Storybook UI | `cd code && yarn storybook:ui:build` |
158| Run unit tests | `yarn test` |
159| Run Storybook Vitest tests | `yarn storybook:vitest` |
160| Generate a sandbox | `yarn task sandbox --template react-vite/default-ts --start-from auto` |
161| Run sandbox E2E tests | `yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto` |
162| Run sandbox test-runner tests | `yarn task test-runner-dev --template react-vite/default-ts --start-from auto` |
163| Run the docgen perf bench | `yarn workspace @storybook/docgen-harness bench:docgen-perf` |
164| Run the docgen memory gate | `yarn workspace @storybook/docgen-harness bench:docgen-memory` |
165
166## NX and `yarn task`
167
168Use NX when you want better caching and dependency tracking. Prefer these faster defaults first, and only add `-c production` or `--no-link` when you specifically need sandbox parity or CI-like behavior.
169
170```bash
171# Compile all packages
172yarn task compile
173yarn nx run-many -t compile
174
175# Check all packages
176yarn task check
177yarn nx run-many -t check
178
179# Run E2E tests for a template
180yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto
181yarn nx e2e-tests-dev react-vite/default-ts -c production
182
183# Jump to a later step
184yarn task e2e-tests-dev --start-from e2e-tests --template react-vite/default-ts
185yarn nx e2e-tests-dev -c production --exclude-task-dependencies
186```
187
188Key points:
189
190- `-c production` is required for sandbox-related NX commands and CI-parity runs
191- `react-vite/default-ts` is the default sandbox template
192- `--no-link` is opt-in, not the default
193- NX handles task dependencies via `nx.json`
194- NX target commands use Nx project names (from `project.json` / Nx graph), not `package.json` names
195- Example: `yarn nx compile core` (project `core` is published as package `storybook`)
196- NX Cloud remote-cache auth failures (e.g. HTTP 401 "insufficient access") degrade to the local cache, so they are expected on local runs where `NX_CLOUD_ACCESS_TOKEN` is unset. CI always sets that token, so a 401 there means an invalid or expired token and should be investigated rather than ignored. A read-only token enables cache reads but cannot store artifacts, so the "wasn't able to store" warning is still expected with one
197
198## Sandbox Notes
199
200Sandboxes are generated outside the repository at `../storybook-sandboxes/` by default.
201
202- `STORYBOOK_SANDBOX_ROOT=./sandbox` forces local output, but is usually not preferred
203- `./sandbox` inside the repo mainly exists for NX outputs, not CI sandboxes
204- If sandbox generation fails, fall back to `cd code && yarn storybook:ui`
205
206Generate and use a sandbox with the same `sandbox` command shape used elsewhere in this file:
207
208```bash
209yarn task sandbox --template react-vite/default-ts --start-from auto
210# Same sandbox step via NX
211yarn nx sandbox react-vite/default-ts -c production
212cd ../storybook-sandboxes/react-vite-default-ts
213yarn install
214yarn storybook
215```
216
217Common templates:
218
219- `react-vite/default-ts`
220- `react-webpack/default-ts`
221- `angular-cli/default-ts`
222- `svelte-vite/default-ts`
223- `vue3-vite/default-ts`
224- `nextjs/default-ts`
225
226## How To Work In This Repo
227
228### For normal code changes
229
2301. Install if needed: `yarn`
2312. Compile with NX: `yarn nx run-many -t compile`
2323. Make changes
2334. Recompile affected packages
2345. Validate there are no TypeScript errors with `yarn nx run-many -t check`
2356. Run relevant lint and tests
2367. Validate behavior in the internal Storybook UI first, then switch to sandbox or `-c production` flows only if you need template or CI parity
237
238### For addon, framework, or renderer work
239
2401. Edit the relevant package under `code/addons/`, `code/frameworks/`, or `code/renderers/`
2412. Recompile with NX, starting without `-c production`
2423. Generate a matching sandbox
2434. Run the relevant test-runner, E2E, or Storybook UI validation flow
244
245## Testing Expectations
246
247> [!IMPORTANT]
248> **For React components, write Storybook stories with `play` functions — do NOT write `*.test.tsx` unit tests.** Behavior, accessibility, and interaction assertions belong in `*.stories.tsx` co-located with the component, executed via the Storybook Vitest project (`yarn storybook:vitest` or `vitest run --config code/vitest.config.storybook.ts`). Unit tests (`*.test.ts(x)`) are reserved for pure utilities, hooks, and non-React modules where rendering is not involved.
249
250- Use `yarn storybook:vitest` to run Storybook story tests (the primary test path for components)
251- Use `yarn test` for unit tests of utilities, hooks, and non-React modules
252- Prefer focused unit-test runs during iteration — the full suite is large: `yarn test <pattern>` (e.g. `yarn test csf-tools`)
253- Use Storybook UI or Chromatic for visual validation
254- Use `yarn task e2e-tests --start-from auto` or `yarn task e2e-tests-dev --start-from auto` for E2E coverage
255- Use `yarn task test-runner --start-from auto` or `yarn task test-runner-dev --start-from auto` for test-runner scenarios
256- Use `yarn task smoke-test --start-from auto` for smoke checks
257
258Watch-mode commands:
259
260```bash
261yarn test:watch
262yarn storybook:vitest
263```
264
265When writing tests for components:
266
267- Add or update `<Component>.stories.tsx` with stories covering each behavior; use `play` functions with `expect`, `userEvent`, `within` from `storybook/test`
268- Mock external context (e.g. `ManagerContext.Provider`) inside story decorators or `beforeEach`
269- Run `vitest --config code/vitest.config.storybook.ts <story-file>` to verify play assertions
270
271When writing unit tests (utilities, hooks, non-React modules):
272
273- Export functions that need direct tests
274- Test real behavior, not just syntax patterns
275- Use coverage when useful: `yarn vitest run --coverage <test-file>`
276- Mock external dependencies like file system access and loggers
277- Use Node's path.resolve to wrap expected FS paths when writing path-related tests, so they work on Windows
278
279### Filesystem tests with `memfs`
280
281For unit tests that touch `node:fs` / `node:fs/promises`, use [`memfs`](https://github.com/streamich/memfs) instead of real temp directories or wholesale `node:fs` mocks:
282
283- Import `vol` from `memfs` and call `vol.reset()` in `beforeEach`
284- Seed virtual files with `vol.fromNestedJSON({ '/absolute/path/file.json': '...' })` or memfs `writeFile` after redirecting spies
285- Use `vi.mock('node:fs/promises', { spy: true })` and, in `beforeEach`, point `mkdir` / `writeFile` / `readFile` at `memfs.fs.promises` (see `code/core/src/shared/open-service/server.test.ts`)
286- Assert disk state with `vol.toJSON()` when helpful
287
288Do **not** use `/tmp` paths or replace `node:fs/promises` with a full async factory mock unless a test file already standardizes on the spy redirect pattern above.
289
290### Globals in tests: never assign `globalThis.*` directly
291
292> [!IMPORTANT]
293> Under no circumstances may a test mutate a global by assigning it directly (e.g. `globalThis.FEATURES = {...}`, `globalThis.window = ...`, `global.fetch = ...`). Direct assignment leaks across tests and files — Vitest does not restore it — so it silently changes behavior in unrelated tests and creates order-dependent flakiness.
294
295Use Vitest's global stubbing instead, which is tracked and restorable:
296
297- Set a global with `vi.stubGlobal('FEATURES', { experimentalDocgenServer: true })`.
298- Restore in `afterEach(() => vi.unstubAllGlobals())` (or enable `unstubGlobals: true` in the Vitest config so it resets before each test automatically).
299- For a value used by every test in a file, stub it in `beforeEach` and unstub in `afterEach`; for a one-off override, call `vi.stubGlobal` inside that single test.
300- Never capture-and-restore by hand (`const original = globalThis.X; ... globalThis.X = original`); `vi.stubGlobal` + `vi.unstubAllGlobals()` does this correctly, including deleting keys that did not previously exist.
301
302This applies to all ambient globals, not just `FEATURES` (e.g. `window`, `document`, `navigator`, `fetch`, `IS_REACT_ACT_ENVIRONMENT`).
303
304## Quality and Logging
305
306After changing files:
307
3081. **Always** format with `yarn fmt:write`, run from the `code/` directory (`cd code && yarn fmt:write`), once you are done editing. The repo uses `oxfmt`, so hand-written formatting will frequently be wrong — do not skip this step.
3092. Lint with `yarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix` or `cd code && yarn lint:js:cmd <file-relative-to-code-folder>`
3103. Run relevant tests before submitting a PR
311
312Use Storybook loggers instead of raw `console.*` in normal code paths:
313
314- Server-side: `storybook/internal/node-logger`
315- Client-side: `storybook/internal/client-logger`
316
317For TypeScript source in the repo, prefer explicit file extensions for relative code imports and exports such as `./foo.ts` or `./bar.tsx` when the target is another TS/JS module in this repository. Keep framework-specific component imports like `.vue` and `.svelte` in the form already expected by their package tooling.
318
319The pre-commit hook automatically detects AI agents (via `std-env`) and switches from check-only to write mode, so formatting is auto-fixed when agents commit.
320
321Avoid `console.log`, `console.warn`, and `console.error` unless the file is isolated enough that importing the logger is not reasonable.
322
323## Troubleshooting
324
325- Build failures are often fixed by rerunning `yarn` and `yarn nx run-many -t compile`
326- Storybook UI uses port `6006` by default
327- Large compiles may require more Node.js memory
328- Sandbox paths are `../storybook-sandboxes/`, not `./sandbox` or `code/sandbox/`
329- Use `--debug` for verbose CLI output
330- Check generated sandbox directories and `.cache/` for build artifacts
331
332## Environment Variables
333
334| Variable | Purpose |
335| ----------------------------- | ----------------------------------------------- |
336| `IN_STORYBOOK_SANDBOX` | Set during sandbox creation |
337| `STORYBOOK_DISABLE_TELEMETRY` | Disable telemetry |
338| `STORYBOOK_TELEMETRY_DEBUG` | Log telemetry events |
339| `DEBUG` | Enable debug logging |
340| `FIX_ON_COMMIT` | Force autofix for fmt & lint in pre-commit hook |
341| `NX_CLOUD_ACCESS_TOKEN` | Authenticate the NX Cloud remote cache |
342
343## Commands To Avoid
344
345- **DO NOT RUN** `yarn task dev` without an explicit sandbox template
346- **DO NOT RUN** `yarn start`
347
348These usually start long-running development servers and are the wrong default for agents.
349
350## Code Authoring Principles
351
352These are recurring failure modes in agent-authored changes to this repo. Apply them when writing or reviewing code, not just when asked.
353
354- **Comments are maintenance docs, not an investigation transcript.** Explain *why* for the next maintainer. Do not commit internal ticket / acceptance-criteria codes (`AC-X2`, `Probe B`, `R6`), the narrative of how you figured something out, "verified byte-identical" provenance prose, or cross-file line references (`L125→L131`) — they are noise and they rot. One or two sentences of rationale beats a paragraph of evidence.
355- **Verify environment assumptions empirically before encoding them.** If a design rests on "the bundler strips X" or "this metadata is empty here", prove it with a throwaway probe before building on it (and before writing it into a comment as fact). A 10-line experiment is cheaper than a wrong architecture.
356- **Encode assumptions with static checks first.** If an assumption is expected to always hold, prefer making it impossible via TypeScript types and existing lint rules. When static checks are not practical, add a cheap runtime assertion close to the boundary so violations fail loudly at the source.
357- **Avoid redundant tests already covered elsewhere.** Do not add tests for code patterns already guaranteed by TypeScript or linting, and do not duplicate coverage that already exists in Storybook `play` functions or Playwright tests.
358- **Test contracts (including side effects), not private implementation details.** It is valid to assert side effects when they are part of the public contract. Avoid assertions about internals that are not part of an exported contract, user-visible DOM output, or externally observable behavior.
359- **Bias toward broader coverage for security and migrations.** For security-sensitive code paths and legacy data migration logic, prefer handling more edge cases and documenting evidence for the chosen safeguards. Migration compatibility code should be explicitly version-scoped so it can be removed once the support window ends.
360- **Prefer deletion and simplicity over speculative generality.** No abstraction, fallback, or "flexibility" for a consumer or scenario that does not exist in this codebase today. If a change adds many lines, check whether the right change removes them.
361- **Don't commit accidental overrides to generated code.** Files like `code/core/src/manager/globals/exports.ts` are auto-generated, as stated in their JSDoc header. Only commit changes if they match changes you made on your PR, otherwise leave them untouched and flag flaky generated files in the PR description.
362
363## Maintenance Rules For Agents
364
365- Use this file as the canonical instruction source
366- Update `AGENTS.md` when architecture, commands, versions, release flows, or contributor guidance changes
367- Keep `CLAUDE.md` and other agent entrypoints as thin references to `AGENTS.md`
368- Do not reintroduce duplicated instruction files when a reference will do
369
storybookjs/storybook · .cursorrules
@@ +1 @@
1## Test Configuration
2
3This Storybook repository uses Vitest as the test runner. Here are the key commands and configuration:
4
5### Test Scripts
6
7- `yarn test` - Run all tests (from root directory, delegates to `cd code; yarn test`)
8- `yarn test <test-name>` - Run focused tests matching the pattern
9- `yarn test:watch` - Run tests in watch mode
10- `yarn test:watch <test-name>` - Run focused tests in watch mode
11
12### Test Directory Structure
13
14- Tests are located in the `code/` directory
15- Vitest configuration is in `code/vitest.workspace.ts`
16- Test files typically follow the pattern `*.test.ts`, `*.test.tsx`, `*.spec.ts`, or `*.spec.tsx`
17
18### Running Tests in Cursor
19
201. Use Cmd+Shift+P (or Ctrl+Shift+P) and search for "Tasks: Run Task"
212. Select from the available test tasks:
22 - "Run All Tests" - Runs all tests
23 - "Run Test (Watch Mode)" - Runs tests in watch mode
24 - "Run Focused Test" - Prompts for test name/pattern to run specific tests
25 - "Run Focused Test (Watch Mode)" - Runs specific tests in watch mode
26
27### Vitest Configuration
28
29- Workspace configuration: `./code/vitest.workspace.ts`
30- Command line: `yarn --cwd code test`
31- Root directory for tests: `./code/`
32
33### Test Execution Context
34
35- Tests run from the `code/` directory
36- Use `NODE_OPTIONS=--max_old_space_size=4096` for memory optimization
37- Supports both watch mode and single-run execution
38
39### Focused Test Patterns
40
41When running focused tests, you can use:
42
43- File names: `Button.test.ts`
44- Test descriptions: `"should render correctly"`
45- Directory patterns: `components/`
46- Vitest patterns: `-t "pattern"` for test name matching
47
48### Test Mocking Rules
49
50Follow the spy mocking rules defined in `.cursor/rules/spy-mocking.mdc` for consistent mocking patterns with Vitest.
51
@@ −1 +1 @@
1−# Storybook Agent Instructions
1+## Test Configuration
22
3−Keep this file, `AGENTS.md`, up to date when Storybook's architecture, tooling, workflows, or contributor guidance changes.
3+This Storybook repository uses Vitest as the test runner. Here are the key commands and configuration:
44
5−This file is the canonical instruction source for coding agents. Files like `CLAUDE.md` should point here instead of duplicating instructions.
5+### Test Scripts
66
7−## Repository Overview
7+- `yarn test` - Run all tests (from root directory, delegates to `cd code; yarn test`)
8+- `yarn test <test-name>` - Run focused tests matching the pattern
9+- `yarn test:watch` - Run tests in watch mode
10+- `yarn test:watch <test-name>` - Run focused tests in watch mode
811
9−Storybook is a large TypeScript monorepo. The git root is the repo root, the main code lives in `code/`, and build tooling lives in `scripts/`. The default branch is `next`.
12+### Test Directory Structure
1013
11−- **Base branch**: `next` (all PRs should target `next`, not `main`)
12−- **Node.js**: `22.22.3` (see `.nvmrc`) — supports `.ts` natively via type stripping (no loader needed)
13−- **Package Manager**: Yarn Berry
14−- **Task orchestration**: NX plus the custom `yarn task` runner
15−- **Linting**: oxlint (root `.oxlintrc.json`, extended by `code/.oxlintrc.json` and `scripts/.oxlintrc.json`; custom rules load via `jsPlugins`). ESLint is no longer used for repo linting — `code/lib/eslint-plugin` remains as the published `eslint-plugin-storybook` package.
16−- **Formatting**: oxfmt (root `.oxfmtrc.json`)
17−- **CI environment**: Linux and Windows
18−- **TS execution**: Migrating from `jiti` to native `node` for running `.ts` files. New scripts should use `node ./path/file.ts` with explicit `.ts` import extensions (enabled by `allowImportingTsExtensions` in tsconfig). Legacy scripts still use `jiti` but should be migrated over time.
19−- **Type checking**: Per-package checks (`yarn task check`, `scripts/check/check-package.ts`) run on the TypeScript 7 native compiler (the `typescript-native` npm alias); diagnostics are filtered to the checked package. `@storybook/vue3`, `@storybook/docgen-harness` (for its `.vue` fixtures), and `@storybook/svelte` use `vue-tsc` / `svelte-check` (TS 6 based). The workspace `typescript` dependency stays on TS 6 for IDEs and API consumers, so tsconfigs must remain valid for both (e.g. no `baseUrl`).
14+- Tests are located in the `code/` directory
15+- Vitest configuration is in `code/vitest.workspace.ts`
16+- Test files typically follow the pattern `*.test.ts`, `*.test.tsx`, `*.spec.ts`, or `*.spec.tsx`
2017
21−## Repository Structure
18+### Running Tests in Cursor
2219
23−```text
24−storybook/
25−├── .github/ # GitHub configs and workflows
26−├── .nx/ # NX workflow state
27−├── code/ # Main codebase
28−│ ├── .storybook/ # Internal Storybook UI config
29−│ ├── core/ # Core package published as "storybook"
30−│ ├── addons/ # Core addons
31−│ ├── builders/ # Builder integrations
32−│ ├── renderers/ # Renderer integrations
33−│ ├── frameworks/ # Framework integrations
34−│ ├── lib/ # Supporting libraries
35−│ ├── presets/ # Webpack-oriented presets
36−│ └── sandbox/ # Internal build artifacts
37−├── scripts/ # Build and development scripts
38−├── docs/ # Documentation
39−├── test-storybooks/ # Test repos
40−└── ../storybook-sandboxes/ # Generated sandboxes outside repo
41−```
20+1. Use Cmd+Shift+P (or Ctrl+Shift+P) and search for "Tasks: Run Task"
21+2. Select from the available test tasks:
22+ - "Run All Tests" - Runs all tests
23+ - "Run Test (Watch Mode)" - Runs tests in watch mode
24+ - "Run Focused Test" - Prompts for test name/pattern to run specific tests
25+ - "Run Focused Test (Watch Mode)" - Runs specific tests in watch mode
4226
43−## Architecture
27+### Vitest Configuration
4428
45−### Renderer vs builder vs framework
29+- Workspace configuration: `./code/vitest.workspace.ts`
30+- Command line: `yarn --cwd code test`
31+- Root directory for tests: `./code/`
4632
47−| Concept | Role | Example |
48−| --------- | ------------------------------------- | ------------------------- |
49−| Renderer | Mounts UI framework to the DOM | `@storybook/react` |
50−| Builder | Bundles and serves Storybook | `@storybook/builder-vite` |
51−| Framework | Renderer + builder + framework config | `@storybook/react-vite` |
33+### Test Execution Context
5234
53−### Core package
35+- Tests run from the `code/` directory
36+- Use `NODE_OPTIONS=--max_old_space_size=4096` for memory optimization
37+- Supports both watch mode and single-run execution
5438
55−The main package is `code/core/src/`. The most important areas are:
39+### Focused Test Patterns
5640
57−- `core-server/` for dev server, static build, and presets
58−- `manager/` and `manager-api/` for the Storybook UI
59−- `preview/` and `preview-api/` for story rendering
60−- `channels/` for manager <-> preview communication
61−- `csf-tools/` for AST-based story indexing
62−- `common/` for shared Node.js utilities
63−- `test/` and `instrumenter/` for testing support
41+When running focused tests, you can use:
6442
65−Public exports include:
43+- File names: `Button.test.ts`
44+- Test descriptions: `"should render correctly"`
45+- Directory patterns: `components/`
46+- Vitest patterns: `-t "pattern"` for test name matching
6647
67−- `storybook/actions`
68−- `storybook/preview-api`
69−- `storybook/manager-api`
70−- `storybook/theming`
71−- `storybook/test`
48+### Test Mocking Rules
7249
73−Internal exports include:
74−
75−- `storybook/internal/core-server`
76−- `storybook/internal/csf-tools`
77−- `storybook/internal/common`
78−- `storybook/internal/channels`
79−
80−### Key flow
81−
82−- `.storybook/main.ts` is loaded at startup
83−- `.storybook/preview.ts` is bundled into preview (TSX for React-based frameworks)
84−- `.storybook/manager.ts` is bundled into manager
85−- `*.stories.*` files are indexed by AST before runtime
86−- Story selection loads the module, prepares the story, and renders it
87−
88−AST indexing keeps the sidebar fast and prevents one broken story file from breaking the whole UI.
89−
90−### Open services and toolsets
91−
92−- OSA hosts two sibling constructs behind the `storybook/open-service` entry: **services**
93− (`defineService`/`registerService`) own internal state, synchronization, queries, commands, and
94− loading; **toolsets** (`defineToolset`/`registerToolset`) are the public agent surface for CLI/MCP.
95− They live in mirrored trees: `open-service/services/` and `open-service/toolsets/`.
96−- All core OSA services are `internal: true` and may change without a public semver bump. Resolve
97− internal services with `getService(id, { internal: true })`. A plain `getService(id)` throws when
98− the service is internal.
99−- A toolset has an `id`, description, and methods with only `schema`, `description`, and `handler`.
100−- Toolsets register imperatively via `registerToolset`, called from the same place the paired
101− service registers (the `services` preset hook for core and addons; the mechanism itself does not
102− depend on the Node preset system). Feature gating is shared: a disabled feature registers neither
103− the service nor its toolset. Adapters read the set via `getRegisteredToolsets()`; nothing consumes
104− it before Milestone 4.
105−- Handlers receive `(input, ctx)` with `consumer` (`'cli' | 'mcp'`), optional `origin`, required
106− `format` (`'markdown' | 'json'`), and `getService`. Methods never declare the output format;
107− adapters own the mapping (CLI `--json` flag, MCP `json` tool input).
108−- The docs toolset's Markdown is a verbatim port of the `@storybook/mcp` manifest formatter
109− (`toolsets/docs/manifest-formatter/`); the two copies must not drift until Milestone 4 deletes the
110− original. MCP consumer + Markdown is the parity-tested cell.
111−- The toolset surface remains experimental. Production MCP migration is Milestone 4. CLI generation
112− and production `storybook tools` wiring are Milestone 5. MCP tools remain hand-authored in
113− `addon-mcp` until Milestone 4.
114−
115−## Common Commands
116−
117−Run commands from the repository root unless stated otherwise.
118−
119−For routine agent work, prefer the faster non-production commands first. Add `-c production` only when you need sandbox-related NX tasks or you are explicitly matching CI behavior.
120−
121−### Install and compile
122−
123−```bash
124−yarn
125−yarn task compile
126−yarn nx run-many -t compile
127−yarn nx compile <nx-project-name>
128−```
129−
130−### Lint and typecheck
131−
132−```bash
133−yarn lint
134−yarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix
135−yarn task check
136−yarn nx run-many -t check
137−```
138−
139−### Development and tests
140−
141−```bash
142−cd code && yarn storybook:ui
143−cd code && yarn storybook:ui:build
144−yarn test
145−yarn test:watch
146−yarn storybook:vitest
147−```
148−
149−### Common task scenarios
150−
151−| Scenario | Command |
152−| ------------------------------- | ------------------------------------------------------------------------------ |
153−| Compile everything quickly | `yarn nx run-many -t compile` |
154−| Compile one project | `yarn nx compile <nx-project-name>` |
155−| Check TypeScript errors quickly | `yarn nx run-many -t check` |
156−| Start the internal Storybook UI | `cd code && yarn storybook:ui` |
157−| Build the internal Storybook UI | `cd code && yarn storybook:ui:build` |
158−| Run unit tests | `yarn test` |
159−| Run Storybook Vitest tests | `yarn storybook:vitest` |
160−| Generate a sandbox | `yarn task sandbox --template react-vite/default-ts --start-from auto` |
161−| Run sandbox E2E tests | `yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto` |
162−| Run sandbox test-runner tests | `yarn task test-runner-dev --template react-vite/default-ts --start-from auto` |
163−| Run the docgen perf bench | `yarn workspace @storybook/docgen-harness bench:docgen-perf` |
164−| Run the docgen memory gate | `yarn workspace @storybook/docgen-harness bench:docgen-memory` |
165−
166−## NX and `yarn task`
167−
168−Use NX when you want better caching and dependency tracking. Prefer these faster defaults first, and only add `-c production` or `--no-link` when you specifically need sandbox parity or CI-like behavior.
169−
170−```bash
171−# Compile all packages
172−yarn task compile
173−yarn nx run-many -t compile
174−
175−# Check all packages
176−yarn task check
177−yarn nx run-many -t check
178−
179−# Run E2E tests for a template
180−yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto
181−yarn nx e2e-tests-dev react-vite/default-ts -c production
182−
183−# Jump to a later step
184−yarn task e2e-tests-dev --start-from e2e-tests --template react-vite/default-ts
185−yarn nx e2e-tests-dev -c production --exclude-task-dependencies
186−```
187−
188−Key points:
189−
190−- `-c production` is required for sandbox-related NX commands and CI-parity runs
191−- `react-vite/default-ts` is the default sandbox template
192−- `--no-link` is opt-in, not the default
193−- NX handles task dependencies via `nx.json`
194−- NX target commands use Nx project names (from `project.json` / Nx graph), not `package.json` names
195−- Example: `yarn nx compile core` (project `core` is published as package `storybook`)
196−- NX Cloud remote-cache auth failures (e.g. HTTP 401 "insufficient access") degrade to the local cache, so they are expected on local runs where `NX_CLOUD_ACCESS_TOKEN` is unset. CI always sets that token, so a 401 there means an invalid or expired token and should be investigated rather than ignored. A read-only token enables cache reads but cannot store artifacts, so the "wasn't able to store" warning is still expected with one
197−
198−## Sandbox Notes
199−
200−Sandboxes are generated outside the repository at `../storybook-sandboxes/` by default.
201−
202−- `STORYBOOK_SANDBOX_ROOT=./sandbox` forces local output, but is usually not preferred
203−- `./sandbox` inside the repo mainly exists for NX outputs, not CI sandboxes
204−- If sandbox generation fails, fall back to `cd code && yarn storybook:ui`
205−
206−Generate and use a sandbox with the same `sandbox` command shape used elsewhere in this file:
207−
208−```bash
209−yarn task sandbox --template react-vite/default-ts --start-from auto
210−# Same sandbox step via NX
211−yarn nx sandbox react-vite/default-ts -c production
212−cd ../storybook-sandboxes/react-vite-default-ts
213−yarn install
214−yarn storybook
215−```
216−
217−Common templates:
218−
219−- `react-vite/default-ts`
220−- `react-webpack/default-ts`
221−- `angular-cli/default-ts`
222−- `svelte-vite/default-ts`
223−- `vue3-vite/default-ts`
224−- `nextjs/default-ts`
225−
226−## How To Work In This Repo
227−
228−### For normal code changes
229−
230−1. Install if needed: `yarn`
231−2. Compile with NX: `yarn nx run-many -t compile`
232−3. Make changes
233−4. Recompile affected packages
234−5. Validate there are no TypeScript errors with `yarn nx run-many -t check`
235−6. Run relevant lint and tests
236−7. Validate behavior in the internal Storybook UI first, then switch to sandbox or `-c production` flows only if you need template or CI parity
237−
238−### For addon, framework, or renderer work
239−
240−1. Edit the relevant package under `code/addons/`, `code/frameworks/`, or `code/renderers/`
241−2. Recompile with NX, starting without `-c production`
242−3. Generate a matching sandbox
243−4. Run the relevant test-runner, E2E, or Storybook UI validation flow
244−
245−## Testing Expectations
246−
247−> [!IMPORTANT]
248−> **For React components, write Storybook stories with `play` functions — do NOT write `*.test.tsx` unit tests.** Behavior, accessibility, and interaction assertions belong in `*.stories.tsx` co-located with the component, executed via the Storybook Vitest project (`yarn storybook:vitest` or `vitest run --config code/vitest.config.storybook.ts`). Unit tests (`*.test.ts(x)`) are reserved for pure utilities, hooks, and non-React modules where rendering is not involved.
249−
250−- Use `yarn storybook:vitest` to run Storybook story tests (the primary test path for components)
251−- Use `yarn test` for unit tests of utilities, hooks, and non-React modules
252−- Prefer focused unit-test runs during iteration — the full suite is large: `yarn test <pattern>` (e.g. `yarn test csf-tools`)
253−- Use Storybook UI or Chromatic for visual validation
254−- Use `yarn task e2e-tests --start-from auto` or `yarn task e2e-tests-dev --start-from auto` for E2E coverage
255−- Use `yarn task test-runner --start-from auto` or `yarn task test-runner-dev --start-from auto` for test-runner scenarios
256−- Use `yarn task smoke-test --start-from auto` for smoke checks
257−
258−Watch-mode commands:
259−
260−```bash
261−yarn test:watch
262−yarn storybook:vitest
263−```
264−
265−When writing tests for components:
266−
267−- Add or update `<Component>.stories.tsx` with stories covering each behavior; use `play` functions with `expect`, `userEvent`, `within` from `storybook/test`
268−- Mock external context (e.g. `ManagerContext.Provider`) inside story decorators or `beforeEach`
269−- Run `vitest --config code/vitest.config.storybook.ts <story-file>` to verify play assertions
270−
271−When writing unit tests (utilities, hooks, non-React modules):
272−
273−- Export functions that need direct tests
274−- Test real behavior, not just syntax patterns
275−- Use coverage when useful: `yarn vitest run --coverage <test-file>`
276−- Mock external dependencies like file system access and loggers
277−- Use Node's path.resolve to wrap expected FS paths when writing path-related tests, so they work on Windows
278−
279−### Filesystem tests with `memfs`
280−
281−For unit tests that touch `node:fs` / `node:fs/promises`, use [`memfs`](https://github.com/streamich/memfs) instead of real temp directories or wholesale `node:fs` mocks:
282−
283−- Import `vol` from `memfs` and call `vol.reset()` in `beforeEach`
284−- Seed virtual files with `vol.fromNestedJSON({ '/absolute/path/file.json': '...' })` or memfs `writeFile` after redirecting spies
285−- Use `vi.mock('node:fs/promises', { spy: true })` and, in `beforeEach`, point `mkdir` / `writeFile` / `readFile` at `memfs.fs.promises` (see `code/core/src/shared/open-service/server.test.ts`)
286−- Assert disk state with `vol.toJSON()` when helpful
287−
288−Do **not** use `/tmp` paths or replace `node:fs/promises` with a full async factory mock unless a test file already standardizes on the spy redirect pattern above.
289−
290−### Globals in tests: never assign `globalThis.*` directly
291−
292−> [!IMPORTANT]
293−> Under no circumstances may a test mutate a global by assigning it directly (e.g. `globalThis.FEATURES = {...}`, `globalThis.window = ...`, `global.fetch = ...`). Direct assignment leaks across tests and files — Vitest does not restore it — so it silently changes behavior in unrelated tests and creates order-dependent flakiness.
294−
295−Use Vitest's global stubbing instead, which is tracked and restorable:
296−
297−- Set a global with `vi.stubGlobal('FEATURES', { experimentalDocgenServer: true })`.
298−- Restore in `afterEach(() => vi.unstubAllGlobals())` (or enable `unstubGlobals: true` in the Vitest config so it resets before each test automatically).
299−- For a value used by every test in a file, stub it in `beforeEach` and unstub in `afterEach`; for a one-off override, call `vi.stubGlobal` inside that single test.
300−- Never capture-and-restore by hand (`const original = globalThis.X; ... globalThis.X = original`); `vi.stubGlobal` + `vi.unstubAllGlobals()` does this correctly, including deleting keys that did not previously exist.
301−
302−This applies to all ambient globals, not just `FEATURES` (e.g. `window`, `document`, `navigator`, `fetch`, `IS_REACT_ACT_ENVIRONMENT`).
303−
304−## Quality and Logging
305−
306−After changing files:
307−
308−1. **Always** format with `yarn fmt:write`, run from the `code/` directory (`cd code && yarn fmt:write`), once you are done editing. The repo uses `oxfmt`, so hand-written formatting will frequently be wrong — do not skip this step.
309−2. Lint with `yarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix` or `cd code && yarn lint:js:cmd <file-relative-to-code-folder>`
310−3. Run relevant tests before submitting a PR
311−
312−Use Storybook loggers instead of raw `console.*` in normal code paths:
313−
314−- Server-side: `storybook/internal/node-logger`
315−- Client-side: `storybook/internal/client-logger`
316−
317−For TypeScript source in the repo, prefer explicit file extensions for relative code imports and exports such as `./foo.ts` or `./bar.tsx` when the target is another TS/JS module in this repository. Keep framework-specific component imports like `.vue` and `.svelte` in the form already expected by their package tooling.
318−
319−The pre-commit hook automatically detects AI agents (via `std-env`) and switches from check-only to write mode, so formatting is auto-fixed when agents commit.
320−
321−Avoid `console.log`, `console.warn`, and `console.error` unless the file is isolated enough that importing the logger is not reasonable.
322−
323−## Troubleshooting
324−
325−- Build failures are often fixed by rerunning `yarn` and `yarn nx run-many -t compile`
326−- Storybook UI uses port `6006` by default
327−- Large compiles may require more Node.js memory
328−- Sandbox paths are `../storybook-sandboxes/`, not `./sandbox` or `code/sandbox/`
329−- Use `--debug` for verbose CLI output
330−- Check generated sandbox directories and `.cache/` for build artifacts
331−
332−## Environment Variables
333−
334−| Variable | Purpose |
335−| ----------------------------- | ----------------------------------------------- |
336−| `IN_STORYBOOK_SANDBOX` | Set during sandbox creation |
337−| `STORYBOOK_DISABLE_TELEMETRY` | Disable telemetry |
338−| `STORYBOOK_TELEMETRY_DEBUG` | Log telemetry events |
339−| `DEBUG` | Enable debug logging |
340−| `FIX_ON_COMMIT` | Force autofix for fmt & lint in pre-commit hook |
341−| `NX_CLOUD_ACCESS_TOKEN` | Authenticate the NX Cloud remote cache |
342−
343−## Commands To Avoid
344−
345−- **DO NOT RUN** `yarn task dev` without an explicit sandbox template
346−- **DO NOT RUN** `yarn start`
347−
348−These usually start long-running development servers and are the wrong default for agents.
349−
350−## Code Authoring Principles
351−
352−These are recurring failure modes in agent-authored changes to this repo. Apply them when writing or reviewing code, not just when asked.
353−
354−- **Comments are maintenance docs, not an investigation transcript.** Explain *why* for the next maintainer. Do not commit internal ticket / acceptance-criteria codes (`AC-X2`, `Probe B`, `R6`), the narrative of how you figured something out, "verified byte-identical" provenance prose, or cross-file line references (`L125→L131`) — they are noise and they rot. One or two sentences of rationale beats a paragraph of evidence.
355−- **Verify environment assumptions empirically before encoding them.** If a design rests on "the bundler strips X" or "this metadata is empty here", prove it with a throwaway probe before building on it (and before writing it into a comment as fact). A 10-line experiment is cheaper than a wrong architecture.
356−- **Encode assumptions with static checks first.** If an assumption is expected to always hold, prefer making it impossible via TypeScript types and existing lint rules. When static checks are not practical, add a cheap runtime assertion close to the boundary so violations fail loudly at the source.
357−- **Avoid redundant tests already covered elsewhere.** Do not add tests for code patterns already guaranteed by TypeScript or linting, and do not duplicate coverage that already exists in Storybook `play` functions or Playwright tests.
358−- **Test contracts (including side effects), not private implementation details.** It is valid to assert side effects when they are part of the public contract. Avoid assertions about internals that are not part of an exported contract, user-visible DOM output, or externally observable behavior.
359−- **Bias toward broader coverage for security and migrations.** For security-sensitive code paths and legacy data migration logic, prefer handling more edge cases and documenting evidence for the chosen safeguards. Migration compatibility code should be explicitly version-scoped so it can be removed once the support window ends.
360−- **Prefer deletion and simplicity over speculative generality.** No abstraction, fallback, or "flexibility" for a consumer or scenario that does not exist in this codebase today. If a change adds many lines, check whether the right change removes them.
361−- **Don't commit accidental overrides to generated code.** Files like `code/core/src/manager/globals/exports.ts` are auto-generated, as stated in their JSDoc header. Only commit changes if they match changes you made on your PR, otherwise leave them untouched and flag flaky generated files in the PR description.
362−
363−## Maintenance Rules For Agents
364−
365−- Use this file as the canonical instruction source
366−- Update `AGENTS.md` when architecture, commands, versions, release flows, or contributor guidance changes
367−- Keep `CLAUDE.md` and other agent entrypoints as thin references to `AGENTS.md`
368−- Do not reintroduce duplicated instruction files when a reference will do
50+Follow the spy mocking rules defined in `.cursor/rules/spy-mocking.mdc` for consistent mocking patterns with Vitest.
36951
