best-of

AI Code Review for Legacy Codebases: What Actually Works

Legacy code breaks the assumptions AI reviewers are built on. The ratchet tactic, exact suppression filenames, exclusion patterns and language gaps that decide it.

Published:

Last Updated:

Direct answer

Legacy code breaks the assumption every AI reviewer is built on. These tools are trained to flag deviation from idiomatic modern practice, and a 15-year-old codebase deviates everywhere, so the default configuration produces a wall of findings that is technically correct and operationally useless. The fix is not a better model. It is a ratchet: baseline the existing findings, gate only the diff, and exclude generated and vendored paths before the first run. Verified 2026-10-18.

Best AI code review tools for legacy codebases

Direct answer: Choose on three mechanisms, not on a leaderboard: can the tool baseline existing findings and gate only the diff, does it cover your languages, and does it reach your forge. SonarQube owns the first with Clean as You Code. CodeRabbit and DeepSource own the configuration surface. Greptile owns whole-repo context. Verified 2026-10-18.

Here is the comparison that matters for old code. Every other legacy roundup compares the same general-purpose feature grid; the columns below are the ones that decide whether the tool survives contact with a repository that predates your current framework.

ToolBaseline / new-code gatingConfig fileLegacy-relevant strengthKnown limit on legacy workPrice (verified 2026-10-18)
SonarQubeYes, first class. Clean as You Code with new code defined as previous version, number of days (default 30, max 90) or reference branchsonar-project.properties plus server-side quality gateThe only mature baseline model in wide deployment; core SAST engine runs fully on-premCommunity Build cannot analyze pull requests and excludes C, C++, Swift, Dart, T-SQL, PL/SQL. AI features are Enterprise tierCommunity Build free; Developer Edition is the minimum for branch and PR analysis
CodeRabbitNo native baseline. Diff-scoped by design.coderabbit.yamlRichest exclusion and instruction surface: reviews.path_filters, reviews.path_instructions, reviews.auto_review.base_branches150 files per review on Free and Essentials, 300 on Team and above. Essentials covers 1 linked repositoryEssentials $24/dev/mo annual, Team $48, Advanced $72
DeepSourcePartial. Deterministic static analysis runs before the AI agent sees the code.deepsource.tomlexclude_patterns and test_patterns separate “ignore entirely” from “analyze with different rules”, which is exactly the legacy distinctionAI review billed separately: $8 per 10K processed LOC Standard, $15 Advanced. Acquired by Harness 9 Sept 2026Team approximately $24/dev/mo plus AI metering
GreptileNoRepo settings plus natural-language rulesIndexes the whole repository rather than reading the diff alone. Documents Bitbucket Data Center, Gitea and Perforce with P4 Code ReviewNo Azure DevOps. Credits are per author and do not pool. Apex depth costs 10 credits per reviewPro $30/seat/mo, 50 credits included, $1 per extra credit
Claude Code reviewVia instruction files onlyREVIEW.md read from the base branch, plus CLAUDE.mdPath-scoped subdirectory REVIEW.md files; multi-agent topology with a verification step that tries to disprove each findingFails closed: if branch protection cannot be confirmed it reads no instruction files at all. Never approves or blocks. Unavailable with ZDR, the HIPAA configuration or CMEKClaude Team and Enterprise only. GA 15 Oct 2026
Cursor BugbotNo.cursor/BUGBOT.md plus .cursor/config/bugbot.yamlreview.incremental and triggers.frequency (everyPush or oncePerPr) keep cost down on long-lived legacy branchesNo longer a standalone product; usage billing from the Cursor Premium plan ($30/mo) upwardApproximately $1.00 to $1.50 per review
SemgrepVia .semgrepignore and diff-aware scanning.semgrep.yml, .semgrepignoreCustom rules let you encode the house patterns a 15-year-old codebase actually usesCross-file taint is proprietary only and covers just 8 languages. Rule maturity is 20 GA, 2 beta, 19 experimentalFree tier: 10 contributors, 10 private repos. Code $30/contributor/mo
GitarN/A (migration tool, not a gate)Platform connection configBuilt specifically around automated migration at scale: fix, commit, run CI, commit only on green, with automatic repair if its own fix breaks the buildDoes not support GitHub Enterprise Server. No published third-party benchmark. Paid sponsor of this siteCore $20/user/mo annual, Pro $40, both capped at 50 users
CodeSceneHotspot trends rather than a pass/fail baselineProject configurationBehavioural analysis over version-control history: change coupling and hotspots are legacy-native conceptsWe did not verify current CodeScene pricing in this sessionNot verified 2026-10-18

Two things the table will not tell you, so I will.

