Config files
Configure React Doctor with a doctor.config.* file or the reactDoctor key in package.json. This page explains where React Doctor looks, which config wins, and how each common option changes a scan.
Where React Doctor looks
React Doctor starts in the scanned directory and walks up until it reaches .git or a monorepo root. Config files can use .ts, .mts, .cts, .js, .mjs, .cjs, .json, or .jsonc. You can also put the same object under reactDoctor in package.json.
Use one config per directory. If more than one exists, React Doctor uses the first valid config it finds and ignores lower-priority fallbacks. Local config wins over ancestor config.
JSON config files use JSON5, so comments and trailing commas are allowed. Add $schema: "https://react.doctor/schema/config.json" for editor autocomplete.
Command-line flags override config values.
Example config file
// doctor.config.ts
import { defineConfig } from "react-doctor/api";
export default defineConfig({
ignore: {
rules: ["react-doctor/no-danger"],
files: ["src/generated/**"],
overrides: [
{
files: ["components/search/HighlightedSnippet.tsx"],
rules: ["react-doctor/no-danger"],
},
],
},
rules: {
"react-doctor/no-array-index-as-key": "error",
},
categories: {
Maintainability: "warn",
},
});Use doctor.config.json for JSON config:
{
"$schema": "https://react.doctor/schema/config.json",
"ignore": {
"rules": ["react-doctor/no-danger"],
"files": ["src/generated/**"],
"overrides": [
{
"files": ["components/search/HighlightedSnippet.tsx"],
"rules": ["react-doctor/no-danger"]
}
]
},
"rules": {
"react-doctor/no-array-index-as-key": "error"
},
"categories": {
"Maintainability": "warn"
}
}Common keys
Use these keys to control scan scope, rule severity, output surfaces, and project-specific escape hatches.
| Key | Type | Default | Purpose |
|---|---|---|---|
ignore.rules | string[] | [] | Drop matching rule diagnostics after linting |
ignore.files | string[] | [] | Exclude matching files from scanning |
ignore.overrides | { files, rules? }[] | [] | Drop diagnostics for matching files or rules |
lint | boolean | true | Enable lint diagnostics |
supplyChain | { enabled?, minScore?, severity?, includeDevDependencies? } | { enabled: true, minScore: 50, severity: "error", includeDevDependencies: true } | Configure Socket.dev checks for direct dependencies |
deadCode | boolean | true | Run dead-code analysis (skipped in partial and staged scans) |
warnings | boolean | true | Surface warning-severity diagnostics |
verbose | boolean | false | Show more detail |
scope | "full" | "files" | "changed" | "lines" | full | Choose how much source to scan and report |
base | string | Set the git ref used by partial scopes | |
blocking | "error" | "warning" | "none" | error | Severity that fails CI (exits non-zero) |
customRulesOnly | boolean | false | Run only configured custom rules |
share | boolean | true | Enable share URL behavior |
noScore | boolean | false | Skip the score API |
textComponents | string[] | [] | React Native text component aliases |
rawTextWrapperComponents | string[] | [] | React Native string wrapper components |
runtimeGlobals | string[] | [] | Runtime JSX globals that are not imported in the current file |
serverAuthFunctionNames | string[] | [] | Accepted server auth guard names |
respectInlineDisables | boolean | true | Respect inline lint disables |
adoptExistingLintConfig | boolean | true | Merge existing JSON lint config |
rootDir | string | Scan a different directory, resolved relative to the config file | |
projects | string[] | Scan and score each listed project separately | |
ignore.tags | string[] | [] | Disable rule families by tag before linting |
rules | object | Set rule severity to | |
categories | object | Set category severity to | |
buckets | object | Set severity for curated buckets such as | |
surfaces | object | Control visibility on CLI, score, PR comments, and CI failure | |
plugins | string[] | [] | Load custom oxlint-shaped rule plugins |
Severity overrides use error, warn, or off. Per-rule rules entries win over categories; buckets currently supports compiler-cleanup for React Compiler cleanup rules.
Category overrides use the five buckets: Security, Bugs, Performance, Accessibility, and Maintainability.
Use rules or categories when you want to change severity or stop a rule from running. Use ignore.rules when you want the rule to run but drop its diagnostics from the final report. Use surfaces when you want a diagnostic to stay visible locally but disappear from PR comments, the score, or the CI failure gate.
Configure rules from the CLI
Use the rules commands when you want React Doctor to edit the active config file for you:
npx react-doctor@latest rules list
npx react-doctor@latest rules explain react-doctor/no-array-index-as-key
npx react-doctor@latest rules disable react-doctor/no-array-index-as-key
npx react-doctor@latest rules set react-doctor/no-danger warn
npx react-doctor@latest rules category Performance off
npx react-doctor@latest rules ignore-tag designReact Doctor accepts a full rule key, a bare rule ID, or a legacy key. It updates the existing doctor.config.* or package.json config. When no config exists, it creates doctor.config.json with the schema URL.
Rule-level settings override category settings. Ignored tags disable matching rules before linting, so a rule-level setting cannot re-enable a tag-ignored rule. Surface controls change visibility without disabling the rule.
Configure scan scope and blocking
Use scope to choose which findings React Doctor reports:
full: every finding in the projectfiles: every finding in changed fileschanged: only findings introduced compared with the baselines: findings whose source range touches a changed line
Set base when React Doctor should compare against a specific git ref. The CLI --scope and --base flags override these values. The older diff option remains a deprecated alias.
blocking controls the process exit code. Use error to fail on errors, warning to fail on any finding, or none for an advisory scan. The CLI defaults to error; the GitHub Action defaults to none.
Configure dependency checks
The supply-chain check scores direct dependencies through Socket.dev. It runs by default and reports a dependency when its supply-chain or vulnerability score falls below 50.
{
"supplyChain": {
"enabled": true,
"minScore": 60,
"severity": "warning",
"includeDevDependencies": false
}
}React Doctor skips this network check in staged and editor scans. In a partial branch scope, it runs only when package.json changed. Set enabled: false or pass --no-supply-chain to disable it.
Per-project scoring in monorepos
Use projects in the root config when you always want a separate score per module, without passing --project on every run:
{
"projects": ["modules/billing", "modules/payroll"]
}Entries resolve the same way as --project values: workspace package names first, then directory paths relative to the scanned root. "*" selects every discovered workspace project. Invalid entries fail the run with the same error as the flag.
Precedence: an explicit --project flag overrides this list. Only the config at the invocation root is consulted; projects inside a module's own config is ignored.
In multi-project scans, each module's own doctor.config.* layers additively onto the root config: rules and categories merge per key, and ignore lists union. A module can override one rule without discarding the shared base.
React Native escape hatches
Use textComponents for components that behave like React Native's <Text>:
{
"textComponents": ["Typography", "NativeTabs.Trigger.Label"]
}Use rawTextWrapperComponents for components that route string children through an internal text component:
{
"rawTextWrapperComponents": ["Button"]
}Server auth guards
Use serverAuthFunctionNames when your server actions use custom auth helpers:
{
"serverAuthFunctionNames": ["requireWorkspaceMember", "ensureSignedIn"]
}Existing lint config
React Doctor can adopt JSON ESLint and oxlint config automatically. Set adoptExistingLintConfig: false if you want React Doctor to ignore existing lint config.
Narrow ignores and suppressions
Use the narrowest control that solves the problem. Ignore a rule everywhere only when it does not apply to your project:
{
"ignore": {
"rules": ["react-doctor/no-danger"]
}
}Ignore generated files when every diagnostic in those files is noise:
{
"ignore": {
"files": ["src/generated/**"]
}
}Ignore one rule in specific files when the exception is local:
{
"ignore": {
"overrides": [
{
"files": ["components/search/HighlightedSnippet.tsx"],
"rules": ["react-doctor/no-danger"]
}
]
}
}Use an inline suppression when the exception should live with the code:
// react-doctor-disable-next-line react-doctor/no-derived-state
useEffect(() => {
setValue(initialValue);
}, []);Comma-separate rule names when one line needs more than one suppression. Use npx react-doctor@latest why src/App.tsx:42 when a suppression does not apply.
Custom rule plugins
React Doctor can run custom oxlint-shaped plugins from your config. Plugin rules are opt-in and use the same CLI, score, PR comment, and CI surfaces as built-in rules.
{
"plugins": ["./lint/team-conventions.cjs"],
"rules": {
"team-conventions/no-bare-fetch": "error"
}
}For the plugin module shape, Node API path, and limits, see Add custom rules.