mech.app
Dev Tools

React Doctor: Static Analysis for Agent-Generated Code

How React Doctor catches the anti-patterns AI coding agents produce that traditional linters miss, and what that means for quality gates.

Source: github.com
React Doctor: Static Analysis for Agent-Generated Code

AI coding agents write code that compiles and often runs, but they consistently produce anti-patterns that human developers would catch in review. React Doctor is a static analysis tool built specifically to detect these patterns. It sits between your agent’s output and your codebase, enforcing rules that ESLint and TypeScript can’t express because they assume human authorship.

The gap is real. Agents hallucinate prop names, create unnecessary state, and generate deeply nested ternaries that pass type checking but fail maintainability. Traditional linters optimize for catching syntax errors and enforcing style guides. They don’t model the specific failure modes of LLM-generated code.

What Agents Get Wrong

AI coding agents fail in predictable ways when generating React:

Prop hallucination. Agents invent props that don’t exist on components, especially when working with third-party libraries. TypeScript catches type mismatches, but agents often generate props that are close enough to real ones that they slip through.

State over-creation. Agents default to useState for every piece of data, even when props or derived values would suffice. This creates unnecessary re-renders and complicates state management.

Effect abuse. Agents reach for useEffect to solve synchronization problems that don’t require effects. They create dependency arrays that are either incomplete or over-specified.

Ternary nesting. Agents generate deeply nested conditional rendering that is syntactically valid but unreadable. Human developers would extract these into variables or helper functions.

Key misuse. Agents use array indices as keys in lists or generate non-stable keys that cause reconciliation bugs.

These patterns share a common trait: they emerge from the agent’s training on code snippets rather than maintained codebases. The agent optimizes for “code that looks right” rather than “code that stays maintainable.”

Architecture

React Doctor runs as a standalone CLI tool that analyzes JSX and TSX files. It parses code into an AST using Babel, then applies a set of heuristic rules designed to catch agent-specific anti-patterns.

import { parse } from '@babel/parser';
import traverse from '@babel/traverse';

// Example: Detect useState overuse
function detectUnnecessaryState(ast) {
  const stateVars = new Set();
  const derivableVars = new Set();
  
  traverse(ast, {
    CallExpression(path) {
      if (path.node.callee.name === 'useState') {
        const [id] = path.parent.id.elements;
        stateVars.add(id.name);
      }
    },
    VariableDeclarator(path) {
      if (isDerivedFromProps(path.node.init)) {
        derivableVars.add(path.node.id.name);
      }
    }
  });
  
  return [...stateVars].filter(v => derivableVars.has(v));
}

The tool outputs violations with line numbers and suggested fixes. It integrates into CI pipelines as a quality gate or runs in pre-commit hooks to block agent-generated code before it reaches the repository.

Rule Categories

React Doctor organizes checks into categories that map to agent failure modes:

CategoryExample RuleWhy Agents Fail
PropsDetect undeclared propsHallucinate based on similar component APIs
StateFlag derivable stateDefault to useState without considering data flow
EffectsIdentify missing dependenciesGenerate partial dependency arrays from context
RenderingLimit ternary depthOptimize for brevity over readability
KeysRequire stable keysUse array indices as quick solution

Each rule includes a severity level and an auto-fix suggestion when possible. The tool can run in fix mode to automatically apply safe corrections.

Integration Surface

React Doctor exposes three integration points:

CLI for CI gates. Run react-doctor check src/ in your CI pipeline. Exit code 1 blocks the merge if violations exceed a threshold. This works for any agent that commits code to a branch.

Pre-commit hooks. Install as a Git hook to validate code before it reaches the remote. This catches issues earlier but requires the agent to have local Git access.

Real-time feedback during generation. The most advanced integration runs React Doctor as the agent generates code, feeding violations back into the agent’s context. This requires the agent to support tool calls or structured output.

# .github/workflows/agent-quality.yml
- name: Check agent-generated code
  run: |
    npx react-doctor check --agent-mode \
      --severity error \
      --output github-annotations

The --agent-mode flag adjusts thresholds and messaging for automated code. It assumes the code was generated rather than hand-written, which changes how certain patterns are scored.

Heuristics vs. Rules

Traditional linters use explicit rules: “no unused variables,” “prefer const over let.” React Doctor adds heuristics that score code based on patterns common in agent output.

Complexity scoring. Agents generate code with high cyclomatic complexity because they don’t refactor. React Doctor flags functions above a threshold and suggests extraction.

Naming entropy. Agents use generic names like data, result, temp. The tool measures naming diversity and flags components with too many generic identifiers.

Import clustering. Agents import the same library multiple times or use inconsistent import styles. React Doctor detects these and suggests consolidation.

These heuristics produce false positives on human code, which is why the tool includes an --agent-mode flag. When enabled, it assumes the code was generated and adjusts scoring accordingly.

Failure Modes

React Doctor catches static patterns but can’t detect runtime issues:

Logic errors. The tool doesn’t validate business logic. An agent can generate syntactically correct code that implements the wrong behavior.

Performance problems. React Doctor flags obvious performance issues like missing memoization, but it doesn’t profile or benchmark.

Accessibility gaps. The tool includes basic a11y checks, but it can’t validate semantic HTML or ARIA usage comprehensively.

Context-dependent bugs. Some agent mistakes only appear in specific runtime contexts. Static analysis can’t catch these without symbolic execution.

The tool also assumes the agent generates valid JavaScript. If the agent produces syntax errors, React Doctor’s parser will fail before analysis begins.

Deployment Shape

React Doctor runs as a Node.js CLI. It requires no external services and stores no data. The typical deployment:

  1. Install as a dev dependency: npm install -D react-doctor
  2. Add a script to package.json: "check:agent": "react-doctor check src/"
  3. Run in CI after agent commits code
  4. Optionally configure auto-fix for safe violations

For teams using agent-in-the-loop workflows, React Doctor can run as a validation step before presenting code to the developer. This reduces review burden by catching obvious issues automatically.

Technical Verdict

Use React Doctor when:

  • You have AI coding agents committing React code to your repository
  • You need quality gates beyond TypeScript and ESLint
  • You want to catch agent-specific anti-patterns before code review
  • You’re building agent workflows that need automated quality feedback

Avoid it when:

  • Your codebase is entirely human-authored (use standard linters)
  • You need runtime validation or performance profiling
  • Your agents generate non-React code (tool is React-specific)
  • You require zero false positives (heuristics trade precision for coverage)

React Doctor fills a gap in the agent development lifecycle. As coding agents become standard tools, quality gates must evolve to catch the patterns they produce. This tool represents an early attempt at that evolution. It won’t replace human review, but it reduces the surface area reviewers need to check.