There is no benchmark that measures performance on old code. SWE-PRBench, CR-Bench, CRBugBench and c-CRAB all sample modern open-source pull requests, and none of them breaks results out by codebase age, language or framework vintage. Anybody telling you tool X is best for legacy is reasoning from architecture, as I am here, or selling you something.

No vendor publishes per-language precision or recall for its own product. The closest thing to capability evidence is CodeRabbit’s published language-to-linter map, which wires in more than 50 underlying tools including Squawk for Postgres migrations, Verilator and zizmor, and which has two gaps that matter on legacy stacks: no Python type checker, and no Error Prone or SpotBugs for Java. Greptile’s published claim is “All languages supported”, which is unfalsifiable. Qodo, Gitar, Cursor Bugbot, Anthropic and GitHub Copilot publish no language list at all.

Why legacy codebases break AI reviewers

Direct answer: AI reviewers are trained to flag deviation from idiomatic modern practice. A 15-year-old codebase deviates everywhere by construction, so the default configuration returns thousands of accurate findings about decisions nobody is revisiting. The tool is not wrong. It is answering a question you did not ask. Verified 2026-10-18.

Run a modern reviewer across a 2011 Java service and it will tell you about raw types, mutable static state, checked exceptions wrapped and swallowed, string concatenation in loops, and a DAO layer that predates the ORM you now use. Every one of those is a real observation. None of them is a reason to block the pull request that fixes a null check in the billing path.

The failure mode is specific and worth naming precisely:

  1. Volume collapses attention. A reviewer who sees 200 comments reads none of them. Our own measurement of large pull requests found that scrutiny per line falls 18-fold as diffs grow, and 52% of merged pull requests over 1,000 lines carried zero inline review comments. See how big should a pull request be for the full dataset. Dumping machine findings on top of that does not help; it accelerates the collapse.
  2. Correct findings crowd out urgent ones. A genuine SQL injection sitting at position 147 in a list of style observations is functionally invisible.
  3. The team learns to ignore the bot. This is irreversible within the tenure of most engineering managers. The first week of output sets the policy for the next year, which is why the configuration you ship on day one matters more than the model you picked.

The second-order problem is that legacy codebases contain intentional deviation. The weird retry loop exists because an upstream system returns 200 on failure. The duplicated constant exists because the shared module is owned by a team that was disbanded. An AI reviewer has no access to either fact, and no amount of prompt engineering invents it. What it can read is a file you commit, which is why the instruction-file mechanics below are the real product surface on legacy work.

AI code review for legacy codebases

Direct answer: The single most useful adoption tactic is the ratchet. Baseline every existing finding as accepted debt, measure nothing against it, and gate only issues introduced by the diff under review. SonarQube’s Clean as You Code is the mature expression of this. Most legacy guides omit it entirely. Verified 2026-10-18.

Here is the model in one sentence: you are not cleaning the codebase, you are stopping it getting worse, and the difference is the only thing that makes the project finishable.

Sonar’s own documentation puts the rationale plainly: “When you add new code to your projects, you usually touch a portion of the old code in the process. As a consequence, analyzing and cleaning new code allows you to fix issues in your old code and gradually improve the overall quality of your codebase” (Clean as You Code introduction, verified 2026-10-18).

The new code definition is configurable three ways, and the choice has real consequences on a legacy repo:

New code definitionHow it behavesBest fit on legacy code
Previous versionAnything changed since the last version increment counts as newLong release trains, quarterly shipping, codebases with real version tags
Number of daysAnything changed in the last X days counts as new. Default 30, maximum 90Continuous delivery, trunk-based teams, no meaningful version boundary
Reference branchDifferences between your branch and a named reference branch count as newPull request gating. This is the one you want if review is the use case

Two hard constraints that kill the obvious plan. First, Sonar’s documentation states that Developer Edition is the minimum required for branch analysis and pull request analysis, and that SonarQube Community Build cannot analyze pull requests. Second, SonarQube Cloud’s free tier does include pull request analysis, up to 50k LOC on private projects, with no expiry. Those two products get conflated constantly. If you want a free baseline-and-gate on a private legacy repo, Cloud is the path and Community Build is not. See SonarQube Community vs Developer and is SonarQube free for the full boundary.

If you are not on Sonar, you can build the same ratchet by hand in three steps:

  1. Run the tool once across the whole repository and export the findings to a committed baseline file.
  2. In CI, run the tool against the diff only and subtract anything whose fingerprint matches the baseline.
  3. Fail the build on the remainder, above a severity floor you choose.

It is unglamorous and it works. The reason to prefer a product that does it natively is fingerprint stability: hand-rolled baselines break the moment a file is reformatted, and legacy repos get reformatted.

AI code review tools for legacy codebases

