AI Code Quality

Keeping AI-written code from piling up duplicates, regressions and technical debt. Start with the pillar guide on reducing AI coding mistakes, then the guide to preventing duplicate functions, and the posts on function search, code audits and an open-source quality framework.

Start with How to Reduce AI Coding Mistakes: A Practical Guide

Guide to preventing technical debt AI development
AI Code Quality

Preventing Technical Debt in AI Development Guide

Suppose an agent adds a currency formatter. Its tests pass, the output looks right, and the feature ships, but the repository already has a formatter with different rounding rules. Now a rounding change means finding and updating both implementations.

I'd want to catch that before asking the agent to write the second one. For this workflow, technical debt means extra maintenance work you've accepted or accidentally introduced, such as repeated behavior or code that never gets connected to the feature it was meant to implement, leaving someone else to work out whether it can be removed.

The useful place to start is the next task. Give it a discovery step before editing, make the caller check part of the plan, and require evidence from the feature's entry point before calling it finished, even when the helper's own tests already pass.

What the research supports

GitClear's 2025 code-quality report found duplicated blocks in 1.80% of sampled commits in 2023 and 6.66% in 2024. Its measure looks for repeated runs of at least five lines, excluding blank and keyword-only lines, so this is a particular duplication measure, not the percentage of a codebase that is duplicated.

That trend is a

Dan Greer · · 6 min read
Open source AI code quality framework guide cover photo
AI Code Quality

Open Source AI Code Quality Framework Guide

A test that calls a new helper directly can pass even if the application never calls that helper. The implementation exists, its unit test is green, the route still uses the old path, and a reviewer has to notice the missing connection.

That's the kind of gap I want an AI code quality framework to make visible.

I split the work into four layers below, with a different question for each one, because a formatting check can't decide whether a feature meets its requirement, and a written requirement can't enforce a formatting rule. Open-source tools cover much of the checking. Someone still has to choose the rules and inspect what the tools didn't establish.

Start with a starter repo, then choose your rules

I built the ai-codebase-boilerplate repository, an MIT-licensed reference for TypeScript projects rather than a standard every team has to adopt; its README also recommends Pharaoh, which I build. Most of the setup lives in FRAMEWORK.md, a six-phase plan meant to run one phase per Claude Code session, which has you create the Biome, Knip and Lefthook configuration, Claude Code hooks, a GitHub Actions workflow and a Stryker config. The template/ directory holds the package.json scripts

Dan Greer · · 6 min read
How to reduce AI coding mistakes practical guide cover photo
AI Code Quality

How to Reduce AI Coding Mistakes: A Practical Guide

A permission helper can be three lines long and still need a review across several packages. In cal.diy, checkAdminOrOwner connects to API services, web components, shared application code, and two HTTP endpoints in the captured three-hop result.

That changes what I'd ask an agent to do first.

Before it edits the helper, I want the affected callers and their assumptions, the behavior we're preserving, the failure paths to review, and the tests that will exercise the change. A clean implementation is only part of the task.

Give each change an investigation before implementation, keep its scope reviewable, write down the behavior you expect, and check it through an entry point afterward. That's the workflow I'd use to reduce AI coding mistakes.

Turn a vague task into something you can check

Write down the expected behavior before asking for code. For a permission change, specify who should retain access, who should lose it, what response a denied request should receive, and whether existing clients need to keep working.

I'd put the acceptance condition next to the task so the reviewer can compare it with the result. Ask the agent to name uncertainties before editing, especially when the request contradicts existing

Dan Greer · · 6 min read
Developers reviewing code on screen during codebase audit for AI assisted development
AI Code Quality

Codebase Audit for AI-Assisted Development

A passing test suite can leave a basic question unanswered: does production ever reach the function you just added?

That's where I'd start a codebase audit for AI-assisted development. The useful result is a finding list tied to a file, a revision, a saved configuration, and enough evidence to decide what needs changing. A general verdict that the repository looks healthy doesn't give you much to work with.

The runbook below covers code that's already been written. For the checks to put around the next change, see reducing AI coding mistakes.

Start with a revision you can name

Pick the commit you're auditing and record its ID beside the reports. Keep the source tree unchanged during the scan, record the tool versions, save the configuration, and write down the directories you excluded so someone else can reproduce the finding.

Use Node.js 24 for the TypeScript examples below, with source under src and pnpm available.

Change that path for your repository. Run the same configuration against your baseline and the revision under review.

Don't fix things yet.

An ignored directory, a missing generated file, or an entry point the scanner hasn't recognized can change what a report means, and I'd

Dan Greer · · 7 min read
Illustration showing developers using tools to function search across codebase efficiently
AI Code Quality

8 Powerful Ways to Function Search Across Codebase Efficiently

A match for formatPrice doesn't tell you whether you've found its definition or a file that calls it. And before you compare search tools, decide which copy of the code matters, because a result from the default branch may describe a helper you've changed locally, and you need to inspect the version your new caller will actually import.

ripgrep is where I'd start for a known name. When I don't know it, I want help finding candidates, followed by enough source code to check their behavior, because a promising signature doesn't settle how a helper handles missing inputs, or whether its defaults fit the new caller.

These are eight starting points. The commands and prompts below are search examples, with captured output identified separately.

Tool Start here when
ripgrep You know a name or literal string in local files
ast-grep You want a particular declaration shape
GitHub Code Search You want definitions in a GitHub repository
VS Code You're navigating symbols while editing
Cursor You can describe the behavior but don't know its name
Claude Code You want an agent to search and read candidates
Sourcegraph Code Search You want to scope a query across repositories on your instance
Pharaoh
Dan Greer · · 6 min read
Diagram showing code blocks merging to prevent duplicate functions in AI coding workflows
AI Code Quality

How to Prevent Duplicate Functions in AI Coding Workflows

Suppose an agent adds an email validator to a form. Another version lives in utils/, one sits in services/, and a controller has its own check, so review now has to establish whether they're copies or different policies. The new function's tests can pass while leaving that question unanswered.

I'd want to settle it before another implementation exists.

That means asking for evidence of a lookup, including the candidates that looked promising but didn't fit, the places the agent checked, and the reason it still needs new code. A request to “avoid duplication” leaves all of that invisible.

Require lookup evidence before the first edit

Start with the behavior you need. Search the relevant module and shared packages, look beyond the proposed function name, open candidate implementations, then inspect their callers before deciding what to change.

An email check used to reject malformed input might have a different contract from one that applies an account policy.

Give the agent this prompt:

Before editing, look for an existing implementation of <behavior>.
Search the target module, adjacent modules, and shared packages.
Try alternative names and domain terms, not only my proposed name.
Open promising implementations and inspect their callers and
Dan Greer · · 6 min read