React Doctorは、Million Software, Inc.(Million.jsの開発元)が公開しているReact専用のコード診断CLIです。プロジェクトのルートでnpx react-doctor@latestを実行すると、バグ・パフォーマンス・セキュリティ・アクセシビリティ・保守性の5カテゴリで問題を列挙し、0〜100のヘルススコアを返します。本記事は2026年10月12日公開の0.9.18を基準に、サンプルプロジェクトで実行した結果を交えて、スコアの算出方法、--scopeによる差分診断、設定ファイル、コーディングエージェントへの導入、GitHub Actionの設定までを整理します。
まとめ:React Doctor 0.9.18の要点
- 実行は
npx react-doctor@latestの1行。Node.jsは^20.19.0 || >=22.13.0が必要で、内部ではoxlintで解析する。 - スコアは手元で計算されず、診断結果を
react.doctor/api/scoreへ送って算出される。--no-scoreやオフラインではスコアが出ない。 - CIの合否は
--blocking(既定error)で決まる。--scoreはerrorが残っていても終了コード0を返すので、合否判定には使えない。 - 差分だけを見るなら
--scope changed。以前の--diffは非推奨の別名として残っている。 - 設定は
doctor.config.*(ts・js・jsonなど8形式)かpackage.jsonのreactDoctorキー。rules disableなどのコマンドで書き込める。 - ライセンスは改変MIT。AIの学習データへの利用と、React Doctorを主な価値とする有償サービスとしての提供には書面の許諾が要る。
React Doctorの開発元・版・ライセンス
Million Software製のReact専用スキャナー
公式ドキュメントはReact Doctorを、Reactのコードを決定的(同じコードなら同じ結果)に検査するスキャナーと説明しています。対応は React・Next.js・Vite・TanStack・React Native・Expo・Preact です。解析エンジンにはRust製のoxlintを使い、npmパッケージの依存にはoxlint・oxc-parser・eslint-plugin-react-hooksが含まれます。oxlint自体の速度やESLintとの違いはOxlintとESLintの違いとは?読み方・速度実測・移行手順とBiomeとの比較で扱っています。
ルールの数は資料によって違います。0.9.18のrules list --jsonは906件を返し、そのうち既定で有効なのは688件でした。公式のルール索引は「802 active rules」と書いています。数え方の範囲が違うため、記事や資料で「約100ルール」「60以上」とあるのは初期の版の数字だと読んでください。
製品名・GitHub Actionのv2とnpm版番号の区別
npmのreact-doctorは2026年2月13日に公開され、10月時点でも0.9系です。一方、公式ブログは2026年2月17日に「React Doctor v1」、5月8日に「React Doctor v2」を発表しました。v2はReact NativeとExpo向けルール、useEffectの解析、ESLintプラグインとしての提供を加えた製品上の区切りです。GitHub Actionのタグも@v2(2026年10月31日時点の最新タグはv2.4.0)で、CLIのnpm版番号とは別に進んでいます。「react doctor v2」で検索してnpm i react-doctor@2を試しても、該当する版は存在しません。
GitHubリポジトリとライセンス
リポジトリはgithub.com/millionco/react-doctorで、GitHub APIで2026年10月31日に取得したスター数は15,072です。READMEには「MIT-licensed」とありますが、LICENSEファイルの題名は「Modified MIT License」で、次の2つの用途に事前の書面許諾を求めています。
- ソフトウェアやその派生物を、機械学習モデルやAIシステムの学習・ファインチューニング・評価のデータとして使うこと
- React Doctorを主な価値とする有償・ホスト型のサービス(商用APIやSaaS)として第三者に提供すること
社内の開発やCIで使う分には無償です。React Doctorを組み込んだ診断サービスを社外へ販売する計画があるなら、着手前に許諾の要否を確認してください。
npx react-doctorでスキャンする手順
実行コマンドと主なオプション
プロジェクトのルートで次を実行します。グローバルインストールは不要で、フレームワークとReactの版は自動で判定されます。
npx react-doctor@latest
npx react-doctor@latest --verbose # ファイルと行番号を表示
npx --yes react-doctor@latest --yes # npmとReact Doctorの確認を省略
npx react-doctor@latest --json | jq '.summary'
モノレポでは--project web,adminでワークスペースを選び、プロジェクトごとに採点させます。--category Performanceは表示を絞るだけで、スキャン対象のファイルは変わりません。
サンプル2ファイルで実行した結果(48点)
2026年10月31日にNode.js 26.5.0・React 19.2.0の最小構成で、診断対象の書き方を入れた2ファイルにreact-doctor 0.9.18を実行しました。useEffect内で絞り込み結果をsetStateする、useEffect内でfetchする、liにonClickを付ける、imgにaltが無い、といった内容です。
React Doctor — rd-sample
Score: 48 / 100 Critical
7 issues
Accessibility: 1 error, 2 warnings
Bugs: 4 warnings
✖ Image missing alt text react-doctor/alt-text
⚠ Derived value copied into state react-doctor/no-derived-state
⚠ Data fetching inside an effect react-doctor/no-fetch-in-effect
⚠ fetch Response consumed without status check
⚠ Effect promise .then sets state with no catch
⚠ Click handler missing keyboard handler
⚠ Handler on non-interactive element
2ファイルの走査は1.5〜2.4秒でした。altを足してerrorを0件にすると、warning 6件のまま65点(17点増)に上がりました。公式の手順では、セキュリティとパフォーマンスの指摘を先に扱い、その後にその他のerrorを修正します。
同じファイルでdangerouslySetInnerHTMLにユーザー入力を渡していましたが、指摘はありませんでした。該当ルールreact-doctor/no-dangerは既定で無効(defaultEnabled: false)だからです。XSS対策として使うなら、設定で明示的に有効にする必要があります。
why・rules explainによる指摘理由の確認
指摘の意味が分からないとき、または抑制コメントが効かないときはwhyに「ファイル:行」を渡します。該当箇所のコード、カテゴリ、推奨する直し方、近くに抑制コメントがあるかどうかが表示されます。ルールそのものの説明はrules explainで読めます。
npx react-doctor@latest why src/UserList.tsx:20
npx react-doctor@latest rules explain react-doctor/no-derived-state
静的解析には誤検知が付きものです。指摘を鵜呑みにしない判断の手順は静的コード解析の誤検知と限界|レビュー・テストとの責任分担にまとめています。
0〜100スコアの算出方法とCIの終了コード
react.doctor APIによるスコア算出と送信データ
0.9.18のソース(dist/index.jsのrequestScore)を読むと、スコアはCLIの中で計算されていません。診断結果をgzip圧縮したJSONでhttps://www.react.doctor/api/scoreへPOSTし、返ってきた点数とラベル(Great・Criticalなど)を表示しています。送信内容は次のとおりです。
- 各診断のルール名・メッセージ・行などと、秘匿情報を伏せたファイルパス(ソースコード本文の送信処理は無い)
- リポジトリ名・コミットSHA・フレームワーク・Reactの版・ソースファイル数・既定ブランチ・React Doctorの版
このため、--no-scoreを付けた場合は「Score disabled」、採点APIに到達できない場合は「Score unavailable」と表示され、点数は出ません。GitHub Actionのscore出力も、APIに届かないときは空になります。社外への送信が契約上許されないリポジトリでは--no-score --no-supply-chainを付けて採点APIとクラッシュ報告、Socket.devへの依存検査の通信を止め、点数ではなくerror・warningの件数で管理するのが現実的です。なお、クラッシュ報告はSentry、利用状況の計測はAxiomへ送られ、Data Useは「ファイルの内容やコード片は送らない」と明記しています。
blockingとscoreオプションの終了コードの違い
サンプルで終了コードを測ると次のとおりでした(error 1件・warning 6件の状態)。
| コマンド | 終了コード |
|---|---|
npx react-doctor -y(既定 blocking=error) |
1 |
--score |
0(48を出力) |
--blocking none |
0 |
--blocking warning |
1 |
| errorを0件にして既定で実行 | 0 |
--scoreは数値を出力するだけで、errorが残っていても成功で終わります。CIを止めたいなら--blocking errorかwarningを使い、点数のしきい値で止めたいなら--scoreの出力をシェルで比較する処理を自分で書く必要があります。GitLabなどで「警告ありだが失敗ではない」状態を表すには--warning-exit-codeで2〜255の値を指定できます。
scopeオプションによる差分診断の範囲と制約
0.9.18では診断範囲を--scopeで選びます。既定はfullです。部分スコープでは基準のブランチを自動で探し、--base mainで固定もできます。
| scope | 報告する範囲 |
|---|---|
full |
プロジェクト全体(既定) |
files |
変更したファイルの全指摘 |
changed |
基準と比べて新たに増えた指摘だけ |
lines |
変更行に掛かる指摘 |
contextual |
変更した関数・JSX要素・ファイル内の既存指摘(0.9.18で追加) |
サンプルでmainから枝を切り、条件分岐の後にuseStateを呼ぶコンポーネントを1つ追加して--scope changed --base mainを実行すると、既存の7件は出ず、react-doctor/rules-of-hooksのerror 1件だけが報告されました。旧来の--diff mainも動きますが、The '--diff' flag is deprecated; use '--scope changed'(原文はバッククォート)という警告が出ます。
コミット前のフックには--stagedを使います。unused-fileやcircular-dependencyなどプロジェクト全体の依存グラフを見る6ルールは既定で無効で、有効にしてもfullのときしか動きません。差分診断だけを回していると、未使用ファイルや循環依存は見つからない点に注意してください。
doctor.config.jsonとrulesコマンドによるルール調整
設定ファイルの置き場所と形式
React Doctorはスキャンするディレクトリから.gitかモノレポのルートまで親をたどり、doctor.config.*を探します。拡張子は.ts・.mts・.cts・.js・.mjs・.cjs・.json・.jsoncの8種類で、package.jsonのreactDoctorキーにも書けます。JSONはJSON5として読まれるため、コメントや末尾のカンマも許されます。コマンドラインの指定は設定より優先されます。
{
"$schema": "https://react.doctor/schema/config.json",
"ignore": {
"files": ["src/generated/**"],
"overrides": [
{ "files": ["components/search/HighlightedSnippet.tsx"], "rules": ["react-doctor/no-danger"] }
]
},
"rules": {
"react-doctor/no-danger": "warn",
"react-doctor/no-array-index-as-key": "error"
},
"categories": { "Maintainability": "warn" }
}
この例は、既定で無効のno-dangerを有効にしたうえで、サニタイズ済みのHTMLを意図して描画する1ファイルだけを除外しています。カテゴリ名はSecurity・Bugs・Performance・Accessibility・Maintainabilityの5つで、個別ルールの指定がカテゴリの指定より優先されます。
rulesコマンドによる設定ファイルの作成・更新
手で書く代わりに、rulesサブコマンドが既存の設定ファイルを編集します。設定ファイルが無ければdoctor.config.jsonを新規作成します。サンプルでalt-textを無効にすると、次のファイルができました。
$ npx react-doctor rules disable react-doctor/alt-text
Set react-doctor/alt-text → off
Updated doctor.config.json (created)
$ cat doctor.config.json
{
"$schema": "https://react.doctor/schema/config.json",
"rules": {
"react-doctor/alt-text": "off"
}
}
ignore・rules・surfacesの使い分け
3つは止める場所が違います。rulesやcategoriesでoffにするとルール自体が走りません。ignore.rulesはルールを走らせたうえで結果から落とします。surfacesではCLI表示・PRコメント・スコア・CIの失敗判定を個別に制御でき、手元に表示を残してCIの失敗判定から除外する設定もできます。既存コードに大量の指摘があるチームは、いきなりoffにせずsurfacesでCIの判定から外し、手元では見える状態を保つほうが負債を見失いません。1行だけ抑制するなら、直前の行に// react-doctor-disable-next-line react-doctor/no-derived-stateと書きます。
Claude Code・Cursorなどエージェントへの導入
npx react-doctor@latest installは、コーディングエージェント用のスキル/react-doctorを入れるコマンドです。手元でinstall --dry-run --yesを実行すると、検出したエージェント(この環境ではClaude Code・Codex・Gemini CLI・GitHub Copilot・Mistral Vibe・OpenCode・OpenHands)へのスキル配置に加えて、次の変更が予定として表示されました。
package.jsonにdoctorスクリプトを追加し、react-doctorを開発依存に入れる.git/hooks/pre-commitに、コミットを止めない診断(--staged --blocking warning)を入れる。Husky・Lefthookなど既存のフック管理があればそれを使う.github/workflows/react-doctor.ymlを作る
入るスキル(SKILL.md)の中身は「Reactのコードを変えたらnpx react-doctor@latest --verbose --scope changedを実行し、スコアが下がっていないか確かめる」という指示です。エージェントが書く前に防ぐのではなく、書いた直後に自分で検査させる仕組みだと理解しておくと期待値がずれません。編集のたびに結果を返すネイティブフック(Claude CodeとCursor)は既定で入らず、--agent-hooksを付けたときだけ入ります。Claude Codeで既存コードを調べる使い方はClaude Codeでソースコード解析する方法、Cursor側のルール管理は.cursorrulesとは?非推奨の現状と.cursor/rules(.mdc)への移行を参照してください。
注意点が1つあります。@latestは固定版ではなくnpmのlatestタグを指定しますが、取得時にはローカルのインストールやキャッシュが再利用される場合があります。サプライチェーンの観点で版を固定したいなら、installで開発依存に入れた版をnpm run doctorで使う運用に寄せてください。
GitHub Actionsによるプルリクエスト診断の設定
ci installが書くワークフロー
npx react-doctor@latest ci install --yesを実行すると、次の要点を持つ.github/workflows/react-doctor.ymlが生成されました(コメントは省略)。
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
push:
branches: ["main"]
permissions:
contents: read
pull-requests: write
issues: write
statuses: write
jobs:
react-doctor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: millionco/react-doctor@v2
Actionの既定はblocking: none(指摘してもチェックを落とさない)とscope: changedです。CLIの既定(blocking=error・scope=full)と逆なので、同じ感覚で設定すると「Actionでは落ちない」ことに驚きます。PRにはまとめのコメント1件、変更行へのインラインコメント、スコア付きのコミットステータスが付き、mainへのpushでは点数を記録するだけです。fetch-depth: 0を外した浅いチェックアウトで比較元コミットを取得できない場合は、変更ファイルの既存指摘まで報告されることがあります。
v1からv2で変わった入力
| v1 | v2 |
|---|---|
fail-on |
blocking |
annotations |
review-comments |
non-blocking: true |
blocking: none |
| (なし) | scope(既定 changed) |
node-version 既定22 |
既定24 |
既存のワークフローはnpx react-doctor@latest ci upgradeで書き換えられます。2026年春ごろの解説にはmillionco/react-doctor@mainにdiff: mainとgithub-tokenを渡す例がありますが、v2の入力一覧にはどちらもありません。
blockingと必須チェックによるマージ制御
チームが指摘の質に納得してから、npx react-doctor@latest ci config --blocking errorで失敗判定を有効にします。さらにGitHubの「Settings → Branches → Branch protection rules」でReact Doctorのチェックを必須にしないと、チェックが赤でもマージボタンは押せます。フォークからのPRには書き込み権限が無いため、診断は走ってもコメントは付きません。React製の業務アプリで品質基準づくりから開発まで任せたい場合は、業務用・Webアプリ開発の支援内容も参考にしてください。
ESLint・oxlintプラグインとReact Scanとの違い
oxlint-plugin-react-doctorとeslint-plugin-react-doctorの登録・設定
CLIを別に回さず、いつものリントの中でReact Doctorのルールを使いたいときは、2026年5月15日にnpmへ公開された2つのプラグイン(いずれも0.9.18)を使います。oxlintでは.oxlintrc.jsonのjsPluginsに登録します。
{
"jsPlugins": [{ "name": "react-doctor", "specifier": "oxlint-plugin-react-doctor" }],
"rules": {
"react-doctor/no-fetch-in-effect": "warn",
"react-doctor/no-derived-state": "warn"
}
}
ESLintではflat configにreactDoctor.configs.recommendedを足し、Next.jsならnext、React Nativeならreact-nativeのプリセットを重ねます。ただし秘密情報や設定ファイルを調べるsecurity-scan系のルールはプラグイン単体では動かず、Socket.devによる依存パッケージの検査(既定でスコア50未満を報告)もCLIだけの機能です。依存検査の仕組みはsocket.devとは?npm/PyPIのサプライチェーン攻撃を防ぐ仕組みと料金で解説しています。ESLintのflat config自体はESLintをVSCodeで使う設定手順を参照してください。
React Scanは実行時、React Doctorは静的解析が中心
同じ開発者のReact Scan(npm 0.5.7)は、動いているアプリの再レンダリングをブラウザ上で可視化するツールです。React Doctorはソースを読むだけで判定するので、実際に遅いかどうかまでは分かりません。ただし0.9.18にはnpx react-doctor@latest scan http://localhost:3000もあり、手元のChromeを一時プロファイルで開いてDevToolsのパフォーマンストレースを最大5分記録します。トレースはローカルに保存され、アップロードはされません。描画の無駄を数字で確かめたい場面ではこちらかReact Scan、書き方の問題を一律に拾う場面では通常のスキャン、と分けると重複しません。React CompilerやHooksの書き方が指摘の多くを占めるため、React Compilerとは?Vite・Next.js・Expoでの導入とReactフック(Hooks)とは?全18種の一覧も併せて読むと、指摘の理由を追いやすくなります。
古い手順の見分け方と導入を見送る場面
React Doctorは版の進みが速く、検索で見つかる手順の多くが古くなっています。次の記述を見たら、0.9.18では動かないか非推奨だと判断してください。
--fixや--prompt:v1発表時(2026年2月)の機能で、現行のCLIリファレンスにありませんcurl -fsSL https://react.doctor/install-skill.sh | bashやnpx skills add:現在はnpx react-doctor@latest installに一本化--diff:--scope changedの非推奨の別名- Actionの
fail-on・annotations・@main:v2のblocking・review-comments・@v2へ
導入を見送るべき場面もあります。まず、コードや診断結果を社外のAPIへ一切出せない閉域環境では、スコアという看板機能が使えません。件数管理で足りるなら導入する価値はありますが、点数をKPIにする計画なら成立しません。次に、ESLintのeslint-plugin-react-hooksとjsx-a11yを既に厳しく運用しているチームでは、指摘の多くが既存のリントと重なり、上乗せになるのはeffect系やフレームワーク固有の指摘、複雑な関数・重複JSXの検査、サプライチェーン検査などです。導入前に--scope full --blocking noneで1回走らせ、既存のリントで拾えていない指摘が何件あるかを数えてから決めるのが確実です。
React Doctorに関するよくある質問
React Doctorは無料で使えますか?
社内の開発やCIでの利用は無料です。ライセンスは改変MITで、AIの学習・評価データとしての利用と、React Doctorを主な価値とする有償サービスとしての提供には、Million Software, Inc.の書面許諾が必要です。
React DoctorのGitHubリポジトリはどこですか?
github.com/millionco/react-doctor です。CLI本体はpackages/react-doctorにあり、GitHub Actionのaction.ymlも同じリポジトリのルートに置かれています。ドキュメントはreact.doctor/docsで公開されています。
React Doctorとoxlintの関係は?
React Doctorは内部でoxlintを使ってルールを実行します。逆に、既にoxlintを使っているプロジェクトではoxlint-plugin-react-doctorを入れると、React Doctorのルールをoxlintの中で動かせます。その場合スコアと依存パッケージ検査は付きません。
npx react-native doctorとは別物ですか?
別物です。npx react-native doctorはReact Native CLIのコマンドで、Node.js・iOS・Androidの開発環境の不備を診断して直します。Expoのnpx expo-doctorもプロジェクトの既知の問題を調べるツールです。React Doctorはコードの書き方を検査するもので、React Nativeのプロジェクトにも使えます。Expoでは依存関係や設定の静的チェックも行いますが、ネイティブ開発環境全体を診断するツールの代替にはなりません。
設定ファイルの名前は何ですか?
doctor.config.ts・doctor.config.jsonなど、doctor.config.*の8形式のどれかです。package.jsonのreactDoctorキーでも構いません。同じディレクトリに複数あると最初に見つかった有効な1つだけが使われるので、1ディレクトリ1ファイルにしてください。