Direct answer: Suppression is per tool and per exact filename, and the files are not interchangeable. CodeRabbit uses .coderabbit.yaml, DeepSource uses .deepsource.toml, Cursor Bugbot uses .cursor/BUGBOT.md, and Anthropic Code Review uses REVIEW.md read from the base branch, which fails closed if branch protection cannot be confirmed. Verified 2026-10-18.

This is the section most guides skip, and it is the one you will actually use on a Monday morning.

ToolExact file pathKey mechanism for suppression or scopingGotcha
CodeRabbit.coderabbit.yamlreviews.path_filters takes glob patterns with a leading ! to exclude. reviews.path_instructions attaches per-path guidance. reviews.auto_review.base_branches accepts regex for non-default branchesBy default knowledge_base.code_guidelines.filePatterns also reads **/REVIEW.md, **/CLAUDE.md, **/AGENTS.md, **/.cursorrules, .github/copilot-instructions.md, **/GEMINI.md and **/.windsurfrules. On a legacy monorepo with years of abandoned agent files, that is a noise source, not a feature
DeepSource.deepsource.tomlexclude_patterns removes files from analysis entirely. test_patterns keeps them analyzed under relaxed rules. [[analyzers]] blocks are per languageThe two arrays are not synonyms. Use exclude_patterns for generated and vendored code, test_patterns for your actual suite. Full syntax in our DeepSource TOML configuration guide
Cursor Bugbot.cursor/BUGBOT.mdNatural-language project rules, resolved with upward directory traversal. .cursor/config/bugbot.yaml holds triggers.drafts, triggers.frequency (everyPush or oncePerPr), review.effort, review.incrementalThe path is .cursor/BUGBOT.md, not a bare root BUGBOT.md. On a long-lived legacy branch, set triggers.frequency: oncePerPr or you pay per push
Anthropic Code ReviewREVIEW.mdRead from the base branch, never from the pull request’s own diff, so a pull request cannot alter the rules it is judged by. Subdirectory REVIEW.md files add path-scoped checksSeverity lowering, path exclusion and nit capping additionally require the root file to sit on a protected default branch. If protection cannot be confirmed, it reads no instruction files at all. The local /code-review command reads CLAUDE.md but not REVIEW.md
Qodo Merge.pr_agent.toml[review_agent].inline_comments_severity_threshold is a severity rank of 1 to 3. Also comments_location_policy and per-tier comments_routingIt is a severity rank, not a confidence score. Raising it does not make the tool more certain, only more selective
Semgrep.semgrepignore, rule-level paths:Per-rule include and exclude globs; nosemgrep inline comments.semgrepignore semantics differ from .gitignore in edge cases. Cross-file taint needs the Pro engine, which is proprietary only

The Anthropic fail-closed behaviour deserves a flag of its own, because it is the one that will surprise you. On a legacy repo where the default branch is not protected, which is common on internal systems that never got the governance treatment, Anthropic Code Review will read none of your instruction files and review the diff with defaults. That is the exact scenario where you most need the instructions. Protect the branch first, then write the file. More on the product in our Claude Code review guide.

Dead code, vendored dependencies and generated files

Direct answer: Exclude them before the first run, not after. In our own sample of 80 merged pull requests over 1,000 changed lines, 42.1% of all changed lines sat in generated, vendored or lockfile paths. On a legacy repository the share is usually higher, and those paths will dominate findings if you let them. Measured 2026-10-18.

The categories, in the order they will hurt you:

Vendored dependencies. vendor/, third_party/, node_modules/ checked in, lib/ directories holding a 2014 copy of a library with the version string edited. Every one of these will produce findings you cannot act on, because fixing them breaks your ability to re-vendor.

Generated code. Protobuf stubs, ORM scaffolding, OpenAPI clients, parser output, .designer.cs files, migration files. The signature is that the fix belongs in the generator, not the output. Mark these with linguist-generated in .gitattributes so GitHub collapses them in the diff view, then exclude the same globs in the tool. Do both: the .gitattributes entry helps the human, the tool exclusion helps the bot.

Dead code. This is the hard one, because you cannot glob it. A 15-year-old codebase is typically 10 to 30 percent unreachable, and no reviewer, human or machine, can tell dead code from live code by reading a diff. The practical answer is coverage data: if a file has zero production coverage over 90 days and zero test coverage, treat findings in it as informational. This is also the one category where CodeScene-style behavioural analysis over version-control history earns its place, because a file nobody has touched in six years is a different risk object from one touched weekly.

Test fixtures. Hardcoded credentials in test data, enormous JSON blobs, snapshot files. Use test_patterns in DeepSource rather than exclude_patterns here. You want the tests analyzed, just under different rules.

A workable starting exclusion set for a legacy repository, expressed as CodeRabbit path filters:

