React Doctor: an agent-facing linter for React codebases
Your agent writes bad React. This catches it
At a glance
- What is it?
- React Doctor is a deterministic scanner that reports React issues across state and effects, performance, architecture, security, accessibility and maintainability, and can install itself as a skill for coding agents. The interesting part is not the rule list, it is the split between what a human reads and what an agent consumes.
- Who is it for?
- Adopt React Doctor if your team already runs coding agents against a React codebase and wants a deterministic pass that catches state, effect, performance and accessibility problems before review, and if you are willing to run a first audit and then decide which rules to keep. Skip it if you need a single linter to replace your existing ESLint setup, or if you cannot accept a CLI that reports anonymous usage counters to Sentry by default.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem React Doctor targets: agents writing React faster than review can absorb
The README opens with a blunt claim: "Your agent writes bad React, this catches it." That sentence defines the audience more precisely than any feature list. The tool is aimed at teams where a coding agent produces React components at a rate that human review cannot match, and where the reviewer's attention is spent on the same recurring mistakes instead of on the parts of the diff that need judgement.
The scanner is deterministic, which matters here. An agent that generates code and an agent that reviews the same code share failure modes. A rule engine does not. React Doctor reports issues in six named categories: state and effects, performance, architecture, security, accessibility, and maintainability. It also flags overly complex React functions and repeated JSX trees as candidates for composition, which is the kind of structural observation that is tedious to make by hand and easy to make mechanically.
Framework coverage is deliberately wide. The README lists Next.js, Vite, Astro, TanStack, React Native and Expo, and says it works across React frameworks and React-enabled sites generally. That breadth is a design commitment: rules cannot assume Next.js routing or a specific bundler. The cost of that choice shows up in what the tool can say about framework-specific behaviour, which is less than a framework-tied tool could say.
How the scan works: rules, config files and the agent skill
The repository is a pnpm workspace with `packages/`, `skills/`, `docs/` and `action.yml` at the top level. The published artifacts visible in the release list are `react-doctor`, `oxlint-plugin-react-doctor` and `eslint-plugin-react-doctor`, all at version 0.9.14. That naming is the clearest architectural signal available: the rule implementations live in plugins that target oxlint and ESLint, and the `react-doctor` package wraps them into a CLI with its own reporting, CI integration and agent-facing output formats.
Rule selection and behaviour are configured in a `doctor.config.ts` file, which the README points to under configuration docs. The README does not reproduce the schema, so the exact keys are not something to guess at. What is documented is that the config controls which rules run and how they run.
The agent side is a separate install step. After an audit, `npx react-doctor@latest install` installs a skill that a coding agent can read, so the agent learns from the issues found in your codebase and applies that knowledge later. The README names Claude Code, Cursor, Codex and OpenCode as supported, and says it works with many more. The repository also carries `.claude`, `.cursor-plugin/`, `AGENTS.md` and `CLAUDE.md` at the top level, which is consistent with a project that ships agent configuration as part of its own development workflow.
Output formats matter for the agent path. The scan command accepts `--format json` or `--format jsonl`, described as being for coding agents. A JSONL stream is a reasonable fit for an agent that wants to process findings incrementally rather than parse one large document.
Installing React Doctor and running a first audit
There is no global install step. The README's quick start runs the package through npx at the project root, which means the first thing you should check is that your Node and package manager setup can execute it without a lockfile conflict.
Run this at your project root to get an audit:
npx react-doctor@latestYou should see a report of issues grouped by the categories the README lists. If you want to scope the run, the README shows passing file paths so that another CI step can decide what to scan:
npx react-doctor@latest src/a.tsx src/b.tsxOnce you have read the audit, install the skill so your coding agent can act on the same findings in future work:
npx react-doctor@latest installCI setup is a single command that adds a workflow, scans pull requests and posts a summary comment:
npx react-doctor@latest ci installThe README states that CI reviews report only the issues a change introduced, not the existing backlog. That scoping decision is what makes the gate usable on a codebase with pre-existing findings. Two follow-up commands are documented: `react-doctor ci config` changes the gate, scan scope and comment behaviour, and `react-doctor ci upgrade` bumps the action version. GitHub Actions is fully supported; GitLab CI gets what the README calls a gate-only scaffold.
Runtime traces with react-doctor scan, and what leaves your machine
Static rules cannot see render behaviour. The `scan` subcommand addresses that by recording a Chrome DevTools performance trace while you interact with a running app:
npx react-doctor@latest scan http://localhost:3000The documented behaviour is specific. React Doctor opens system Chrome in a temporary isolated profile, records until you press Enter for up to five minutes, and flashes purple outlines with component names as React renders. It then returns a readable summary plus the path to a compressed DevTools trace. In an interactive terminal you can run `react-doctor scan` without a URL and pick a detected localhost app; coding agents and CI must pass the URL explicitly.
Authenticated sessions are handled by attaching to a Chrome instance you started yourself:
npx react-doctor@latest scan https://app.example.com --cdp http://127.0.0.1:9222The constraint here is real and the README is upfront about it. Chrome performance tracing is browser-wide, so React Doctor rejects attached profiles that have open pages. It closes blank startup tabs before tracing and closes its own scan tab afterward, leaving the attached browser open. An already-open normal browser is left alone.
The trace is stored locally and never uploaded, but the README warns that it can contain page URLs, source paths and React profiling details, and says to treat it as sensitive application data. That is the correct framing. A local-only artifact is not the same as a safe artifact; it is a file that will end up in a shared drive or a CI cache if nobody decides where it goes.
Telemetry, the licence, and what the repository does not say
The CLI reports crashes, basic run traces and anonymous usage counters to Sentry by default. The README enumerates the categories: environment (CLI version, platform, Node version); invocation (command, package manager, and whether the run is local, CI or a coding agent); project shape (framework, React version, TypeScript, project size, with no file contents); rules fired (rule names and counts only, with no code or specific findings); and de-minified CLI stack traces. Opting out is a single flag:
npx react-doctor@latest --no-telemetryThe README does not say whether telemetry is disabled by default in CI or in agent contexts, so if that distinction matters to your organisation, the flag is the documented answer.
The licence situation needs care. The README ends with "MIT-licensed", and the repository has a `LICENSE` file, but the repository metadata reports the licence as NOASSERTION, which means GitHub could not classify it. That is a discrepancy worth resolving before you depend on the package in a commercial product, since the README text and the machine-readable metadata disagree. Nothing here is legal advice; read the `LICENSE` file and decide with whoever handles licensing at your organisation.
On maintenance, the facts are narrow: the repository is not archived, and the last push was on 2026-09-15. The three 0.9.14 packages were released on 2026-09-12. Beyond that, the README does not document a support policy, a release cadence, or a deprecation process for rules.
Where React Doctor is the wrong tool
The most important limitation is the one the project's own framing implies. React Doctor is an additional pass, not a replacement for your existing linter. The published `eslint-plugin-react-doctor` and `oxlint-plugin-react-doctor` packages mean the rules can live inside an ESLint or oxlint run, but the CLI's value comes from the audit report, the agent skill and the CI gate, not from rule coverage that duplicates what you already have. If your team wants one linter and one config file, adding a second rule set with its own `doctor.config.ts` is a net increase in surface area.
Rule noise is the second risk, and it is structural rather than a bug. A scanner that reports across six categories on an existing codebase will produce a long first report. The CI design mitigates this by reporting only issues a change introduced, which is a deliberate admission that the full report is not a usable gate.
The trace workflow has its own boundary. It requires a running app, a Chrome installation, and a human or script to interact with the page. It is not a headless check you can run on every commit without deciding what interaction to perform. The five-minute recording ceiling and the rejection of attached profiles with open pages both constrain how it fits into an automated pipeline.
Finally, the tool is React-specific by construction. The README's framework list is broad within React, but a Vue or Svelte codebase gets nothing from it, and the rules encode React idioms that do not translate.
React Doctor versus a plain ESLint setup
The honest comparison is not React Doctor against some other React scanner; it is React Doctor against the ESLint configuration you already maintain. The difference is not the rule engine, since `eslint-plugin-react-doctor` runs inside ESLint. The difference is everything around it.
A hand-built ESLint setup reports every violation in the files it lints. React Doctor's CI path reports only what a pull request introduced, and posts a summary comment on the PR. That single behavioural difference changes who reads the output: an ESLint run is consumed by the developer who triggered it, while a PR comment is consumed by reviewers and, in the agent workflow, by the agent that will fix the code next.
The second difference is the skill install. ESLint has no equivalent step. `npx react-doctor@latest install` writes agent-readable guidance derived from your own audit, which is a different mechanism from a rules file, even when both end up enforcing similar constraints.
The third is the runtime trace. ESLint is static. `react-doctor scan` records an actual Chrome performance trace and maps renders to component names. If your problem is a re-render that no static rule can see, the static linter is the wrong instrument, and the trace path is the reason to run this tool at all.
If none of those three differences matter to you, the plugins alone are the smaller commitment.
Editorial conclusion
Adopt React Doctor if your team already runs coding agents against a React codebase and wants a deterministic pass that catches state, effect, performance and accessibility problems before review, and if you are willing to run a first audit and then decide which rules to keep. Skip it if you need a single linter to replace your existing ESLint setup, or if you cannot accept a CLI that reports anonymous usage counters to Sentry by default. Verify three things first: that `npx react-doctor@latest` runs clean on your project root, that `react-doctor ci config` exposes a gate setting you can live with, and that the trace files produced by `react-doctor scan` are stored somewhere you consider acceptable, since the README notes they can contain page URLs and source paths.
Frequently asked questions
How do I install React Doctor?
There is no global install. The README's quick start runs `npx react-doctor@latest` at your project root to get an audit, and `npx react-doctor@latest install` afterwards to install the skill for your coding agent.
How do I use React Doctor?
Run `npx react-doctor@latest` at the project root for an audit, optionally passing file paths to limit the scan. From there you can install the agent skill, set up the CI gate with `npx react-doctor@latest ci install`, or record a runtime trace with `npx react-doctor@latest scan http://localhost:3000`.
What does React Doctor do?
It deterministically scans a React codebase and reports issues across state and effects, performance, architecture, security, accessibility and maintainability. It also highlights overly complex React functions and repeated JSX trees as candidates for composition.
Is React Doctor free?
The README states the project is MIT-licensed, and the packages are published on npm. Note that the repository metadata reports the licence as NOASSERTION, so read the LICENSE file if the licence matters for your use.
Is React Doctor safe to run?
The CLI reports crashes, run traces and anonymous usage counters to Sentry by default, covering environment, invocation, project shape, rule names and counts, but no file contents or specific findings. You can opt out with `npx react-doctor@latest --no-telemetry`. Runtime traces stay local, but the README says they can contain page URLs and source paths and should be treated as sensitive.
How does React Doctor compare to ESLint?
React Doctor publishes `eslint-plugin-react-doctor` and `oxlint-plugin-react-doctor`, so its rules can run inside ESLint or oxlint. The difference is around the rules: a CI gate that reports only issues a pull request introduced, an installable agent skill, and a Chrome performance trace path that static linting cannot cover.
Community notes