New
Introducing React Bench, see how different models perform on React code

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.

KeyTypeDefaultPurpose
ignore.rulesstring[][]Drop matching rule diagnostics after linting
ignore.filesstring[][]Exclude matching files from scanning
ignore.overrides{ files, rules? }[][]Drop diagnostics for matching files or rules
lintbooleantrueEnable lint diagnostics
supplyChain{ enabled?, minScore?, severity?, includeDevDependencies? }{ enabled: true, minScore: 50, severity: "error", includeDevDependencies: true }Configure Socket.dev checks for direct dependencies
deadCodebooleantrueRun dead-code analysis (skipped in partial and staged scans)
warningsbooleantrueSurface warning-severity diagnostics
verbosebooleanfalseShow more detail
scope"full" | "files" | "changed" | "lines"fullChoose how much source to scan and report
basestringSet the git ref used by partial scopes
blocking"error" | "warning" | "none"errorSeverity that fails CI (exits non-zero)
customRulesOnlybooleanfalseRun only configured custom rules
sharebooleantrueEnable share URL behavior
noScorebooleanfalseSkip the score API
textComponentsstring[][]React Native text component aliases
rawTextWrapperComponentsstring[][]React Native string wrapper components
runtimeGlobalsstring[][]Runtime JSX globals that are not imported in the current file
serverAuthFunctionNamesstring[][]Accepted server auth guard names
respectInlineDisablesbooleantrueRespect inline lint disables
adoptExistingLintConfigbooleantrueMerge existing JSON lint config
rootDirstringScan a different directory, resolved relative to the config file
projectsstring[]Scan and score each listed project separately
ignore.tagsstring[][]Disable rule families by tag before linting
rulesobject

Set rule severity to error, warn, or off

categoriesobject

Set category severity to error, warn, or off

bucketsobject

Set severity for curated buckets such as compiler-cleanup

surfacesobjectControl visibility on CLI, score, PR comments, and CI failure
pluginsstring[][]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 design

React 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 project
  • files: every finding in changed files
  • changed: only findings introduced compared with the base
  • lines: 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.