reviews:
  path_filters:
    - "!**/vendor/**"
    - "!**/third_party/**"
    - "!**/node_modules/**"
    - "!**/*.pb.go"
    - "!**/*_pb2.py"
    - "!**/*.designer.cs"
    - "!**/migrations/**"
    - "!**/*.min.js"
    - "!**/package-lock.json"
    - "!**/yarn.lock"
    - "!**/Gemfile.lock"
  path_instructions:
    - path: "legacy/**"
      instructions: "Flag only correctness, security and data-loss issues. Do not comment on style, naming, or modernisation opportunities in this tree."

That second block is the important half. Exclusion removes a path from review; path instructions keep it reviewed but narrow the question. On legacy code you usually want the second, because the old tree is exactly where the expensive bugs live. More tuning detail in how to reduce CodeRabbit noise and our monorepo configuration guide.

Does full-repo indexing help on legacy code?

Direct answer: Architecturally it should, and empirically nobody has proved it on old code. Greptile indexes the whole repository rather than reading the diff alone, which fits legacy work where the relevant call site is rarely adjacent. But SWE-PRBench found model performance degrades as context grows. We report the tension rather than resolving it. Verified 2026-10-18.

The argument for indexing on legacy code is strong and simple. A change to a 15-year-old module is dangerous precisely because of what calls it, and the caller is usually not in the diff. A diff-only reviewer sees a function signature change and approves it. A repository-aware reviewer sees the three call sites in a module nobody has opened since 2017.

The counter-evidence is real and comes from the most credible independent source in this market. SWE-PRBench (arXiv 2603.26130, 350 human-annotated pull requests, LLM-as-judge validated at kappa 0.75) found that performance degrades with more context, an attention dilution effect, and reported 8 frontier models at only 15 to 31 percent detection on diff-only review. It is also the only benchmark publishing a per-model false-positive rate: Claude Sonnet 4.6 lowest at 0.227, Llama 3.3 70B highest at 0.417.

Those two statements are less contradictory than they look. Indexing and retrieval is not the same thing as stuffing context into a prompt. A retrieval system that pulls three relevant call sites is doing something different from a harness that pastes 200 files into a window. But the honest position is that the distinction is architectural rather than measured: no published benchmark compares a retrieval-augmented reviewer against a diff-only reviewer on the same pull requests. If a vendor tells you indexing wins, ask which study.

For the practical implication on legacy repos specifically, see our guide to AI code review on a large codebase.

AI code review tools for legacy applications

Direct answer: Legacy applications usually live on legacy infrastructure, and forge support eliminates tools faster than quality does. Greptile is the only reviewer documenting Perforce with P4 Code Review. Gitar does not support GitHub Enterprise Server. Codacy’s AI Reviewer is cloud-and-GitHub-only, so GHES customers structurally cannot get it. Verified 2026-10-18.

This is the section where a legacy buyer saves a week. Before you evaluate review quality, check whether the product can see your code at all.

PlatformWho documents supportWho does not
GitHub Enterprise ServerAnthropic Code Review (supports GHES), Kodus, GitLab-adjacent self-hosted optionsGitar lists GHES as unsupported on its own platform matrix. GitHub Copilot code review does not support GHES. Codacy AI Reviewer is cloud-and-GitHub-only; GHES needs Codacy Self-hosted, which does not include the AI Reviewer
Perforce (P4)Greptile, with P4 Code Review. The only tool in our matrix documenting PerforceEveryone else
Bitbucket Data CenterGreptile, GitarSeveral AI-first reviewers are Bitbucket Cloud only
Azure DevOps Server (on-prem)Gitar covers Azure DevOps Services and ServerGreptile does not support Azure DevOps at all
AWS CodeCommitGitar, in previewMost
GitLab self-managedGitar (including GitLab Free), Kodus, GitLab Duo itselfTools built GitHub-first

Two further constraints specific to old enterprise estates:

Air gap. SonarQube AI CodeFix is the strongest documented air-gap plus bring-your-own-model combination we have found, described in Sonar’s docs as designed to operate without outbound internet access, with Ollama, LiteLLM and vLLM named. GitLab Duo Code Review reached GA for self-hosted models in GitLab 18.4. Note that Semgrep’s Network Broker and Snyk Broker are tunnels to the vendor’s cloud, not on-prem deployments - a distinction that matters enormously on a legacy estate that cannot egress.

Compliance configuration. Anthropic Code Review is unavailable to organisations with zero data retention, the HIPAA configuration, or CMEK. The exact configuration that makes Claude Code eligible for PHI disables Code Review. On an old healthcare or financial system, that is often the end of the evaluation.

Static analysis rules for legacy codebases

Direct answer: Start from a deliberately small rule set, not the vendor default. Enable correctness, security and data-loss rules across the whole repository; enable style, complexity and modernisation rules only on new code. On a 15-year-old codebase the default rule set is a denial-of-service attack on your reviewers. Verified 2026-10-18.

