react-doctor 0.2.0-beta.1 → 0.2.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,13 +9,13 @@
9
9
 
10
10
  Your agent writes bad React, this catches it.
11
11
 
12
- React Doctor scans React projects with native codebase analysis, a curated oxlint rule set, and actionable diagnostics.
12
+ One command scans your codebase and outputs a **0 to 100 health score** with actionable diagnostics.
13
13
 
14
- Works with React, Next.js, React Native, Expo, TanStack Start, and common React ecosystem libraries.
14
+ Works with Next.js, Vite, and React Native.
15
15
 
16
- ### [See it in action](https://react.doctor)
16
+ ### [See it in action](https://react.doctor)
17
17
 
18
- ## Run
18
+ ## Install
19
19
 
20
20
  Run this at your project root:
21
21
 
@@ -23,119 +23,104 @@ Run this at your project root:
23
23
  npx -y react-doctor@latest .
24
24
  ```
25
25
 
26
- By default React Doctor runs:
27
-
28
- - native project structure and codebase graph checks
29
- - oxlint with the React Doctor custom plugin
30
- - scoring and grouped human output
31
-
32
- You get a 0 to 100 score and a list of issues across state and effects, performance, architecture, security, accessibility, framework usage, dependencies, and dead code. Rules toggle automatically based on your framework, React version, and detected libraries.
26
+ You'll get a score (75+ Great, 50 to 74 Needs work, under 50 Critical) and a list of issues across state & effects, performance, architecture, security, accessibility, and dead code. Rules toggle automatically based on your framework and React version.
33
27
 
34
28
  https://github.com/user-attachments/assets/07cc88d9-9589-44c3-aa73-5d603cb1c570
35
29
 
36
- ## React Doctor Skill
30
+ ## Install for your coding agent
37
31
 
38
- React Doctor also ships as an agent Skill. The CLI catches problems after code is written; the Skill teaches your coding agent the same React, framework, and performance guidance before it writes the next patch.
32
+ Teach your coding agent React best practices so it stops writing the bad code in the first place.
39
33
 
40
34
  ```bash
41
35
  npx -y react-doctor@latest install
42
36
  ```
43
37
 
44
- Use the Skill when you want agents to:
38
+ You'll be prompted to pick which detected agents to install for. Pass `--yes` to skip prompts.
45
39
 
46
- - avoid common state and effect mistakes
47
- - choose framework-native APIs for Next.js, React Native, Expo, and TanStack Start
48
- - keep rendering, animation, data fetching, and accessibility choices high-signal
49
- - understand React Doctor diagnostics and fix the underlying issue instead of hiding it
40
+ Works with Claude Code, Cursor, Codex, OpenCode, and 50+ other agents.
50
41
 
51
- The installer detects supported coding agents and prompts you to choose where to install the Skill. Pass `--yes` to accept the default detected targets.
42
+ ## GitHub Actions
52
43
 
53
- ## CLI
44
+ A composite action ships with this repository. Drop it into `.github/workflows/react-doctor.yml`:
54
45
 
55
- ```bash
56
- react-doctor [directory]
57
- ```
46
+ ```yaml
47
+ name: React Doctor
58
48
 
59
- Useful flags:
49
+ on:
50
+ pull_request:
51
+ push:
52
+ branches: [main]
60
53
 
61
- ```bash
62
- react-doctor apps/web --json
63
- react-doctor apps/web --json --json-compact
64
- react-doctor apps/web --no-lint
65
- react-doctor apps/web --no-dead-code
66
- react-doctor apps/web --custom-rules-only
67
- react-doctor apps/web --staged
68
- react-doctor apps/web --unstaged
69
- react-doctor apps/web --changed
70
- react-doctor apps/web --diff main
71
- react-doctor apps/web --offline
72
- react-doctor apps/web --fail-on error
54
+ permissions:
55
+ contents: read
56
+ pull-requests: write # required to post PR comments
57
+
58
+ jobs:
59
+ react-doctor:
60
+ runs-on: ubuntu-latest
61
+ steps:
62
+ - uses: actions/checkout@v5
63
+ with:
64
+ fetch-depth: 0 # required for `diff`
65
+ - uses: millionco/react-doctor@main
66
+ with:
67
+ diff: main
68
+ github-token: ${{ secrets.GITHUB_TOKEN }}
73
69
  ```
