react-doctor 0.2.0-beta.5 → 0.2.0
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 +100 -14
- package/dist/cli.js +2145 -187
- package/dist/index.d.ts +55 -0
- package/dist/index.js +2113 -153
- package/dist/skills/react-doctor/SKILL.md +4 -4
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -20,10 +20,12 @@ Works with Next.js, Vite, and React Native.
|
|
|
20
20
|
Run this at your project root:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
npx
|
|
23
|
+
npx react-doctor@latest
|
|
24
24
|
```
|
|
25
25
|
|
|
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,
|
|
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, and accessibility. Rules toggle automatically based on your framework and React version.
|
|
27
|
+
|
|
28
|
+
> **Migration note:** React Doctor used to bundle [knip](https://knip.dev/) for dead-code detection. That integration was removed in v0.2 — if you want dead-code analysis, run `npx knip` directly as part of your own pre-commit or CI pipeline.
|
|
27
29
|
|
|
28
30
|
https://github.com/user-attachments/assets/07cc88d9-9589-44c3-aa73-5d603cb1c570
|
|
29
31
|
|
|
@@ -32,7 +34,7 @@ https://github.com/user-attachments/assets/07cc88d9-9589-44c3-aa73-5d603cb1c570
|
|
|
32
34
|
Teach your coding agent React best practices so it stops writing the bad code in the first place.
|
|
33
35
|
|
|
34
36
|
```bash
|
|
35
|
-
npx
|
|
37
|
+
npx react-doctor@latest install
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
You'll be prompted to pick which detected agents to install for. Pass `--yes` to skip prompts.
|
|
@@ -68,16 +70,87 @@ jobs:
|
|
|
68
70
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
69
71
|
```
|
|
70
72
|
|
|
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.
|
|
73
|
+
When `github-token` is set on `pull_request` events, findings are posted (and updated) as a sticky PR comment. The action also exposes a `score` output (0–100) you can use in subsequent steps.
|
|
74
|
+
|
|
75
|
+
**Inputs:** `directory`, `verbose`, `project`, `diff`, `github-token`, `fail-on` (`error` / `warning` / `none`), `offline`, `annotations`, `node-version`. See [`action.yml`](https://github.com/millionco/react-doctor/blob/main/action.yml) for full descriptions.
|
|
76
|
+
|
|
77
|
+
#### PR feedback modes
|
|
72
78
|
|
|
73
|
-
|
|
79
|
+
Pick one or both; they're independent.
|
|
80
|
+
|
|
81
|
+
- **Comments only** (default): set `github-token`.
|
|
82
|
+
- **Annotations only**: set `annotations: true`.
|
|
83
|
+
- **Both**: set `github-token` and `annotations: true`. Annotation lines are stripped from the comment body.
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
- uses: millionco/react-doctor@main
|
|
87
|
+
with:
|
|
88
|
+
diff: main
|
|
89
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
90
|
+
annotations: true
|
|
91
|
+
```
|
|
74
92
|
|
|
75
93
|
Prefer not to add a marketplace action? The bare `npx` form works too:
|
|
76
94
|
|
|
77
95
|
```yaml
|
|
78
|
-
- run: npx
|
|
96
|
+
- run: npx react-doctor@latest --fail-on warning
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## PR blocking and exit codes
|
|
100
|
+
|
|
101
|
+
Two independent gates can block a PR — pick one or both:
|
|
102
|
+
|
|
103
|
+
- **`--fail-on <level>`** exits non-zero on diagnostics: `error` (default, any error-severity rule fires), `warning` (any diagnostic fires), or `none` (never). Runs against the `ciFailure` surface, so the default `design`-tag exclusion still applies.
|
|
104
|
+
- **Score floor** — a follow-up step that reads the action's `score` output and `exit 1`s when it's below your threshold.
|
|
105
|
+
|
|
106
|
+
Combine `--fail-on` with `--diff <base>` to scope the gate to the PR's changed files only — that's the built-in way to fail on **new** regressions without dragging in baseline backlog. There is no separate `--fail-on-new` flag.
|
|
107
|
+
|
|
108
|
+
`--annotations` (bare `npx` only) and `github-token` (sticky PR comment) are visualization layers and never change the exit code.
|
|
109
|
+
|
|
110
|
+
### Examples
|
|
111
|
+
|
|
112
|
+
**Advisory mode** — never blocks, always comments:
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
- uses: millionco/react-doctor@main
|
|
116
|
+
with:
|
|
117
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
118
|
+
fail-on: none
|
|
79
119
|
```
|
|
80
120
|
|
|
121
|
+
**Regression-only mode** — fail only on new diagnostics introduced by the PR:
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
- uses: actions/checkout@v5
|
|
125
|
+
with:
|
|
126
|
+
fetch-depth: 0 # required for `diff`
|
|
127
|
+
- uses: millionco/react-doctor@main
|
|
128
|
+
with:
|
|
129
|
+
diff: main
|
|
130
|
+
fail-on: warning
|
|
131
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Strict threshold mode** — fail when the baseline score drops below a floor:
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
- id: doctor
|
|
138
|
+
uses: millionco/react-doctor@main
|
|
139
|
+
with:
|
|
140
|
+
fail-on: error
|
|
141
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
142
|
+
- env:
|
|
143
|
+
SCORE: ${{ steps.doctor.outputs.score }}
|
|
144
|
+
FLOOR: "80"
|
|
145
|
+
run: |
|
|
146
|
+
if [ -n "$SCORE" ] && [ "$SCORE" -lt "$FLOOR" ]; then
|
|
147
|
+
echo "::error::React Doctor score $SCORE is below floor $FLOOR"
|
|
148
|
+
exit 1
|
|
149
|
+
fi
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Pin a specific `react-doctor` version when using a score floor — new rule releases can lower the score even when your code hasn't changed (see [Scoring](#scoring)).
|
|
153
|
+
|
|
81
154
|
## Configuration
|
|
82
155
|
|
|
83
156
|
Create a `react-doctor.config.json` in your project root:
|
|
@@ -132,6 +205,19 @@ Diagnostics flow through four independent surfaces — `cli`, `prComment`, `scor
|
|
|
132
205
|
|
|
133
206
|
Each surface accepts `includeTags`, `excludeTags`, `includeCategories`, `excludeCategories`, `includeRules`, and `excludeRules`. Include wins over exclude when both match. Run the CLI with `--pr-comment` (the GitHub Action passes it automatically when `github-token` is set) to apply the `prComment` surface to the printed output destined for sticky PR comments.
|
|
134
207
|
|
|
208
|
+
#### Rule severity (`rules`, `categories`)
|
|
209
|
+
|
|
210
|
+
Same shape as ESLint / oxlint. `rules` is ESLint's exact field; `categories` mirrors oxlint's, keyed by React Doctor display categories (`"React Native"`, `"Server"`, `"Architecture"`, …).
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"rules": { "react-doctor/no-array-index-as-key": "error" },
|
|
215
|
+
"categories": { "React Native": "warn" }
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Per-rule wins over per-category. `"off"` short-circuits before the rule runs; `"warn"` / `"error"` re-stamps the diagnostic so every channel — CLI, PR comment, score, `--fail-on` — sees the chosen severity, including for external-plugin rules. Use `surfaces` instead when you only want to hide a rule from one channel; use `ignore.tags` to silence a whole tag-defined family (`"design"`, `"test-noise"`, `"migration-hint"`) that doesn't align with a single category.
|
|
220
|
+
|
|
135
221
|
#### Optional companion plugins
|
|
136
222
|
|
|
137
223
|
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.
|
|
@@ -326,8 +412,8 @@ React Doctor detects 50+ coding agents (Claude Code, Cursor, Codex, OpenCode, Wi
|
|
|
326
412
|
- **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.
|
|
327
413
|
- **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.
|
|
328
414
|
- **Score-only output**: `--score` outputs just the numeric score (0-100), useful for threshold checks in agent loops.
|
|
329
|
-
- **GitHub Actions annotations**: `--annotations` emits `::error` / `::warning` format for inline PR annotations.
|
|
330
|
-
- **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.
|
|
415
|
+
- **GitHub Actions annotations**: `--annotations` emits `::error` / `::warning` format for inline PR annotations. Annotations don't change the exit code.
|
|
416
|
+
- **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. See [PR blocking and exit codes](#pr-blocking-and-exit-codes) for the full model — including how to fail only on new regressions vs. fail on the baseline score.
|
|
331
417
|
- **Programmatic API**: `import { diagnose } from "react-doctor/api"` for direct integration in scripts and automation.
|
|
332
418
|
|
|
333
419
|
In CI environments, prompts are automatically skipped and `--offline` is implied (no network round-trip; score is omitted from the output).
|
|
@@ -361,16 +447,16 @@ Top React codebases scanned by React Doctor, ranked by score. Updated automatica
|
|
|
361
447
|
<!-- prettier-ignore -->
|
|
362
448
|
| # | Repo | Score |
|
|
363
449
|
| -- | ---- | ----: |
|
|
364
|
-
| 1 | [executor](https://github.com/RhysSullivan/executor) |
|
|
450
|
+
| 1 | [executor](https://github.com/RhysSullivan/executor) | 96 |
|
|
365
451
|
| 2 | [nodejs.org](https://github.com/nodejs/nodejs.org) | 86 |
|
|
366
|
-
| 3 | [tldraw](https://github.com/tldraw/tldraw) |
|
|
367
|
-
| 4 | [t3code](https://github.com/pingdotgg/t3code) |
|
|
452
|
+
| 3 | [tldraw](https://github.com/tldraw/tldraw) | 71 |
|
|
453
|
+
| 4 | [t3code](https://github.com/pingdotgg/t3code) | 69 |
|
|
368
454
|
| 5 | [better-auth](https://github.com/better-auth/better-auth) | 64 |
|
|
369
|
-
| 6 | [
|
|
370
|
-
| 7 | [
|
|
455
|
+
| 6 | [mastra](https://github.com/mastra-ai/mastra) | 63 |
|
|
456
|
+
| 7 | [excalidraw](https://github.com/excalidraw/excalidraw) | 62 |
|
|
371
457
|
| 8 | [payload](https://github.com/payloadcms/payload) | 60 |
|
|
372
458
|
| 9 | [typebot](https://github.com/baptisteArno/typebot.io) | 57 |
|
|
373
|
-
| 10 | [
|
|
459
|
+
| 10 | [medusajs/admin](https://github.com/medusajs/medusa) | 56 |
|
|
374
460
|
|
|
375
461
|
<!-- LEADERBOARD:END -->
|
|
376
462
|
|