A rule-selection policy that survives contact with old code:

Tier 1, repository-wide, blocking. Injection, deserialisation, hardcoded secrets, path traversal, null dereference on a public entry point, resource leaks, unchecked external input. These are worth fixing in code you will never otherwise touch, because an attacker does not care how old the file is.

Tier 2, new code only, blocking. Cyclomatic complexity thresholds, function length, duplicate blocks, missing error handling, type-safety rules. These are the ratchet. The old code fails them all and that is accepted; the diff must pass.

Tier 3, informational, never blocking. Naming conventions, modernisation suggestions (“use a record here”), import ordering, documentation coverage. On legacy code these generate the largest volume and the least value. If you want them, run them on a quarterly report, not in the merge path.

Tier 4, disabled. Anything that fires more than a few hundred times repository-wide on first run and is not in Tier 1. A rule with 4,000 hits is not a rule, it is a property of the codebase, and you should record it as technical debt rather than as findings.

For safety-critical legacy C, this maps onto an existing standard rather than a bespoke policy: see our worked examples of MISRA C:2012 rules. MISRA’s own deviation process is, in effect, a formalised version of Tier 4, and it is worth borrowing the vocabulary even if you are not bound by the standard.

One operational rule that applies to every tier: measure the rule set by how many findings get fixed, not by how many get raised. If your fix rate on Tier 2 is under 20 percent, the tier is too wide. Our noise index methodology covers how we score that, and AI code review tools with low false positives covers which products have the best published evidence.

Best static analysis tool for a legacy codebase

Direct answer: SonarQube if you need the baseline model and your languages are covered, and Developer Edition or Cloud rather than Community Build if you need pull request analysis. Semgrep if your value is in custom rules encoding house patterns. DeepSource if you want deterministic analysis to run before an AI layer. Verified 2026-10-18.

ScenarioPickWhyWhat to watch
Multi-language enterprise estate, needs a baselineSonarQube Developer Edition or CloudClean as You Code is the only mature new-code gate in wide deployment; core SAST runs fully on-premCommunity Build cannot analyze pull requests. AI agents (Vortex, Remediation, Hunter) are Enterprise-only and trigger above 50 developers
C or C++ codebaseNot SonarQube Community BuildC and C++ are excluded from Community Build entirelyBudget for a commercial edition or a dedicated C/C++ analyzer from the outset
Oracle or SQL Server stored-procedure estateNot SonarQube Community BuildT-SQL and PL/SQL are excludedVery thin market. Verify coverage before signing anything
You know exactly what the bad pattern isSemgrepCustom rules are the right tool for “never call this deprecated helper again”Cross-file taint is proprietary only and covers 8 languages. Semgrep CE cannot do interfile analysis
Want deterministic findings before the AI layerDeepSource5,000+ rules across 30+ languages run before the AI agent sees the code, which keeps the AI layer’s job smallerAI review is metered separately at $8 per 10K LOC (Standard) or $15 (Advanced). Now a Harness product as of 9 Sept 2026
Need to know where the risk concentratesCodeSceneHotspot and change-coupling analysis over commit history is the only view that treats age as a variableWe did not verify current pricing this session

A note on the free-tier trap, because it is the most common planning error we see on legacy projects. “Just start with the free tier” fails for a large share of legacy shops. SonarQube Community Build covers 21 languages and omits C, C++, Swift, Dart, T-SQL and PL/SQL. Verified against Sonar’s own language overview on 2026-10-18. Combine that with “Community Build cannot analyze pull requests” and the free self-hosted option is unusable as a review gate for a meaningful fraction of the legacy market. SonarQube Cloud’s free tier is the better free starting point for private repos under 50k LOC, because it does include pull request analysis.

For the wider field, our static analysis buyers guide compares the full set.

Which AI code review tool handles legacy code best?

Direct answer: There is no measured answer, because no benchmark breaks results out by codebase age and no vendor publishes per-language precision. Decide on mechanism: SonarQube for baselining, Greptile for whole-repo context, CodeRabbit for configuration depth, Anthropic for instruction-file rigour. Verified 2026-10-18.

The strongest published number anywhere near this question is Anthropic’s own: 84% bug detection on pull requests over 1,000 lines at under 1% false positives, roughly 7.5 issues per large change, 6 to 10 minutes per review. Large pull requests are the legacy norm, so the claim is directly relevant. It is also vendor-published and unreplicated, and a sub-1% false-positive rate is extraordinary against every independent measurement we have. We neither repeat it as fact nor pretend it does not exist.

The independent counterweight: c-CRAB (arXiv 2603.23448) converted human review comments into executable tests across 184 pull request instances from 67 repositories with 234 validated review comments, and found that “Considering the union across all four tools, 97 out of the 234 tests were passed by at least one tool (41.5%)”. Per tool: Claude Code 32.1%, Devin 24.8%, PR-Agent 23.1%, Codex 20.1%.

