React Doctor

React / Next.js / Vite / React Native 向けのヘルス診断。Oxlint ベースのルールと Knip によるデッドコード検出で 0〜100 のスコアを出す(millionco/react-doctor)。

1 — 概要

プロジェクトルートで 1 コマンド走らせると、状態管理・副作用・パフォーマンス・アーキテクチャ・セキュリティ・アクセシビリティ・デッドコードなど横断の診断がまとまり、0〜100 のヘルススコアと修正可能なメッセージが返る。フレームワークと React のメジャーバージョンに応じてルールが自動で切り替わる。

0–100スコア帯
75+Great
50–74Needs work
<50Critical

デモとリーダーボードは react.doctor。npm パッケージ名は react-doctor。

2 — スキャンとスコア

リポジトリのルートで次を実行する。結果にスコアと上位のルール違反が表示される。

npx -y react-doctor@latest .
既存の Lint 設定: .oxlintrc.json や .eslintrc.json がある場合、そのルールがスキャンにマージされスコアに反映される。マージを止めたい場合は設定で adoptExistingLintConfig: false。
3 — エージェント連携

コーディングエージェント向けにベストプラクティス用スキルを配置する対話フローがある。Claude Code、Cursor、Codex、OpenCode など検出されたエージェントを選べる。--yes でプロンプトを省略できる。

npx -y react-doctor@latest install
4 — GitHub Actions

pull_request で github-token を渡すと、指摘を PR コメントとして投稿できる。diff に基づく部分スキャンでは履歴取得のため fetch-depth: 0 が推奨される。

- uses: actions/checkout@v5
  with:
    fetch-depth: 0
- uses: millionco/react-doctor@main
  with:
    diff: main
    github-token: ${{ secrets.GITHUB_TOKEN }}

アクションは score 出力も公開するため、後続ステップの条件に使える。

5 — 設定と無視

ルートに JSON を置くか、package.json の "reactDoctor" キーで同様の構造を書ける。CLI フラグは常に設定より優先する。

{
  "ignore": {
    "rules": ["react/no-danger", "jsx-a11y/no-autofocus"],
    "files": ["src/generated/**"],
    "overrides": [
      {
        "files": ["components/diff/**"],
        "rules": ["react-doctor/no-array-index-as-key"]
      }
    ]
  }
}

無視の階層

キー効果
ignore.rules指定ルールを全体で無効化
ignore.filesマッチしたファイル上のすべてのルールを無効化
ignore.overridesディレクトリごとに特定ルールだけ無効化

.gitignore、.eslintignore、.oxlintignore、.prettierignore、および .gitattributes の linguist-vendored / linguist-generated を尊重する。行コメントの // eslint-disable* と // oxlint-disable* も解釈される。

インライン抑制(React Doctor 用)

// react-doctor-disable-next-line react-doctor/no-cascading-set-state
useEffect(() => {
  setA(value);
  setB(value);
}, [value]);

同一行で複数ルールを止めるときはルール ID をカンマ区切り。JSX 内ではブロックコメントや JSX コメントの置き方が ESLint と同様の慣習に合わせる。

6 — Lint プラグイン

同じルールセットが Oxlint プラグインと ESLint フラット設定用プラグインの両方として提供される。既存の Lint パイプラインに組み込みたい場合はこちらを使う。

Oxlint(.oxlintrc.json)

{
  "jsPlugins": [{ "name": "react-doctor", "specifier": "react-doctor/oxlint-plugin" }],
  "rules": {
    "react-doctor/no-fetch-in-effect": "warn",
    "react-doctor/no-derived-state-effect": "warn"
  }
}

ESLint(flat config)

import reactDoctor from "react-doctor/eslint-plugin";

export default [
  reactDoctor.configs.recommended,
  reactDoctor.configs.next,
  reactDoctor.configs["react-native"],
  reactDoctor.configs["tanstack-start"],
  reactDoctor.configs["tanstack-query"],
];

全ルール一覧の実体は upstream の oxlint-config.ts を参照。

7 — CLI と API
フラグ説明
--no-lintLint をスキップ
--no-dead-codeデッドコード検出をスキップ
--diff [base]指定ブランチとの差分ファイルだけスキャン
--stagedステージ済みファイルのみ(pre-commit 向け)
--json構造化 JSON を標準出力(人可読ログは抑制)
--explain <file:line>その位置でルールが発火した理由や抑制が効かない理由を表示
--annotationsGitHub Actions のアノテーション形式で診断を出力
--fail-on <level>error / warning / none で終了コードを制御

Node API

import { diagnose, toJsonReport, summarizeDiagnostics } from "react-doctor/api";

const result = await diagnose("./path/to/your/react-project");
console.log(result.score);
console.log(result.diagnostics);

diagnose の第 2 引数で { lint?: boolean, deadCode?: boolean } を渡せる。toJsonReport と summarizeDiagnostics で JSON レポート用の組み立てができる。型定義は api.ts。

8 — リポジトリ構成

pnpm workspace と Turborepo で管理されている。CLI とルール実装の本体、公開サイト、エージェント向けスキル定義が分離されている。

領域役割
packages/react-doctorCLI バイナリ、Oxlint/ESLint プラグイン、スキャン・スコアリング・設定読み込みの中核
packages/websiteスコア共有やバッジなどの Web 面(Next 系)
skills/react-doctorエージェント向けに配布するスキルメタデータ
action.ymlGitHub Action のエントリ
開発者向け: クローン後は pnpm install と pnpm build。ローカルバイナリは node packages/react-doctor/bin/react-doctor.js <path> で試せる。

ライセンス

MIT。