claude/ai-resources-plugin/skills/react-scan/SKILL.md
This skill should be used when the user asks to "set up react-scan", "install react-scan", "diagnose React re-renders", "find unnecessary renders", "find unstable props", "automate React render checks with Playwright", "react-scan + playwright", "measure component renders programmatically", "check why a React component is slow", or mentions React rendering issues, slow React interactions, render counts, or component-level perf attribution. Covers install across Next.js/Vite/Remix/script-tag/browser-extension, the lite headless API for CI, and the canonical render-attribution → fix → validate loop driven through Playwright.
npx skillsauth add amhuppert/my-ai-resources react-scanInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
react-scan instruments React's fiber tree via the same DevTools hook React DevTools uses, observing every commit without any application code change. It reports which component rendered, how long it took, and what changed (props / state / context / hooks / parent cascade). Pair it with Playwright and the result is a deterministic, file:line-attributable workflow for re-render bugs that traces alone cannot resolve.
This skill is the entry point. Detailed setup, integration patterns, API surface, diagnosis classification, and fix recipes live in references/ and load only when needed.
Use react-scan when the symptom points at component-level rendering, not asset delivery or paint:
<Results>")Do not use react-scan as the first move for: LCP regressions, network/bundle issues, layout shift, third-party scripts. Those belong in investigate-web-perf (sibling skill in this plugin). Trace-level analysis with the chrome-devtools-mcp Performance Insights complements react-scan: investigate-web-perf is canonical for trace work, react-scan is canonical for render-count attribution.
| Mode | When | How |
|---|---|---|
| Toolbar overlay (default) | Local dev, human-driven visual debugging | npx react-scan@latest init, or CLI proxy, or script tag |
| Lite (react-scan/lite) | Programmatic data collection, CI, agent-driven analysis | instrument({ onEvent }) or instrument({ endpoint }) |
| CLI proxy (npx react-scan@latest URL) | Quick check of any running app without touching its code | npx react-scan@latest http://localhost:3000 |
| Browser extension | Audit a deployed app you do not control | Install for Chrome/Firefox, click icon |
| Playwright + injection | Headless render counting in tests | Inject auto.global.js + patch onRender (see references/playwright-integration.md) |
For agent-driven workflows the order of preference is:
LiteEvent records).window.__REACT_SCAN__.ReactScanInternals is present.onRender(fiber, renders) callback, lite subscribe() events, or Store.reportData per-fiber map. Save raw payload to disk; do not stream to model context.changeDescription (props / state / context / hooks / parent). Cross-reference with source to find the unstable reference. Categories in references/diagnosis-patterns.md.references/fix-recipes.md). Do not bulk-add React.memo.dangerouslyForceRunInProduction: true is set. In Playwright against a dev server this works automatically; against any other build, set the flag or you will measure nothing and conclude wrongly. "Production build" here means React's production build as detected by bippy's detectReactBuildType — not "minified component names." A dev-mode React build can still emit minified single-letter names (e.g., Next.js + Turbopack); counters will work, names will just be unhelpful. If counters stay at zero, suspect prod React; if counters populate but names are _/r/i, you have a minified dev build — fix names via @react-scan/vite-plugin-react-scan autoDisplayNames: true (Vite) or babel-plugin-react-display-name (others) rather than reaching for the prod flag.React.memo without a measured render count first. Memoization has a non-zero cost; on components that render in <0.1 ms it's net negative. Always measure before and after.react-scan/lite for programmatic capture, not the full bundle. Lite has no overlay, no Preact, no toolbar — bundle and runtime overhead are minimal.LiteEvent arrays into the model context.react-scan/lite keepalive POSTs cap at ~64 KB. If using the endpoint option for large trees, tune maxFibersPerCommit (default 5000) downward or use in-process subscribe() instead.references/setup.mdreferences/playwright-integration.md + scripts/playwright-render-collector.tswindow?" → references/api-surface.mdreferences/diagnosis-patterns.md (load references/api-surface.md first if you don't yet have a render payload)references/fix-recipes.mdreferences/workflow.mdonRender output during JSX render. The callback fires on every commit; logging on every fire pollutes the console and skews measurements via console overhead. Buffer, then flush after the interaction completes.onRender calls per component. A single commit can produce one Render[] array with multiple entries — count the array length, not the callback invocations.react-scan in a Playwright test. The overlay attempts to mount Shadow DOM + Preact, which adds noise to render counts and slows tests. Use react-scan/lite or full bundle with showToolbar: false.Load on demand:
references/setup.md — Install per framework (Next.js App + Pages, Vite, Remix, script tag, CLI init, Vite plugin, browser extension, lite mode); environment guards and dev/prod gating.references/playwright-integration.md — addInitScript injection, the render-counter pattern from react-scan's own E2E suite, lite-mode subscriber, multi-page metrics aggregation, CI gating with budgets, when to disable StrictMode for measurement.references/api-surface.md — window.__REACT_SCAN__, ReactScanInternals, Store.reportData, onRender(fiber, renders) shape, Render / ChangeDescription types, the lite LiteEvent taxonomy and LiteOptions.references/diagnosis-patterns.md — Classification of root causes from changeDescription: unstable props, context over-scope, cascade from parent, memo bypass, hook dependency unstable, store selector instability, child-of-list-without-key.references/fix-recipes.md — Minimal-diff fixes per category: useMemo / useCallback placement, React.memo with custom equality, context split, selector with shallow, useDeferredValue / useTransition, list virtualization, key stabilization, lifting state down.references/workflow.md — End-to-end loop with prompts: reproduce → instrument → capture → classify → fix → validate, plus the slow-interaction (>150 ms long-render frame) and INP-driven variants.scripts/inject-react-scan.js — Playwright addInitScript-compatible helper that loads auto.global.js and disables the overlay for headless measurement.scripts/playwright-render-collector.ts — Example Playwright test that drives an interaction, collects per-component render counts via the lite subscriber, and writes a JSON report to disk for diff comparison.tools
Use when picking or vetting a keyboard shortcut on macOS. Triggers include "what hotkey should I use for X", "is `<combo>` available", "does this shortcut conflict", "recommend a keybinding for…", "check `<combo>` against my setup", "pick a hotkey for…", or any mention of choosing/binding/changing a shortcut in WezTerm, tmux, Zed, Chrome, Claude Code, or macOS. Determines whether a proposed combo collides with OS-reserved bindings, app defaults, or the user's customizations, and recommends ergonomic alternatives when needed.
development
Detect and remove dead code with knip. Use when the user asks to "run knip", "find unused files", "find unused exports", "find unused dependencies", "clean up dead code", "remove dead code", "set up knip", "configure knip", "knip.json", "knip false positive", "knip CI", or mentions a `knip` config, dependency bloat, bundle bloat from unused imports, or tree-shaking unused exports. Covers the configuration-first workflow, confidence-gated deletion, framework-specific gotchas (Next.js 15+, Tailwind, Storybook, Jest, Bun's test runner and `bun build --compile`), monorepos, CI integration, and performance tuning.
documentation
This skill should be used when integrating source material into a knowledge base, including when the user asks to "integrate this document into the knowledge base", "add this transcript to the memory bank", "ingest this document", "update the knowledge base", "analyze a new source document", or "sync current-state docs with this source".
tools
--- name: kb-ingest description: Delegate knowledge-base ingestion to the `knowledge-base-ingester` sub-agent so the source document, primary/current trees, and ingest workflow stay out of the main conversation's context window. Run this when the user explicitly invokes `/ai-resources:kb-ingest`; do not auto-trigger from natural-language ingestion requests (those should use the `knowledge-base-ingest` skill directly). disable-agent disable-model-invocation: true --- # kb-ingest Run a knowledge