c-CRAB conflict disclosure: five of six c-CRAB authors are academic (National University of Singapore, Zhejiang University), but Ridwan Shariffdeen lists SonarSource as his affiliation, and the paper carries a disclaimer that its conclusions do not represent SonarSource policy. Sonar sells SonarQube and acquired Gitar in May 2026. Gitar is a paid sponsor of this site. SonarQube is not among the four tools c-CRAB evaluates, which blunts the conflict considerably, but we call out vendor-funded benchmarks everywhere else and so we disclose this one.

The sentence we will stand behind: no party without a commercial stake has published a false-positive rate, precision figure or noise measurement for any shipping commercial AI code reviewer. SWE-PRBench and CR-Bench publish false-positive data, but they measure bare models in fixed harnesses, not products you can buy.

Decision by constraint:

  • You need adoption to survive week two. SonarQube plus a reference-branch new code definition. The ratchet is the whole game.
  • Your bugs come from distant call sites. Greptile, for whole-repo indexing, if you are not on Azure DevOps.
  • You need fine-grained per-path policy. CodeRabbit, for path_instructions. It is the deepest configuration surface in the market.
  • You need instructions that a pull request cannot subvert. Anthropic Code Review, because REVIEW.md is read from the base branch. Protect the branch first or it fails closed.
  • You are doing a framework-wide migration, not a review. Gitar. Disclosed sponsor, no published third-party benchmark.

Where review fits in a long-running migration

Direct answer: Review is the ratchet and the regression net, not the migration engine. Gate every migration pull request on new-code rules, use the reviewer as a diff explainer for engineers who did not write the original, and treat codemod output as the highest-risk category because it is right at scale and wrong in the exceptions. Verified 2026-10-18.

A Java 8 to Java 21 migration, a jQuery to React rewrite, a Struts removal, an Oracle to Postgres move: these run for quarters, and they generate exactly the pull requests AI review handles worst. Mechanical, enormous, mostly correct.

Three placements that earn their cost:

On the ratchet. Every migration pull request introduces new code by definition. Gate it. This is the one moment in a legacy project where you can raise the standard for free, because the author is already rewriting the file.

As a diff explainer. The person reviewing a Struts removal usually did not write the Struts. A reviewer that can summarise what the change does to behaviour is worth more here than one that finds bugs. We cover this capability specifically in AI code review tools that explain findings.

As a regression net on codemods. A codemod applied to 900 files is correct in 898 and wrong in 2, and the 2 are invisible in a diff that long. This is the strongest argument for repository-aware review on migration work, and it is also where Gitar is explicitly positioned: its documented loop is fix, commit, run CI, and commit only on a green build, with automatic follow-up repair if its own fix breaks the build. Low-confidence findings fall back to thread suggestions rather than commits. Sonar’s own material states that a green build is evidence, not proof. Gitar is a paid sponsor of aicodereview.cc, it has no published third-party benchmark, and it does not support GitHub Enterprise Server. Our full Gitar review carries the same caveats.

One CI detail that bites migration projects specifically, because they are the teams most likely to turn on a merge queue: GitHub’s merge queue fires a merge_group event that is separate from pull_request and push. If your required AI review check is wired only to pull_request, the queue stalls permanently. GitHub’s documentation states that status checks “will not be triggered… The merge will fail as the required status check will not be reported.” See what is a merge queue.

How we verified this

Checked on 2026-10-18, all against primary vendor documentation or primary research except where noted.

Verified at source:

  • Sonar’s Clean as You Code introduction, for the new code definitions (previous version; number of days, default 30 and maximum 90; reference branch) and the incremental-improvement rationale, quoted above.
  • Sonar’s SonarQube Community Build language overview, confirming that C, C++, Dart, Objective-C, PL/SQL, PowerShell, R, Shell, Swift and T-SQL show no Community Build support, and that ABAP, Apex, COBOL, Gosu, JCL, Mulesoft Dataweave, PL/I and RPG are commercial-edition only. This directly contradicts the common advice to start a legacy C++ or Oracle project on the free tier.
  • CodeRabbit’s YAML configuration reference, for reviews.path_filters, reviews.path_instructions, reviews.auto_review.base_branches, reviews.auto_review.ignore_title_keywords, reviews.auto_review.labels, and knowledge_base.code_guidelines.filePatterns.
  • SWE-PRBench (arXiv 2603.26130) for the attention-dilution finding and the per-model false-positive rates.
  • c-CRAB (arXiv 2603.23448) for 184 pull request instances, 67 repositories, 234 validated review comments, and the 41.5% union figure, with the SonarSource affiliation disclosure above.

