AGENTS.md
AGENTS.mdAGENTS.mdroot
Quality
84/100
Scores the file, not the repository.Length
2,876 words
32 headings · 7 code blocksRepository
91k
— · pushed 0 days agoLast changed
today
First indexed 3 days ago.1# Storybook Agent Instructions23Keep this file, `AGENTS.md`, up to date when Storybook's architecture, tooling, workflows, or contributor guidance changes.45This file is the canonical instruction source for coding agents. Files like `CLAUDE.md` should point here instead of duplicating instructions.67## Repository Overview89Storybook 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`.1011- **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 Berry14- **Task orchestration**: NX plus the custom `yarn task` runner15- **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 Windows18- **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`).2021## Repository Structure2223```text24storybook/25├── .github/ # GitHub configs and workflows26├── .nx/ # NX workflow state27├── code/ # Main codebase28│ ├── .storybook/ # Internal Storybook UI config29│ ├── core/ # Core package published as "storybook"30│ ├── addons/ # Core addons31│ ├── builders/ # Builder integrations32│ ├── renderers/ # Renderer integrations33│ ├── frameworks/ # Framework integrations34│ ├── lib/ # Supporting libraries35│ ├── presets/ # Webpack-oriented presets36│ └── sandbox/ # Internal build artifacts37├── scripts/ # Build and development scripts38├── docs/ # Documentation39├── test-storybooks/ # Test repos40└── ../storybook-sandboxes/ # Generated sandboxes outside repo41```4243## Architecture4445### Renderer vs builder vs framework4647| 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` |5253### Core package5455The main package is `code/core/src/`. The most important areas are:5657- `core-server/` for dev server, static build, and presets58- `manager/` and `manager-api/` for the Storybook UI59- `preview/` and `preview-api/` for story rendering60- `channels/` for manager <-> preview communication61- `csf-tools/` for AST-based story indexing62- `common/` for shared Node.js utilities63- `test/` and `instrumenter/` for testing support6465Public exports include:6667- `storybook/actions`68- `storybook/preview-api`69- `storybook/manager-api`70- `storybook/theming`71- `storybook/test`7273Internal exports include:7475- `storybook/internal/core-server`76- `storybook/internal/csf-tools`77- `storybook/internal/common`78- `storybook/internal/channels`7980### Key flow8182- `.storybook/main.ts` is loaded at startup83- `.storybook/preview.ts` is bundled into preview (TSX for React-based frameworks)84- `.storybook/manager.ts` is bundled into manager85- `*.stories.*` files are indexed by AST before runtime86- Story selection loads the module, prepares the story, and renders it8788AST indexing keeps the sidebar fast and prevents one broken story file from breaking the whole UI.8990### Open services and toolsets9192- OSA hosts two sibling constructs behind the `storybook/open-service` entry: **services**93 (`defineService`/`registerService`) own internal state, synchronization, queries, commands, and94 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. Resolve97 internal services with `getService(id, { internal: true })`. A plain `getService(id)` throws when98 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 paired101 service registers (the `services` preset hook for core and addons; the mechanism itself does not102 depend on the Node preset system). Feature gating is shared: a disabled feature registers neither103 the service nor its toolset. Adapters read the set via `getRegisteredToolsets()`; nothing consumes104 it before Milestone 4.105- Handlers receive `(input, ctx)` with `consumer` (`'cli' | 'mcp'`), optional `origin`, required106 `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 formatter109 (`toolsets/docs/manifest-formatter/`); the two copies must not drift until Milestone 4 deletes the110 original. MCP consumer + Markdown is the parity-tested cell.111- The toolset surface remains experimental. Production MCP migration is Milestone 4. CLI generation112 and production `storybook tools` wiring are Milestone 5. MCP tools remain hand-authored in113 `addon-mcp` until Milestone 4.114115## Common Commands116117Run commands from the repository root unless stated otherwise.118119For 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.120121### Install and compile122123```bash124yarn125yarn task compile126yarn nx run-many -t compile127yarn nx compile <nx-project-name>128```129130### Lint and typecheck131132```bash133yarn lint134yarn --cwd code lint:js:cmd <file-relative-to-code-folder> --fix135yarn task check136yarn nx run-many -t check137```138139### Development and tests140141```bash142cd code && yarn storybook:ui143cd code && yarn storybook:ui:build144yarn test145yarn test:watch146yarn storybook:vitest147```148149### Common task scenarios150151| 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` |165166## NX and `yarn task`167168Use 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.169170```bash171# Compile all packages172yarn task compile173yarn nx run-many -t compile174175# Check all packages176yarn task check177yarn nx run-many -t check178179# Run E2E tests for a template180yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto181yarn nx e2e-tests-dev react-vite/default-ts -c production182183# Jump to a later step184yarn task e2e-tests-dev --start-from e2e-tests --template react-vite/default-ts185yarn nx e2e-tests-dev -c production --exclude-task-dependencies186```187188Key points:189190- `-c production` is required for sandbox-related NX commands and CI-parity runs191- `react-vite/default-ts` is the default sandbox template192- `--no-link` is opt-in, not the default193- NX handles task dependencies via `nx.json`194- NX target commands use Nx project names (from `project.json` / Nx graph), not `package.json` names195- 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 one197198## Sandbox Notes199200Sandboxes are generated outside the repository at `../storybook-sandboxes/` by default.201202- `STORYBOOK_SANDBOX_ROOT=./sandbox` forces local output, but is usually not preferred203- `./sandbox` inside the repo mainly exists for NX outputs, not CI sandboxes204- If sandbox generation fails, fall back to `cd code && yarn storybook:ui`205206Generate and use a sandbox with the same `sandbox` command shape used elsewhere in this file:207208```bash209yarn task sandbox --template react-vite/default-ts --start-from auto210# Same sandbox step via NX211yarn nx sandbox react-vite/default-ts -c production212cd ../storybook-sandboxes/react-vite-default-ts213yarn install214yarn storybook215```216217Common templates:218219- `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`225226## How To Work In This Repo227228### For normal code changes2292301. Install if needed: `yarn`2312. Compile with NX: `yarn nx run-many -t compile`2323. Make changes2334. Recompile affected packages2345. Validate there are no TypeScript errors with `yarn nx run-many -t check`2356. Run relevant lint and tests2367. Validate behavior in the internal Storybook UI first, then switch to sandbox or `-c production` flows only if you need template or CI parity237238### For addon, framework, or renderer work2392401. Edit the relevant package under `code/addons/`, `code/frameworks/`, or `code/renderers/`2412. Recompile with NX, starting without `-c production`2423. Generate a matching sandbox2434. Run the relevant test-runner, E2E, or Storybook UI validation flow244245## Testing Expectations246247> [!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.249250- 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 modules252- 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 validation254- Use `yarn task e2e-tests --start-from auto` or `yarn task e2e-tests-dev --start-from auto` for E2E coverage255- Use `yarn task test-runner --start-from auto` or `yarn task test-runner-dev --start-from auto` for test-runner scenarios256- Use `yarn task smoke-test --start-from auto` for smoke checks257258Watch-mode commands:259260```bash261yarn test:watch262yarn storybook:vitest263```264265When writing tests for components:266267- 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 assertions270271When writing unit tests (utilities, hooks, non-React modules):272273- Export functions that need direct tests274- Test real behavior, not just syntax patterns275- Use coverage when useful: `yarn vitest run --coverage <test-file>`276- Mock external dependencies like file system access and loggers277- Use Node's path.resolve to wrap expected FS paths when writing path-related tests, so they work on Windows278279### Filesystem tests with `memfs`280281For 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:282283- 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 spies285- 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 helpful287288Do **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.289290### Globals in tests: never assign `globalThis.*` directly291292> [!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.294295Use Vitest's global stubbing instead, which is tracked and restorable:296297- 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.301302This applies to all ambient globals, not just `FEATURES` (e.g. `window`, `document`, `navigator`, `fetch`, `IS_REACT_ACT_ENVIRONMENT`).303304## Quality and Logging305306After changing files:3073081. **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 PR311312Use Storybook loggers instead of raw `console.*` in normal code paths:313314- Server-side: `storybook/internal/node-logger`315- Client-side: `storybook/internal/client-logger`316317For 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.318319The 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.320321Avoid `console.log`, `console.warn`, and `console.error` unless the file is isolated enough that importing the logger is not reasonable.322323## Troubleshooting324325- Build failures are often fixed by rerunning `yarn` and `yarn nx run-many -t compile`326- Storybook UI uses port `6006` by default327- Large compiles may require more Node.js memory328- Sandbox paths are `../storybook-sandboxes/`, not `./sandbox` or `code/sandbox/`329- Use `--debug` for verbose CLI output330- Check generated sandbox directories and `.cache/` for build artifacts331332## Environment Variables333334| 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 |342343## Commands To Avoid344345- **DO NOT RUN** `yarn task dev` without an explicit sandbox template346- **DO NOT RUN** `yarn start`347348These usually start long-running development servers and are the wrong default for agents.349350## Code Authoring Principles351352These are recurring failure modes in agent-authored changes to this repo. Apply them when writing or reviewing code, not just when asked.353354- **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.362363## Maintenance Rules For Agents364365- Use this file as the canonical instruction source366- Update `AGENTS.md` when architecture, commands, versions, release flows, or contributor guidance changes367- Keep `CLAUDE.md` and other agent entrypoints as thin references to `AGENTS.md`368- Do not reintroduce duplicated instruction files when a reference will do369
Also in storybookjs/storybook
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| storybookjs/storybook.cursor/rules/cursor-cloud.mdc · 91k | Cursor rules | setupagent-behaviour | 56/100 | today | |
| storybookjs/storybook.cursor/rules/spy-mocking.mdc · 91k | Cursor rules | teststyletesting-strategydo-not | 59/100 | 3 days ago | |
| storybookjs/storybook.cursorrules · 91k | .cursorrules | teststylearchdo-not+1 | 78/100 | 3 days ago |
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199k | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| aaif-goose/gooseAGENTS.md · 52k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 3 days ago | |
| wpscanteam/wpscanAGENTS.md · 9.7k | AGENTS.md | setupbuildteststyle+6 | 100/100 | 2 days ago | |
| mui/material-uiAGENTS.md · 99k | AGENTS.md | setupbuildtestlint-format+9 | 100/100 | 3 days ago | |
| SkeneTechnologies/skene-cookbookAGENTS.md · 51 | AGENTS.md | setupbuildtestlint-format+7 | 100/100 | 2 days ago | |
| duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70 | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| trick77/agents-md-syncAGENTS.md · 2 | AGENTS.md | setupbuildteststyle+5 | 100/100 | 3 days ago | |
| TryGhost/Ghoste2e/AGENTS.md · 55k | AGENTS.md | setupteststylearch+2 | 100/100 | 3 days ago |