74
70
 
75
- Changed-file modes only inspect matching source files:
71
+ When `github-token` is set on `pull_request` events, findings are posted (and updated) as a PR comment. The action also exposes a `score` output (0–100) you can use in subsequent steps.
76
72
 
77
- - `--staged` scans the git index for pre-commit flows.
78
- - `--unstaged` scans unstaged and untracked source files.
79
- - `--changed` scans staged, unstaged, and untracked source files since `HEAD`.
80
- - `--diff [base]` scans files changed against a base branch, defaulting to `main`.
73
+ **Inputs:** `directory`, `verbose`, `project`, `diff`, `github-token`, `fail-on` (`error` / `warning` / `none`), `offline`, `node-version`. See [`action.yml`](https://github.com/millionco/react-doctor/blob/main/action.yml) for full descriptions.
81
74
 
82
- If no changed source files are found, source checks are skipped instead of falling back to a full scan.
75
+ Prefer not to add a marketplace action? The bare `npx` form works too:
83
76
 
84
- `--fail-on` accepts `error`, `warning`, or `none`.
77
+ ```yaml
78
+ - run: npx -y react-doctor@latest --fail-on warning
79
+ ```
85
80
 
86
81
  ## Configuration
87
82
 
88
- React Doctor looks for configuration in:
89
-
90
- - `react-doctor.config.json`
91
- - `package.json#reactDoctor`
92
-
93
- Config lookup starts at the requested directory and walks ancestors until a project boundary. `rootDir` is resolved relative to the config source, not the current working directory.
83
+ Create a `react-doctor.config.json` in your project root:
94
84
 
95
85
  ```json
96
86
  {
97
- "rootDir": "apps/web",
98
- "lint": true,
99
- "deadCode": true,
100
- "customRulesOnly": false,
101
- "offline": true,
102
- "failOn": "error",
103
- "respectInlineDisables": true,
104
- "adoptExistingLintConfig": false,
105
- "includeEcosystemRules": true,
106
- "ignoredTags": ["design"],
107
- "textComponents": ["Trans"],
108
- "rawTextWrapperComponents": ["Button"],
109
87
  "ignore": {
110
- "rules": ["react-doctor/no-gradient-text"],
88
+ "rules": ["react/no-danger", "jsx-a11y/no-autofocus"],
111
89
  "files": ["src/generated/**"],
112
90
  "overrides": [
113
91
  {
114
- "files": ["src/legacy/**"],
115
- "rules": ["react-doctor/no-default-props"]
92
+ "files": ["components/modules/diff/**"],
93
+ "rules": ["react-doctor/no-array-index-as-key", "react-doctor/no-render-in-render"]
94
+ },
95
+ {
96
+ "files": ["components/search/HighlightedSnippet.tsx"],
97
+ "rules": ["react/no-danger"]
116
98
  }
117
99
  ]
118
100
  }
119
101
  }
120
102
  ```
121
103
 
122
- Pick the narrowest ignore that fits:
104
+ Three nested keys, three layers of granularity — pick the narrowest one that fits:
123
105
 
124
- - **`ignore.rules`** silences a rule across the codebase.
125
- - **`ignore.files`** silences every rule on matched files.
106
+ - **`ignore.rules`** silences a rule across the whole codebase.
107
+ - **`ignore.files`** silences **every** rule on the matched files (use sparingly — it loses coverage for unrelated rules).
126
108
  - **`ignore.overrides`** silences only the listed rules on the matched files, leaving every other rule active. This is what you want when a single file (or glob) legitimately needs an exemption from one or two rules but should still be scanned for everything else.
127
109
 
128
- React Doctor scans only its curated rule set by default. Set `adoptExistingLintConfig` to `true` to adopt the first JSON `.oxlintrc.json` or `.eslintrc.json` found while walking ancestors.
110
+ You can also use the `"reactDoctor"` key in `package.json`. CLI flags always override config values.
129
111
 
130
- `ignoredTags` lets you trim noisy categories without turning the whole scanner off. For example, `["design"]` keeps structural React checks while skipping subjective visual style suggestions.
112
+ React Doctor respects `.gitignore`, `.eslintignore`, `.oxlintignore`, `.prettierignore`, and `linguist-vendored` / `linguist-generated` annotations in `.gitattributes`. Inline `// eslint-disable*` and `// oxlint-disable*` comments are honored too.
131
113
 
132
- For React Native, `textComponents` marks custom components that behave like `<Text>`, while `rawTextWrapperComponents` marks components that safely wrap string-only children in text internally.
114
+ If you have a JSON oxlint or eslint config (`.oxlintrc.json` or `.eslintrc.json`), its rules get merged into the scan automatically and count toward the score. Set `adoptExistingLintConfig: false` to opt out.
133
115
 
134
- ## Scoring
116
+ #### Optional companion plugins
135
117
 
136
- Scores are a simple health signal, not a moral judgment. React Doctor starts at 100, subtracts more for error-level rule families than warning-level families, and counts a repeated rule once so one noisy pattern does not dominate the whole project.
118
+ When the following ESLint plugins are installed in the scanned project (or hoisted in your monorepo), React Doctor folds their rules into the same scan. Both are listed as **optional peer dependencies** install only what you want.
137
119
 
138
- The score can move between releases as rules become more precise, new framework rules are added, or noisy checks are demoted. Treat the detailed diagnostics as the source of truth and use the score for trend tracking across repeated runs.
120
+ | Plugin | Adds | Namespace |
121
+ | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
122
+ | [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks) (v6 or v7) | The React Compiler frontend's correctness rules — fired when a React Compiler is detected in the project. | `react-hooks-js/*` |
123
+ | [`eslint-plugin-react-you-might-not-need-an-effect`](https://github.com/nickjvandyke/eslint-plugin-react-you-might-not-need-an-effect) (v0.10+) | Complementary effects-as-anti-pattern rules (`no-derived-state`, `no-chain-state-updates`, `no-event-handler`, `no-pass-data-to-parent`, …) that run alongside React Doctor's native State & Effects rules. | `effect/*` |
139
124
 
140
125
  ### Inline suppressions
141
126
 
@@ -154,7 +139,7 @@ When two rules fire on the same line, you have two equivalent options. Comma-sep
154
139
  const [localSearch, setLocalSearch] = useState(searchQuery);
155
140
  ```
156
141
 
157
- Or stack one comment per rule directly above the diagnostic:
142
+ Or stack one comment per rule directly above the diagnostic. Stacked comments are honored as long as nothing but other `react-doctor-disable-next-line` comments sits between them and the target line:
158
143
 
159
144
  ```tsx
160
145
  // react-doctor-disable-next-line react-doctor/rerender-state-only-in-handlers
@@ -162,142 +147,165 @@ Or stack one comment per rule directly above the diagnostic:
162
147
  const [localSearch, setLocalSearch] = useState(searchQuery);
163
148
  ```
164
149
 
150
+ A code line between stacked comments breaks the chain: only the comment immediately above the diagnostic (and any contiguous `react-doctor-disable-next-line` comments stacked on top of it) is honored. If a comment looks adjacent but the rule still fires, run `react-doctor --explain <file:line>` — it reports whether a nearby suppression was found, what rules it covers, and why it didn't apply.
151
+
165
152
  Block comments work inside JSX:
166
153
 
167
154
  <!-- prettier-ignore -->
168
155
  ```tsx
169
- {/* react-doctor-disable-next-line no-danger */}
156
+ {/* react-doctor-disable-next-line react/no-danger */}
170
157
  <div dangerouslySetInnerHTML={{ __html }} />
171
158
  ```
172
159
 
173
160
  For multi-line JSX, putting the comment immediately above the opening tag covers the entire attribute list (matching ESLint convention).
174
161
 
175
- ## Lint Integrations
162
+ ## Lint plugin (standalone)
176
163
 
177
- The same rule set ships as both an oxlint plugin and an ESLint plugin, so you can wire it into whichever lint engine your project already runs.
164
+ The same rule set ships as both an oxlint plugin and an ESLint plugin, so you can wire it into whichever lint engine your project already runs. These are published as separate packages, so you can install just the lint integration without pulling in the full CLI.
178
165
 
179
- Oxlint (`.oxlintrc.json`):
166
+ **oxlint** in `.oxlintrc.json` (install [`oxlint-plugin-react-doctor`](https://npmjs.com/package/oxlint-plugin-react-doctor)):
180
167
 
181
168
  ```jsonc
182
169
  {
183
- "jsPlugins": [{ "name": "react-doctor", "specifier": "react-doctor/oxlint-plugin" }],
170
+ "jsPlugins": [{ "name": "react-doctor", "specifier": "oxlint-plugin-react-doctor" }],
184
171
  "rules": {
185
172
  "react-doctor/no-fetch-in-effect": "warn",
173
+ "react-doctor/no-derived-state-effect": "warn",
186
174
  },
187
175
  }
188
176
  ```
189
177
 
190
- ESLint:
178
+ **ESLint** flat config (install [`eslint-plugin-react-doctor`](https://npmjs.com/package/eslint-plugin-react-doctor)):
191
179
 
192
180
  ```js
193
- import reactDoctor from "react-doctor/eslint-plugin";
181
+ import reactDoctor from "eslint-plugin-react-doctor";
194
182
 
195
183
  export default [
196
- {
197
- plugins: {
198
- "react-doctor": reactDoctor,
199
- },
200
- rules: {
201
- "react-doctor/no-fetch-in-effect": "warn",
202
- },
203
- },
184
+ reactDoctor.configs.recommended,
185
+ reactDoctor.configs.next,
186
+ reactDoctor.configs["react-native"],
187
+ reactDoctor.configs["tanstack-start"],
188
+ reactDoctor.configs["tanstack-query"],
204
189
  ];
205
190
  ```
206
191
 
207
- The ESLint wrapper reuses the same rule implementations and metadata as the oxlint plugin.
192
+ The full rule list lives in [`packages/oxlint-plugin-react-doctor/src/plugin/rules`](https://github.com/millionco/react-doctor/tree/main/packages/oxlint-plugin-react-doctor/src/plugin/rules).
208
193
 
209
- ## SDK
194
+ ## CLI reference
210
195
 
211
- ```ts
212
- import { createReactDoctor, inspectReactProject } from "react-doctor";
196
+ ```
197
+ Usage: react-doctor [directory] [options]
198
+
199
+ Options:
200
+ -v, --version display the version number
201
+ --no-lint skip linting
202
+ --verbose show every rule and per-file details (default shows top 3 rules)
203
+ --score output only the score
204
+ --json output a single structured JSON report
205
+ -y, --yes skip prompts, scan all workspace projects
206
+ --full skip prompts, always run a full scan
207
+ --project <name> select workspace project (comma-separated for multiple)
208
+ --diff [base] scan only files changed vs base branch
209
+ --staged scan only staged files (for pre-commit hooks)
210
+ --offline skip the score API and share URL (no score shown)
211
+ --fail-on <level> exit with error on diagnostics: error, warning, none
212
+ --annotations output diagnostics as GitHub Actions annotations
213
+ --explain <file:line> diagnose why a rule fired or why a suppression didn't apply
214
+ --why <file:line> alias for --explain
215
+ -h, --help display help
216
+ ```
213
217
 
214
- const result = await inspectReactProject({
215
- rootDirectory: "apps/web",
216
- lint: true,
217
- deadCode: true,
218
- });
218
+ When a suppression isn't working, `--explain <file:line>` (or its alias `--why <file:line>`) reports what the scanner sees at that location, including why a nearby `react-doctor-disable-next-line` didn't apply. The diagnosis distinguishes the common failure modes — adjacent comment for a different rule (use the comma form), a code line between the comment and the diagnostic (the chain is broken), or no nearby suppression at all. The same hint surfaces inline with `--verbose` for every flagged site, and in `--json` output as `diagnostic.suppressionHint`, so a single scan doubles as a suppression audit without a separate flag.
219
219
 
220
- const reactDoctor = createReactDoctor({ rootDirectory: "apps/web" });
221
- const nextResult = await reactDoctor.inspect();
222
- ```
220
+ `--json` produces a parsable object on stdout with all human-readable output suppressed. Errors still produce a JSON object with `ok: false`, so stdout is always a valid document.
223
221
 
224
- The result includes project metadata, check results, normalized issues, score, and timing.
222
+ ### Config keys
225
223
 
226
- ```ts
227
- import { buildReactDoctorJsonReport } from "react-doctor";
224
+ | Key | Type | Default |
225
+ | -------------------------- | -------------------------------- | -------- |
226
+ | `ignore.rules` | `string[]` | `[]` |
227
+ | `ignore.files` | `string[]` | `[]` |
228
+ | `ignore.overrides` | `{ files, rules? }[]` | `[]` |
229
+ | `lint` | `boolean` | `true` |
230
+ | `verbose` | `boolean` | `false` |
231
+ | `diff` | `boolean \| string` | |
232
+ | `failOn` | `"error" \| "warning" \| "none"` | `"none"` |
233
+ | `customRulesOnly` | `boolean` | `false` |
234
+ | `share` | `boolean` | `true` |
235
+ | `offline` | `boolean` | `false` |
236
+ | `textComponents` | `string[]` | `[]` |
237
+ | `rawTextWrapperComponents` | `string[]` | `[]` |
238
+ | `respectInlineDisables` | `boolean` | `true` |
239
+ | `adoptExistingLintConfig` | `boolean` | `true` |
240
+ | `ignore.tags` | `string[]` | `[]` |
228
241
 
229
- const report = buildReactDoctorJsonReport(result);
230
- ```
242
+ `textComponents` is the broad escape hatch for `rn-no-raw-text` — list components that themselves behave like React Native's `<Text>` (custom `Typography`, `NativeTabs.Trigger.Label`, etc.) and the rule will treat them as text containers regardless of what their children look like.
231
243
 
232
- Typed runtime errors are exported from the main SDK:
244
+ `rawTextWrapperComponents` is the narrower option for components that are not text elements but safely route string-only children through an internal `<Text>` (e.g. `heroui-native`'s `Button`, which stringifies its children and renders them through a `ButtonLabel`). Listed wrappers suppress `rn-no-raw-text` only when their children are entirely stringifiable. A wrapper with mixed children — e.g. `<Button>Save<Icon /></Button>` — still reports because the wrapper can't safely route raw text alongside a sibling JSX element.
233
245
 
234
- ```ts
235
- import { ReactDoctorInvalidConfigError, isReactDoctorError } from "react-doctor";
236
- ```
246
+ `ignore.tags` suppresses entire categories of rules by tag. For example, `"tags": ["design"]` disables all opinionated design rules (gradient text, pure black backgrounds, side tab borders, default Tailwind palettes). Available tags: `"design"`.
237
247
 
238
- ## Compatibility API
248
+ `offline` skips the score API entirely — no score is shown and no share URL is generated. Automatically enabled in CI environments (GitHub Actions, GitLab CI, CircleCI) so CI runs don't depend on the network.
239
249
 
240
- Deprecated compatibility APIs live under `react-doctor/api` and are intentionally isolated from the main runtime.
250
+ ## Scoring
241
251
 
242
- ```ts
243
- import { diagnose, clearCaches } from "react-doctor/api";
252
+ The health score formula: `100 - (unique_error_rules x 1.5) - (unique_warning_rules x 0.75)`.
244
253
 
245
- const result = await diagnose("apps/web", {
246
- lint: true,
247
- deadCode: true,
248
- });
254
+ Scoring runs on react.doctor's API and is **network-dependent**: without a successful API round-trip (or under `--offline`) the score is omitted and the rest of the report still renders normally. Key details:
249
255
 
250
- clearCaches();
251
- ```
256
+ - The score counts **unique rules triggered**, not total instances. Fixing 49 of 50 `no-barrel-import` violations does not change the score; fixing all 50 removes the 0.75 penalty for that rule.
257
+ - Error-severity rules cost 1.5 points each. Warning-severity rules cost 0.75 points each.
258
+ - Category breakdowns shown in the output are for display only and do not weight the score.
252
259
 
253
- Prefer `createReactDoctor()` or `inspectReactProject()` for new integrations.
260
+ Score labels: 75+ is **Great**, 50 to 74 is **Needs work**, under 50 is **Critical**.
254
261
 
255
- ## Development
262
+ Scores may decrease across releases as new rules are added. Each new rule that fires in your codebase introduces an additional penalty. This is expected — it means the tool is catching more issues, not that your code got worse. Pin to a specific react-doctor version in CI if you need stable scores across upgrades.
256
263
 
257
- Run package checks from the package directory:
264
+ ## Diff and staged modes
258
265
 
259
- ```bash
260
- nr typecheck
261
- nr test
262
- nr build
263
- ```
266
+ React Doctor can scan only changed files instead of the full project:
264
267
 
265
- Run workspace formatting and linting from the repository root:
268
+ - **`--diff [base]`** scans files changed vs a base branch. Auto-detects `main`/`master`, or pass an explicit branch: `--diff develop`. Also available as a config key: `"diff": true` or `"diff": "develop"`.
269
+ - **`--staged`** scans only files in the git staging area (index). Designed for pre-commit hooks — materializes staged file contents into a temp directory so the scan reflects exactly what will be committed.
270
+ - **`--full`** forces a full scan, overriding any `diff` value in config or CLI.
266
271
 
267
- ```bash
268
- nr format:check packages/react-doctor/src packages/react-doctor/tests
269
- nr lint packages/react-doctor/src packages/react-doctor/tests
270
- ```
272
+ When on a feature branch without explicit flags, you'll be prompted: "Only scan changed files?" This prompt is suppressed in CI, `--json` mode, and non-interactive environments.
271
273
 
272
- ## Regression testing
274
+ `--staged` and `--diff` cannot be combined.
273
275
 
274
- Drive the sandbox test suite in the sibling [`react-review`](https://github.com/millionco/react-review) repo against a fleet of real React projects, using the local working copy of `react-doctor` (packed into a tarball).
276
+ ## Agent and CI integration
275
277
 
276
- ```bash
277
- pnpm --filter react-doctor test:regression
278
- ```
278
+ React Doctor detects 50+ coding agents (Claude Code, Cursor, Codex, OpenCode, Windsurf, and more) and adapts its behavior automatically:
279
279
 
280
- The script builds the package, packs it into `packages/react-doctor/.regression/react-doctor-<version>.tgz`, then shells out to `~/Developer/react-review/apps/api` and runs `pnpm test` with:
280
+ - **Install for agents**: `npx react-doctor@latest install` writes agent-specific rule files (SKILL.md, AGENTS.md, .cursorrules) into your project so agents learn React best practices.
281
+ - **JSON output**: `--json` produces a structured `JsonReport` on stdout. Errors still produce a valid JSON document with `ok: false`. Use `--json-compact` for minimal whitespace.
282
+ - **Score-only output**: `--score` outputs just the numeric score (0-100), useful for threshold checks in agent loops.
283
+ - **GitHub Actions annotations**: `--annotations` emits `::error` / `::warning` format for inline PR annotations.
284
+ - **Exit codes**: `--fail-on error` (default) exits non-zero when error-severity diagnostics are found. Use `--fail-on warning` or `--fail-on none` to tune CI gating.
285
+ - **Programmatic API**: `import { diagnose } from "react-doctor/api"` for direct integration in scripts and automation.
281
286
 
282
- - `GITHUB_TOKEN` from `gh auth token` (required so GitHub does not 403 the tarball downloads).
283
- - `REACT_DOCTOR_SPECIFIERS` pointing at the local tarball — `react-review`'s sandbox test detects the `.tgz`, uploads it into the Vercel Sandbox, and installs via `file:`.
284
- - `REACT_DOCTOR_TEST_REPOS` defaulting to the first 10 repos from a curated fleet, comma-separated `owner/repo` entries.
287
+ In CI environments, prompts are automatically skipped and `--offline` is implied (no network round-trip; score is omitted from the output).
285
288
 
286
- Preconditions the script checks for and surfaces clear errors when missing:
289
+ ## Node.js API
287
290
 
288
- - `gh auth token` succeeds (run `gh auth login` first if not).
289
- - `~/Developer/react-review/apps/api` exists.
290
- - `~/Developer/react-review/apps/api/.env.local` exists (run `vercel env pull` inside `~/Developer/react-review/apps/api` to populate `@vercel/sandbox` credentials).
291
+ ```js
292
+ import { diagnose, toJsonReport, summarizeDiagnostics } from "react-doctor/api";
291
293
 
292
- Overrides:
294
+ const result = await diagnose("./path/to/your/react-project");
293
295
 
294
- ```bash
295
- REACT_DOCTOR_REGRESSION_SAMPLE=25 pnpm --filter react-doctor test:regression
296
- REACT_DOCTOR_REGRESSION_SAMPLE=all pnpm --filter react-doctor test:regression
297
- REACT_DOCTOR_TEST_REPOS="vercel/ai-chatbot,shadcn-ui/ui" pnpm --filter react-doctor test:regression
296
+ console.log(result.score); // { score: 82, label: "Great" } or null
297
+ console.log(result.diagnostics); // Diagnostic[]
298
+ console.log(result.project); // detected framework, React version, etc.
299
+ ```
300
+
301
+ `diagnose` accepts a second argument: `{ lint?: boolean }`.
302
+
303
+ ```js
304
+ const report = toJsonReport(result, { version: "1.0.0" });
305
+ const counts = summarizeDiagnostics(result.diagnostics);
298
306
  ```
299
307
 
300
- Each repo runs sequentially inside a Vercel Sandbox; expect a few minutes per repo. The default 10-repo sample is the sane batch size for a single run.
308
+ `react-doctor/api` re-exports `JsonReport`, `JsonReportSummary`, `JsonReportProjectEntry`, `JsonReportMode`, plus the lower-level `buildJsonReport` and `buildJsonReportError` builders. See [`packages/react-doctor/src/api.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/api.ts) for the full types.
301
309
 
302
310
  ## Leaderboard
303
311
 
@@ -331,15 +339,13 @@ Looking to contribute back? Clone the repo, install, build, and submit a PR.
331
339
  ```bash
332
340
  git clone https://github.com/millionco/react-doctor
333
341
  cd react-doctor
334
- ni
335
- nr build
336
- node packages/react-doctor/bin/react-doctor.js apps/web
342
+ pnpm install
343
+ pnpm build
344
+ node packages/react-doctor/bin/react-doctor.js /path/to/your/react-project
337
345
  ```
338
346
 
339
347
  Find a bug? Head to the [issue tracker](https://github.com/millionco/react-doctor/issues).
340
348
 
341
- Release notes are published on [GitHub Releases](https://github.com/millionco/react-doctor/releases).
342
-
343
349
  ### License
344
350
 
345
351
  React Doctor is MIT-licensed open-source software.