Carried from our own prior verification, re-stated rather than re-fetched this session: Anthropic Code Review’s REVIEW.md base-branch and fail-closed behaviour; Cursor Bugbot’s .cursor/BUGBOT.md path and .cursor/config/bugbot.yaml keys; DeepSource’s .deepsource.toml keys (documented in full in our DeepSource TOML guide); Qodo Merge’s review_agent.inline_comments_severity_threshold; Gitar’s platform matrix excluding GHES; Greptile’s Perforce support and Azure DevOps absence; the GitHub merge_group behaviour.

What we could not verify:

  • No benchmark measures AI review performance on legacy code. SWE-PRBench, CR-Bench, CRBugBench and c-CRAB all sample modern open-source pull requests with no breakout by codebase age, framework vintage or language. Every claim in this market about legacy performance, including the architectural reasoning in this article, is inference.
  • No vendor publishes per-language precision or recall, so “which tool is best for 2009-era Java” has no evidentiary answer.
  • Anthropic’s 84% detection at under 1% false positives is unreplicated. We report it and do not rely on it.
  • CodeScene pricing was not checked in this session. Do not treat the row above as a price.
  • One discrepancy to flag honestly: Sonar’s live language overview lists Secrets detection under Community Build, while our own earlier internal note recorded secrets detection as excluded. We are going with the live page. Verify against Sonar’s documentation for your specific version before planning around it.

Recommendations

Criteria: adoption survivability on a repository that will never be clean, coverage of the languages legacy codebases actually contain, and the ability to reach legacy infrastructure. Review quality is deliberately not the first criterion, because the evidence to rank it on legacy code does not exist.

1. If you do one thing, build the ratchet. Baseline the backlog, gate the diff. Use SonarQube with a reference-branch new code definition if your languages are covered, and budget for Developer Edition or SonarQube Cloud rather than Community Build if you need pull request analysis. This single decision determines whether the project is alive in three months.

2. Exclude before you tune. Vendored, generated and lockfile paths first, with linguist-generated in .gitattributes for the humans and tool-level globs for the bot. Our own data puts 42.1% of changed lines in large pull requests inside those paths.

3. Use path instructions, not blanket exclusions, on the old tree. reviews.path_instructions in CodeRabbit is the deepest surface for this. Keep the legacy tree reviewed for correctness and security; stop it being reviewed for style.

4. Check forge support before you check review quality. Perforce means Greptile. GHES rules out Gitar, Copilot code review and the Codacy AI Reviewer. Azure DevOps rules out Greptile. This eliminates faster than any quality comparison.

5. For migrations specifically, separate the engine from the gate. Gitar (paid sponsor, no published third-party benchmark, no GHES) is built for the migration itself. The review gate should be a different tool with a baseline model.

6. Measure the programme, not the findings. Fix rate per rule tier, time to first review, and scrutiny density beat finding counts every time. We set out exactly how in how to measure code review quality, and the latency and size baselines come from our own 2026 datasets in pull request review time and how big should a pull request be. For the human side, pull request review best practices and DORA metrics explained are the companions.

We have no tool to sell. When two sources disagree we print both and name who paid for each.

Sponsored Why?
Gitar logoGitar

Comments are not enough

Gitar applies the fix, validates it in CI, and clears the queue.

See it on your repo Read our independent Gitar review

Frequently Asked Questions

Best AI code review tools for legacy codebases

Pick on three criteria: can it baseline existing findings and gate only the diff, does it cover your languages, and can it read your forge. SonarQube is the mature answer to the first because Clean as You Code is built into the product, but Community Build cannot analyze pull requests at all and excludes C, C++, Swift, Dart, T-SQL and PL/SQL, so a C++ or Oracle shop needs Developer Edition or SonarQube Cloud. For the diff-review layer on top, CodeRabbit gives you path_filters and path_instructions in .coderabbit.yaml, and DeepSource gives you exclude_patterns in .deepsource.toml. Verified 2026-10-18.

Which AI code review tool handles legacy code best?

No tool is measurably best, because no benchmark breaks results out by codebase age and no vendor publishes per-language precision or recall. What we can compare is mechanism. SonarQube is the only widely deployed product with a first-class new-code baseline. Greptile indexes the whole repository rather than reading the diff alone, which matters when a 15-year-old call site is three files away. Anthropic Code Review reads REVIEW.md from the base branch and fails closed if branch protection cannot be confirmed. Choose on the mechanism that matches your constraint, not on a vendor leaderboard. Verified 2026-10-18.

AI code review tools for generated code

