{"owner":"aidenybai","repo":"react-grab","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"## General Rules\n\n- MUST: Use @antfu/ni. Use `ni` to install, `nr SCRIPT_NAME` to run. `nun` to uninstall.\n- MUST: Use TypeScript interfaces over types.\n- MUST: Keep all types in the global scope.\n- MUST: Use arrow functions over function declarations\n- MUST: Default to NO comments. Only add a comment when the user explicitly asks, or when the \"why\" is truly non-obvious - browser quirks, platform bugs, performance tradeoffs, fragile internal patching, or counter-intuitive design decisions. Never add comments that restate what the code does or what a well-named function/variable already conveys. When in doubt, leave the comment out.\n  - Do not delete descriptive comments >3 lines without confirming with the user\n- MUST: Use kebab-case for files\n- MUST: Use descriptive names for variables (avoid shorthands, or 1-2 character names).\n  - Example: for .map(), you can use `innerX` instead of `x`\n  - Example: instead of `moved` use `didPositionChange`\n- MUST: Frequently re-evaluate and refactor variable names to be more accurate and descriptive.\n- MUST: Do not type cast (\"as\") unless absolutely necessary\n- MUST: Remove unused code and don't repeat yourself.\n- MUST: Always search the codebase, think of many solutions, then implement the most _elegant_ solution.\n- MUST: Put all magic numbers in `constants.ts` using `SCREAMING_SNAKE_CASE` with unit suffixes (`_MS`, `_PX`).\n- MUST: Put small, focused utility functions in `utils/` with one utility per file.\n- MUST: Use Boolean over !!.\n- MUST: No dynamic imports (`import()`) unless strictly necessary (e.g. code-splitting a large optional dependency, breaking a circular dependency that cannot be refactored). Prefer static `import` at the top of the file.\n\n## V8 Hot-Path Rules\n\nFor hot per-frame paths (pointer/scroll handlers, animation ticks, fiber walks):\n\n- MUST: Keep indirect call sites monomorphic. Do not pass different callbacks to a shared recursor/iterator that gets hot - split into one specialized helper per callback, or inline the loop.\n- MUST: Mutate object fields in place instead of replacing the field with a fresh object literal. `obj.target.x = ...` not `obj.target = { x, y, ... }`. Allocating per-frame literals churns the GC and cycles hidden classes.\n- MUST: Keep numeric helpers in a single number-type \"lane\". A function that early-returns a Smi (`return 8`) and otherwise returns a double (`labelWidth * 0.2`) will deopt every consumer with `not a Smi`. Pick one (e.g. `Math.round` the double).\n- SHOULD: Prefer closed-form arithmetic over loops that subtract/add a constant until a delta is in range (e.g. angle normalization with `Math.round(delta / 360)`, not `while delta > 180`).\n\n## SolidJS Rules\n\n### Mental Model\n\n- MUST: Treat components as setup functions that run ONCE, not render functions.\n- MUST: Place reactive work in primitives (`createMemo`, `createEffect`, `<Show>`, `<For>`), not component body.\n- MUST: Access signals only inside reactive contexts (JSX expressions, effects, memos).\n\n### Reactivity\n\n- MUST: Call signals as functions: `count()` not `count`.\n- MUST: Use functional updates when new state depends on old: `setCount((prev) => prev + 1)`.\n- MUST: Keep signals atomic (one per value) - one big state object loses granularity.\n- MUST: Use derived functions `() => count() * 2` for cheap/infrequent derivations.\n- MUST: Use `createMemo(() => ...)` for expensive/frequent derivations - caches result.\n- MUST: Use `createEffect` for side effects only (DOM, localStorage, subscriptions).\n- MUST: Call `onCleanup(() => ...)` inside effects for subscriptions/intervals/listeners.\n- MUST: Use path syntax for store updates: `setStore(\"users\", 0, \"name\", \"Jane\")`.\n- MUST: Wrap store props in arrow for `on()`: `on(() => store.value, fn)` not `on(store.value, fn)`.\n- SHOULD: Use `{ equals: false }` for trigger signals that always notify.\n- SHOULD: Use `batch(() => { ... })` when updating multiple signals outside event handlers.\n- SHOULD: Use `on(dep, fn)` for explicit effect dependencies.\n- SHOULD: Use `untrack(() => value())` to read without subscribing.\n- SHOULD: Use `createStore({ ... })` for nested objects with fine-grained reactivity.\n- SHOULD: Use `produce(draft => { ... })` for complex store mutations.\n- NEVER: Derive state via `createEffect(() => setX(y()))` - use memo or derived function.\n- NEVER: Place side effects inside `createMemo` - causes infinite loops/crashes.\n\n### Effect Taxonomy\n\nBefore writing `createEffect`, classify the work and pick the right primitive:\n\n- MUST: Use `createMemo` when the result is pure derived state from other signals/stores. If no external system is touched, it is not an effect.\n- MUST: Use event handlers and direct action calls when work happens because a user clicked, selected, or navigated. Do not watch a flag/token in an effect to trigger imperative logic.\n- MUST: Use `onMount`/`onCleanup` for one-time lifecycle setup and teardown (subscriptions, timers, imperative DOM wiring) that should not rerun for reactive changes.\n- MUST: Keep `createEffect` single-purpose - one effect, one external bridge. Split mixed-responsibility effects.\n- SHOULD: Use keyed ownership boundaries (keyed `<Show>`/`<For>`, or keyed `createRoot`) when local state should reset because an identity changed. Do not write a \"watch key, clear state\" effect.\n- SHOULD: Normalize state at the write boundary, not via a repair effect that rewrites after the fact.\n- NEVER: Use `createEffect` just to copy one store/signal into another - find the single source of truth.\n- NEVER: Use `createEffect` as an event bus (watching a trigger signal to run a command). Call the action directly from the event source.\n\n### Props\n\n- MUST: Access props via `props.title`, not destructuring.\n- SHOULD: Wrap in getter if needed: `const title = () => props.title`.\n- SHOULD: Use `splitProps(props, [\"keys\"])` to separate local from pass-through props.\n- SHOULD: Use `mergeProps(defaults, props)` for default values.\n- SHOULD: Use `children(() => props.children)` only when transforming, otherwise `{props.children}`.\n- NEVER: Destructure props `({ title })` - breaks reactivity.\n\n### Control Flow\n\n- MUST: Use `<For each={items()}>` for object arrays - item is value, index is signal.\n- MUST: Use `<Index each={items()}>` for primitives/inputs - item is signal, index is number.\n- MUST: Use `<Suspense fallback={...}>` for async, not `<Show when={!loading}>`.\n- MUST: Access resource states via `data()`, `data.loading`, `data.error`, `data.latest`.\n- SHOULD: Use `<Show when={cond()} fallback={...}>` for conditionals.\n- SHOULD: Use `<Show when={val}>` callback for type narrowing: `{(v) => <div>{v().name}</div>}`.\n- SHOULD: Use `<Switch>/<Match>` for multiple conditions.\n- SHOULD: Use `createResource(source, fetcher)` for reactive async data.\n- SHOULD: Use `<ErrorBoundary fallback={(err, reset) => ...}>` for render errors.\n- NEVER: Use `.map()` in JSX - use `<For>` or `<Index>`.\n- NEVER: Rely on ErrorBoundary for event handler or setTimeout errors - use try/catch.\n\n### JSX & DOM\n\n- MUST: Use `class` not `className`.\n- MUST: Combine static `class=\"btn\"` with reactive `classList={{ active: isActive() }}`.\n- MUST: Use `onClick` for delegated events; `on:click` for native (element-level).\n- MUST: Condition inside handler since events are not reactive: `onClick={() => props.onClick?.()}`.\n- MUST: Read refs in `onMount` or effects - refs connect after render.\n- MUST: Call `onCleanup` inside directives for cleanup.\n- SHOULD: Use `on:click` for `stopPropagation`, capture, passive, or custom events.\n- SHOULD: Use `style={{ color: color(), \"--css-var\": value() }}` for inline styles.\n- SHOULD: Use the native `textContent` prop for dynamic content that is guaranteed to be text-only.\n- SHOULD: Type refs as `let el: HTMLElement | undefined` with guard.\n- SHOULD: Use `use:directiveName={accessor}` for reusable DOM behaviors.\n- NEVER: Mix reactive `class={x()}` with `classList`.\n\n## Testing\n\nRun dev `packages/cli` with:\n\n```bash\nnpm_command=exec node packages/cli/dist/cli.js\n```\n\nRun checks always before committing with:\n\n```bash\npnpm test # runs e2e tests\npnpm lint\npnpm typecheck # runs type checking\npnpm format\n```\n\n## Development instructions\n\nThis is a pnpm monorepo with `apps/` (playgrounds, sites, extensions) and `packages/` (libraries, tools). No external services (databases, Docker, etc.) are required.\n\n### Build before test\n\n`pnpm build` must complete before `pnpm test` or `pnpm lint`. After modifying source files, always rebuild before running tests.\n\n### Approved build scripts\n\nThe root `package.json` has `pnpm.onlyBuiltDependencies` configured for `@parcel/watcher`, `esbuild`, `sharp`, `spawn-sync`, and `unrs-resolver`. Without this, `pnpm install` silently skips their native builds and downstream packages may fail.\n\n### Playwright\n\nE2E tests use a Vite Plus kitchen-sink fixture and a shared framework contract across stock Vite, Next.js, and TanStack Start in development and production. Set `E2E_ENVIRONMENT` to run one environment and start only its server: `vite-plus-development`, `vite-plus-production`, `vite-upstream-development`, `vite-upstream-production`, `next-development`, `next-production`, `tanstack-development`, or `tanstack-production`. Chromium must be installed: `npx --prefix packages/react-grab playwright install chromium --with-deps`.\n\n### Key commands reference\n\nSee root `package.json` scripts and `CONTRIBUTING.md` for the full list. Quick reference:\n\n- **Install**: `ni` (or `pnpm install`)\n- **Build**: `nr build` (or `pnpm build`)\n- **Dev watch**: `nr dev` (or `pnpm dev`) - watches core packages\n- **Test**: `pnpm test` - runs Playwright E2E + Vitest CLI tests\n- **Lint**: `pnpm lint` - oxlint on react-grab package\n- **Typecheck**: `pnpm typecheck` - tsc on react-grab package\n- **Format**: `pnpm format` - oxfmt\n- **CLI dev**: `npm_command=exec node packages/cli/dist/cli.js`\n- **Test app (Vite Plus)**: `pnpm --filter @react-grab/e2e-app-vite dev` (port 5175, lives in `apps/e2e-app-vite`)\n- **Test app (stock Vite)**: `pnpm --filter @react-grab/e2e-app-vite-upstream dev` (port 5181, lives in `apps/e2e-app-vite-upstream`)\n- **Test app (Next)**: `pnpm --filter @react-grab/e2e-app-next dev` (port 5176, lives in `apps/e2e-app-next`)\n- **Test app (TanStack Start)**: `pnpm --filter @react-grab/e2e-app-tanstack-start dev` (port 5178, lives in `apps/e2e-app-tanstack-start`)\n"},"files":{"AGENTS.md":"## General Rules\n\n- MUST: Use @antfu/ni. Use `ni` to install, `nr SCRIPT_NAME` to run. `nun` to uninstall.\n- MUST: Use TypeScript interfaces over types.\n- MUST: Keep all types in the global scope.\n- MUST: Use arrow functions over function declarations\n- MUST: Default to NO comments. Only add a comment when the user explicitly asks, or when the \"why\" is truly non-obvious - browser quirks, platform bugs, performance tradeoffs, fragile internal patching, or counter-intuitive design decisions. Never add comments that restate what the code does or what a well-named function/variable already conveys. When in doubt, leave the comment out.\n  - Do not delete descriptive comments >3 lines without confirming with the user\n- MUST: Use kebab-case for files\n- MUST: Use descriptive names for variables (avoid shorthands, or 1-2 character names).\n  - Example: for .map(), you can use `innerX` instead of `x`\n  - Example: instead of `moved` use `didPositionChange`\n- MUST: Frequently re-evaluate and refactor variable names to be more accurate and descriptive.\n- MUST: Do not type cast (\"as\") unless absolutely necessary\n- MUST: Remove unused code and don't repeat yourself.\n- MUST: Always search the codebase, think of many solutions, then implement the most _elegant_ solution.\n- MUST: Put all magic numbers in `constants.ts` using `SCREAMING_SNAKE_CASE` with unit suffixes (`_MS`, `_PX`).\n- MUST: Put small, focused utility functions in `utils/` with one utility per file.\n- MUST: Use Boolean over !!.\n- MUST: No dynamic imports (`import()`) unless strictly necessary (e.g. code-splitting a large optional dependency, breaking a circular dependency that cannot be refactored). Prefer static `import` at the top of the file.\n\n## V8 Hot-Path Rules\n\nFor hot per-frame paths (pointer/scroll handlers, animation ticks, fiber walks):\n\n- MUST: Keep indirect call sites monomorphic. Do not pass different callbacks to a shared recursor/iterator that gets hot - split into one specialized helper per callback, or inline the loop.\n- MUST: Mutate object fields in place instead of replacing the field with a fresh object literal. `obj.target.x = ...` not `obj.target = { x, y, ... }`. Allocating per-frame literals churns the GC and cycles hidden classes.\n- MUST: Keep numeric helpers in a single number-type \"lane\". A function that early-returns a Smi (`return 8`) and otherwise returns a double (`labelWidth * 0.2`) will deopt every consumer with `not a Smi`. Pick one (e.g. `Math.round` the double).\n- SHOULD: Prefer closed-form arithmetic over loops that subtract/add a constant until a delta is in range (e.g. angle normalization with `Math.round(delta / 360)`, not `while delta > 180`).\n\n## SolidJS Rules\n\n### Mental Model\n\n- MUST: Treat components as setup functions that run ONCE, not render functions.\n- MUST: Place reactive work in primitives (`createMemo`, `createEffect`, `<Show>`, `<For>`), not component body.\n- MUST: Access signals only inside reactive contexts (JSX expressions, effects, memos).\n\n### Reactivity\n\n- MUST: Call signals as functions: `count()` not `count`.\n- MUST: Use functional updates when new state depends on old: `setCount((prev) => prev + 1)`.\n- MUST: Keep signals atomic (one per value) - one big state object loses granularity.\n- MUST: Use derived functions `() => count() * 2` for cheap/infrequent derivations.\n- MUST: Use `createMemo(() => ...)` for expensive/frequent derivations - caches result.\n- MUST: Use `createEffect` for side effects only (DOM, localStorage, subscriptions).\n- MUST: Call `onCleanup(() => ...)` inside effects for subscriptions/intervals/listeners.\n- MUST: Use path syntax for store updates: `setStore(\"users\", 0, \"name\", \"Jane\")`.\n- MUST: Wrap store props in arrow for `on()`: `on(() => store.value, fn)` not `on(store.value, fn)`.\n- SHOULD: Use `{ equals: false }` for trigger signals that always notify.\n- SHOULD: Use `batch(() => { ... })` when updating multiple signals outside event handlers.\n- SHOULD: Use `on(dep, fn)` for explicit effect dependencies.\n- SHOULD: Use `untrack(() => value())` to read without subscribing.\n- SHOULD: Use `createStore({ ... })` for nested objects with fine-grained reactivity.\n- SHOULD: Use `produce(draft => { ... })` for complex store mutations.\n- NEVER: Derive state via `createEffect(() => setX(y()))` - use memo or derived function.\n- NEVER: Place side effects inside `createMemo` - causes infinite loops/crashes.\n\n### Effect Taxonomy\n\nBefore writing `createEffect`, classify the work and pick the right primitive:\n\n- MUST: Use `createMemo` when the result is pure derived state from other signals/stores. If no external system is touched, it is not an effect.\n- MUST: Use event handlers and direct action calls when work happens because a user clicked, selected, or navigated. Do not watch a flag/token in an effect to trigger imperative logic.\n- MUST: Use `onMount`/`onCleanup` for one-time lifecycle setup and teardown (subscriptions, timers, imperative DOM wiring) that should not rerun for reactive changes.\n- MUST: Keep `createEffect` single-purpose - one effect, one external bridge. Split mixed-responsibility effects.\n- SHOULD: Use keyed ownership boundaries (keyed `<Show>`/`<For>`, or keyed `createRoot`) when local state should reset because an identity changed. Do not write a \"watch key, clear state\" effect.\n- SHOULD: Normalize state at the write boundary, not via a repair effect that rewrites after the fact.\n- NEVER: Use `createEffect` just to copy one store/signal into another - find the single source of truth.\n- NEVER: Use `createEffect` as an event bus (watching a trigger signal to run a command). Call the action directly from the event source.\n\n### Props\n\n- MUST: Access props via `props.title`, not destructuring.\n- SHOULD: Wrap in getter if needed: `const title = () => props.title`.\n- SHOULD: Use `splitProps(props, [\"keys\"])` to separate local from pass-through props.\n- SHOULD: Use `mergeProps(defaults, props)` for default values.\n- SHOULD: Use `children(() => props.children)` only when transforming, otherwise `{props.children}`.\n- NEVER: Destructure props `({ title })` - breaks reactivity.\n\n### Control Flow\n\n- MUST: Use `<For each={items()}>` for object arrays - item is value, index is signal.\n- MUST: Use `<Index each={items()}>` for primitives/inputs - item is signal, index is number.\n- MUST: Use `<Suspense fallback={...}>` for async, not `<Show when={!loading}>`.\n- MUST: Access resource states via `data()`, `data.loading`, `data.error`, `data.latest`.\n- SHOULD: Use `<Show when={cond()} fallback={...}>` for conditionals.\n- SHOULD: Use `<Show when={val}>` callback for type narrowing: `{(v) => <div>{v().name}</div>}`.\n- SHOULD: Use `<Switch>/<Match>` for multiple conditions.\n- SHOULD: Use `createResource(source, fetcher)` for reactive async data.\n- SHOULD: Use `<ErrorBoundary fallback={(err, reset) => ...}>` for render errors.\n- NEVER: Use `.map()` in JSX - use `<For>` or `<Index>`.\n- NEVER: Rely on ErrorBoundary for event handler or setTimeout errors - use try/catch.\n\n### JSX & DOM\n\n- MUST: Use `class` not `className`.\n- MUST: Combine static `class=\"btn\"` with reactive `classList={{ active: isActive() }}`.\n- MUST: Use `onClick` for delegated events; `on:click` for native (element-level).\n- MUST: Condition inside handler since events are not reactive: `onClick={() => props.onClick?.()}`.\n- MUST: Read refs in `onMount` or effects - refs connect after render.\n- MUST: Call `onCleanup` inside directives for cleanup.\n- SHOULD: Use `on:click` for `stopPropagation`, capture, passive, or custom events.\n- SHOULD: Use `style={{ color: color(), \"--css-var\": value() }}` for inline styles.\n- SHOULD: Use the native `textContent` prop for dynamic content that is guaranteed to be text-only.\n- SHOULD: Type refs as `let el: HTMLElement | undefined` with guard.\n- SHOULD: Use `use:directiveName={accessor}` for reusable DOM behaviors.\n- NEVER: Mix reactive `class={x()}` with `classList`.\n\n## Testing\n\nRun dev `packages/cli` with:\n\n```bash\nnpm_command=exec node packages/cli/dist/cli.js\n```\n\nRun checks always before committing with:\n\n```bash\npnpm test # runs e2e tests\npnpm lint\npnpm typecheck # runs type checking\npnpm format\n```\n\n## Development instructions\n\nThis is a pnpm monorepo with `apps/` (playgrounds, sites, extensions) and `packages/` (libraries, tools). No external services (databases, Docker, etc.) are required.\n\n### Build before test\n\n`pnpm build` must complete before `pnpm test` or `pnpm lint`. After modifying source files, always rebuild before running tests.\n\n### Approved build scripts\n\nThe root `package.json` has `pnpm.onlyBuiltDependencies` configured for `@parcel/watcher`, `esbuild`, `sharp`, `spawn-sync`, and `unrs-resolver`. Without this, `pnpm install` silently skips their native builds and downstream packages may fail.\n\n### Playwright\n\nE2E tests use a Vite Plus kitchen-sink fixture and a shared framework contract across stock Vite, Next.js, and TanStack Start in development and production. Set `E2E_ENVIRONMENT` to run one environment and start only its server: `vite-plus-development`, `vite-plus-production`, `vite-upstream-development`, `vite-upstream-production`, `next-development`, `next-production`, `tanstack-development`, or `tanstack-production`. Chromium must be installed: `npx --prefix packages/react-grab playwright install chromium --with-deps`.\n\n### Key commands reference\n\nSee root `package.json` scripts and `CONTRIBUTING.md` for the full list. Quick reference:\n\n- **Install**: `ni` (or `pnpm install`)\n- **Build**: `nr build` (or `pnpm build`)\n- **Dev watch**: `nr dev` (or `pnpm dev`) - watches core packages\n- **Test**: `pnpm test` - runs Playwright E2E + Vitest CLI tests\n- **Lint**: `pnpm lint` - oxlint on react-grab package\n- **Typecheck**: `pnpm typecheck` - tsc on react-grab package\n- **Format**: `pnpm format` - oxfmt\n- **CLI dev**: `npm_command=exec node packages/cli/dist/cli.js`\n- **Test app (Vite Plus)**: `pnpm --filter @react-grab/e2e-app-vite dev` (port 5175, lives in `apps/e2e-app-vite`)\n- **Test app (stock Vite)**: `pnpm --filter @react-grab/e2e-app-vite-upstream dev` (port 5181, lives in `apps/e2e-app-vite-upstream`)\n- **Test app (Next)**: `pnpm --filter @react-grab/e2e-app-next dev` (port 5176, lives in `apps/e2e-app-next`)\n- **Test app (TanStack Start)**: `pnpm --filter @react-grab/e2e-app-tanstack-start dev` (port 5178, lives in `apps/e2e-app-tanstack-start`)\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"## General Rules\n\n- MUST: Use @antfu/ni. Use `ni` to install, `nr SCRIPT_NAME` to run. `nun` to uninstall.\n- MUST: Use TypeScript interfaces over types.\n- MUST: Keep all types in the global scope.\n- MUST: Use arrow functions over function declarations\n- MUST: Default to NO comments. Only add a comment when the user explicitly asks, or when the \"why\" is truly non-obvious - browser quirks, platform bugs, performance tradeoffs, fragile internal patching, or counter-intuitive design decisions. Never add comments that restate what the code does or what a well-named function/variable already conveys. When in doubt, leave the comment out.\n  - Do not delete descriptive comments >3 lines without confirming with the user\n- MUST: Use kebab-case for files\n- MUST: Use descriptive names for variables (avoid shorthands, or 1-2 character names).\n  - Example: for .map(), you can use `innerX` instead of `x`\n  - Example: instead of `moved` use `didPositionChange`\n- MUST: Frequently re-evaluate and refactor variable names to be more accurate and descriptive.\n- MUST: Do not type cast (\"as\") unless absolutely necessary\n- MUST: Remove unused code and don't repeat yourself.\n- MUST: Always search the codebase, think of many solutions, then implement the most _elegant_ solution.\n- MUST: Put all magic numbers in `constants.ts` using `SCREAMING_SNAKE_CASE` with unit suffixes (`_MS`, `_PX`).\n- MUST: Put small, focused utility functions in `utils/` with one utility per file.\n- MUST: Use Boolean over !!.\n- MUST: No dynamic imports (`import()`) unless strictly necessary (e.g. code-splitting a large optional dependency, breaking a circular dependency that cannot be refactored). Prefer static `import` at the top of the file.\n\n## V8 Hot-Path Rules\n\nFor hot per-frame paths (pointer/scroll handlers, animation ticks, fiber walks):\n\n- MUST: Keep indirect call sites monomorphic. Do not pass different callbacks to a shared recursor/iterator that gets hot - split into one specialized helper per callback, or inline the loop.\n- MUST: Mutate object fields in place instead of replacing the field with a fresh object literal. `obj.target.x = ...` not `obj.target = { x, y, ... }`. Allocating per-frame literals churns the GC and cycles hidden classes.\n- MUST: Keep numeric helpers in a single number-type \"lane\". A function that early-returns a Smi (`return 8`) and otherwise returns a double (`labelWidth * 0.2`) will deopt every consumer with `not a Smi`. Pick one (e.g. `Math.round` the double).\n- SHOULD: Prefer closed-form arithmetic over loops that subtract/add a constant until a delta is in range (e.g. angle normalization with `Math.round(delta / 360)`, not `while delta > 180`).\n\n## SolidJS Rules\n\n### Mental Model\n\n- MUST: Treat components as setup functions that run ONCE, not render functions.\n- MUST: Place reactive work in primitives (`createMemo`, `createEffect`, `<Show>`, `<For>`), not component body.\n- MUST: Access signals only inside reactive contexts (JSX expressions, effects, memos).\n\n### Reactivity\n\n- MUST: Call signals as functions: `count()` not `count`.\n- MUST: Use functional updates when new state depends on old: `setCount((prev) => prev + 1)`.\n- MUST: Keep signals atomic (one per value) - one big state object loses granularity.\n- MUST: Use derived functions `() => count() * 2` for cheap/infrequent derivations.\n- MUST: Use `createMemo(() => ...)` for expensive/frequent derivations - caches result.\n- MUST: Use `createEffect` for side effects only (DOM, localStorage, subscriptions).\n- MUST: Call `onCleanup(() => ...)` inside effects for subscriptions/intervals/listeners.\n- MUST: Use path syntax for store updates: `setStore(\"users\", 0, \"name\", \"Jane\")`.\n- MUST: Wrap store props in arrow for `on()`: `on(() => store.value, fn)` not `on(store.value, fn)`.\n- SHOULD: Use `{ equals: false }` for trigger signals that always notify.\n- SHOULD: Use `batch(() => { ... })` when updating multiple signals outside event handlers.\n- SHOULD: Use `on(dep, fn)` for explicit effect dependencies.\n- SHOULD: Use `untrack(() => value())` to read without subscribing.\n- SHOULD: Use `createStore({ ... })` for nested objects with fine-grained reactivity.\n- SHOULD: Use `produce(draft => { ... })` for complex store mutations.\n- NEVER: Derive state via `createEffect(() => setX(y()))` - use memo or derived function.\n- NEVER: Place side effects inside `createMemo` - causes infinite loops/crashes.\n\n### Effect Taxonomy\n\nBefore writing `createEffect`, classify the work and pick the right primitive:\n\n- MUST: Use `createMemo` when the result is pure derived state from other signals/stores. If no external system is touched, it is not an effect.\n- MUST: Use event handlers and direct action calls when work happens because a user clicked, selected, or navigated. Do not watch a flag/token in an effect to trigger imperative logic.\n- MUST: Use `onMount`/`onCleanup` for one-time lifecycle setup and teardown (subscriptions, timers, imperative DOM wiring) that should not rerun for reactive changes.\n- MUST: Keep `createEffect` single-purpose - one effect, one external bridge. Split mixed-responsibility effects.\n- SHOULD: Use keyed ownership boundaries (keyed `<Show>`/`<For>`, or keyed `createRoot`) when local state should reset because an identity changed. Do not write a \"watch key, clear state\" effect.\n- SHOULD: Normalize state at the write boundary, not via a repair effect that rewrites after the fact.\n- NEVER: Use `createEffect` just to copy one store/signal into another - find the single source of truth.\n- NEVER: Use `createEffect` as an event bus (watching a trigger signal to run a command). Call the action directly from the event source.\n\n### Props\n\n- MUST: Access props via `props.title`, not destructuring.\n- SHOULD: Wrap in getter if needed: `const title = () => props.title`.\n- SHOULD: Use `splitProps(props, [\"keys\"])` to separate local from pass-through props.\n- SHOULD: Use `mergeProps(defaults, props)` for default values.\n- SHOULD: Use `children(() => props.children)` only when transforming, otherwise `{props.children}`.\n- NEVER: Destructure props `({ title })` - breaks reactivity.\n\n### Control Flow\n\n- MUST: Use `<For each={items()}>` for object arrays - item is value, index is signal.\n- MUST: Use `<Index each={items()}>` for primitives/inputs - item is signal, index is number.\n- MUST: Use `<Suspense fallback={...}>` for async, not `<Show when={!loading}>`.\n- MUST: Access resource states via `data()`, `data.loading`, `data.error`, `data.latest`.\n- SHOULD: Use `<Show when={cond()} fallback={...}>` for conditionals.\n- SHOULD: Use `<Show when={val}>` callback for type narrowing: `{(v) => <div>{v().name}</div>}`.\n- SHOULD: Use `<Switch>/<Match>` for multiple conditions.\n- SHOULD: Use `createResource(source, fetcher)` for reactive async data.\n- SHOULD: Use `<ErrorBoundary fallback={(err, reset) => ...}>` for render errors.\n- NEVER: Use `.map()` in JSX - use `<For>` or `<Index>`.\n- NEVER: Rely on ErrorBoundary for event handler or setTimeout errors - use try/catch.\n\n### JSX & DOM\n\n- MUST: Use `class` not `className`.\n- MUST: Combine static `class=\"btn\"` with reactive `classList={{ active: isActive() }}`.\n- MUST: Use `onClick` for delegated events; `on:click` for native (element-level).\n- MUST: Condition inside handler since events are not reactive: `onClick={() => props.onClick?.()}`.\n- MUST: Read refs in `onMount` or effects - refs connect after render.\n- MUST: Call `onCleanup` inside directives for cleanup.\n- SHOULD: Use `on:click` for `stopPropagation`, capture, passive, or custom events.\n- SHOULD: Use `style={{ color: color(), \"--css-var\": value() }}` for inline styles.\n- SHOULD: Use the native `textContent` prop for dynamic content that is guaranteed to be text-only.\n- SHOULD: Type refs as `let el: HTMLElement | undefined` with guard.\n- SHOULD: Use `use:directiveName={accessor}` for reusable DOM behaviors.\n- NEVER: Mix reactive `class={x()}` with `classList`.\n\n## Testing\n\nRun dev `packages/cli` with:\n\n```bash\nnpm_command=exec node packages/cli/dist/cli.js\n```\n\nRun checks always before committing with:\n\n```bash\npnpm test # runs e2e tests\npnpm lint\npnpm typecheck # runs type checking\npnpm format\n```\n\n## Development instructions\n\nThis is a pnpm monorepo with `apps/` (playgrounds, sites, extensions) and `packages/` (libraries, tools). No external services (databases, Docker, etc.) are required.\n\n### Build before test\n\n`pnpm build` must complete before `pnpm test` or `pnpm lint`. After modifying source files, always rebuild before running tests.\n\n### Approved build scripts\n\nThe root `package.json` has `pnpm.onlyBuiltDependencies` configured for `@parcel/watcher`, `esbuild`, `sharp`, `spawn-sync`, and `unrs-resolver`. Without this, `pnpm install` silently skips their native builds and downstream packages may fail.\n\n### Playwright\n\nE2E tests use a Vite Plus kitchen-sink fixture and a shared framework contract across stock Vite, Next.js, and TanStack Start in development and production. Set `E2E_ENVIRONMENT` to run one environment and start only its server: `vite-plus-development`, `vite-plus-production`, `vite-upstream-development`, `vite-upstream-production`, `next-development`, `next-production`, `tanstack-development`, or `tanstack-production`. Chromium must be installed: `npx --prefix packages/react-grab playwright install chromium --with-deps`.\n\n### Key commands reference\n\nSee root `package.json` scripts and `CONTRIBUTING.md` for the full list. Quick reference:\n\n- **Install**: `ni` (or `pnpm install`)\n- **Build**: `nr build` (or `pnpm build`)\n- **Dev watch**: `nr dev` (or `pnpm dev`) - watches core packages\n- **Test**: `pnpm test` - runs Playwright E2E + Vitest CLI tests\n- **Lint**: `pnpm lint` - oxlint on react-grab package\n- **Typecheck**: `pnpm typecheck` - tsc on react-grab package\n- **Format**: `pnpm format` - oxfmt\n- **CLI dev**: `npm_command=exec node packages/cli/dist/cli.js`\n- **Test app (Vite Plus)**: `pnpm --filter @react-grab/e2e-app-vite dev` (port 5175, lives in `apps/e2e-app-vite`)\n- **Test app (stock Vite)**: `pnpm --filter @react-grab/e2e-app-vite-upstream dev` (port 5181, lives in `apps/e2e-app-vite-upstream`)\n- **Test app (Next)**: `pnpm --filter @react-grab/e2e-app-next dev` (port 5176, lives in `apps/e2e-app-next`)\n- **Test app (TanStack Start)**: `pnpm --filter @react-grab/e2e-app-tanstack-start dev` (port 5178, lives in `apps/e2e-app-tanstack-start`)\n","category":"root","tokens":2598}]}