Exclude it rather than tune it. Generated files produce the highest volume of technically correct and operationally useless findings in any legacy repository. In our own sample of 80 merged pull requests over 1,000 changed lines (measured 2026-10-18), 42.1% of all changed lines sat in generated, vendored or lockfile paths. Mark those paths with linguist-generated in .gitattributes so GitHub collapses them, then exclude them in the tool: reviews.path_filters with a leading exclamation mark in .coderabbit.yaml, exclude_patterns in .deepsource.toml, and path-scoped REVIEW.md rules for Anthropic. Do not rely on the model to infer that a 40,000-line protobuf stub is not worth commenting on.

AI code review tools that review documentation changes

Most AI reviewers comment on Markdown by default, which is usually the wrong setting for a legacy repository where documentation drifted years ago. CodeRabbit ships a documentation-aware review and lets you scope it with reviews.path_instructions so docs get prose rules and source gets engineering rules. If you want docs excluded entirely, add an exclusion glob to reviews.path_filters. Anthropic Code Review takes path-scoped instructions from subdirectory REVIEW.md files, so a docs/REVIEW.md can narrow the check set for that tree. Treat documentation review as a separate policy rather than a side effect of the default configuration. Verified 2026-10-18.

AI code review tools that follow team coding standards

Four products read a committed instruction file, and the mechanics differ in ways that matter on legacy code. CodeRabbit reads .coderabbit.yaml plus, by default, the competitor files listed in knowledge_base.code_guidelines.filePatterns, which include REVIEW.md, CLAUDE.md, AGENTS.md, .cursorrules, .github/copilot-instructions.md, GEMINI.md and .windsurfrules. Anthropic Code Review reads REVIEW.md from the base branch, never from the pull request diff, so a pull request cannot loosen its own rules. Cursor Bugbot reads .cursor/BUGBOT.md with upward directory traversal. Qodo Merge exposes a severity rank at review_agent.inline_comments_severity_threshold. Verified 2026-10-18.

How do I stop an AI reviewer flooding a legacy repo with findings?

Baseline first, then gate the diff. The single most effective tactic is the ratchet: accept every existing finding as debt, measure nothing against it, and fail the build only on issues introduced by the change under review. SonarQube implements this as Clean as You Code, where the new code definition can be previous version, a number of days (default 30, maximum 90) or a reference branch. On the AI layer, raise the severity floor rather than disabling rules: Qodo Merge uses review_agent.inline_comments_severity_threshold, CodeRabbit uses path-scoped instructions, and Anthropic supports nit capping via a root REVIEW.md on a protected branch.

Does full-repo indexing help on a legacy codebase?

It should, and the honest answer is that nobody has measured it on old code specifically. Greptile indexes the entire repository rather than reading the diff alone, which is the right shape for legacy work where a call site is often nowhere near the change. But SWE-PRBench (arXiv 2603.26130) found that model performance degrades as more context is added, an attention dilution effect. Indexing and retrieval is not the same thing as stuffing a prompt, so the finding does not refute the architecture, but it does mean more context is not automatically better. We report the tension rather than resolving it.

Can I run AI code review on a 15-year-old C++ or Oracle codebase?

Yes, but your free options collapse. SonarQube Community Build covers 21 languages and excludes C, C++, Swift, Dart, T-SQL and PL/SQL (verified against Sonar's own language overview, 2026-10-18), so the common advice to start with the free tier fails immediately for a C++ or Oracle shop. Community Build also cannot analyze pull requests at all, per Sonar's documentation, which rules it out as a review gate regardless of language. For C and C++ in regulated contexts you are into Developer Edition or a dedicated tool. The diff-level AI reviewers are language agnostic in principle, but none publishes per-language precision.

Where does AI review fit in a long-running modernisation project?

In three places, and not as the thing doing the migration. First, as a ratchet on every migration pull request so the new code holds a standard the old code never did. Second, as a diff explainer for reviewers who did not write the original, which is the common case on a 15-year-old system. Third, as a regression net on mechanical changes, where the risk is a codemod that is right 998 times and wrong twice. Gitar is built around automated migration at scale and commits only on a green build; Sonar's own material calls a green build evidence, not proof. Gitar is a paid sponsor of this site and has no published third-party benchmark.

Should a legacy repo fail the build on AI review findings?

Only on new code, and only on a severity floor you set deliberately. Blocking on whole-repository findings in a legacy codebase is how adoption dies in week two. Gate the diff, let the backlog sit, and review the backlog on a schedule instead of in the merge path. One hard CI gotcha if you do gate: GitHub's merge queue fires a merge_group event that is separate from pull_request and push. A required AI review job wired only to pull_request will stall the queue permanently, because GitHub's documentation states the merge will fail as the required status check will not be reported.

Explore More

Free Newsletter

Stay ahead with AI dev tools

Weekly insights on AI code review, static analysis, and developer productivity. No spam, unsubscribe anytime.

By subscribing you agree to receive the weekly newsletter. Unsubscribe in one click, any time. See our privacy policy.

Join developers getting weekly AI tool insights.

Related Articles