How to keep a large codebase consistent when AI writes most of it
To keep a codebase consistent when AI writes most of it, you can't count on the agent to remember how the rest of the repo does things, because it can't. AI codebase consistency isn't a habit you can document your way out of. It's a structural problem, and it needs a structural fix. This playbook gives you five concrete steps that, together, keep a large codebase in agreement with itself even when agents do the typing.
The order matters. Each step catches what the one before it misses. You move from intent (write down the rules) to prevention (check before writing) to measurement (score the drift) to enforcement (block regressions) to watching the trend. Skip the early steps and the later ones drown in noise. Skip the later ones and the early ones quietly erode.
Why a large codebase drifts when AI writes it
A human engineer keeps a working model of the codebase in their head. They know there's already a retryWithBackoff helper, that the team wraps errors in a Result type, that data access goes through one repository layer. An AI agent keeps none of that between sessions. Each task is a cold start: the agent sees the files in its context window, makes a choice that looks fine on its own, and writes code that works in isolation but may not match how the rest of the repo solves the same problem.
That's drift — the codebase slowly pulling apart across separate, memory-less AI sessions. One off-pattern function is harmless. But agents are fast, and drift adds up. After a few hundred edits you have three error-handling styles, two ways to talk to the database, a second date formatter some agent reinvented, and leftovers from a half-finished refactor. No single change looks wrong in review. The codebase as a whole stops agreeing with itself.
Step 1: Declare your conventions where the agent reads them
Start with the cheapest lever: write the rules down where the agent will actually look. For Claude Code that's CLAUDE.md; for Cursor it's .cursorrules. Spell out the conventions a new contributor, human or agent, would otherwise have to work out for themselves:
- +How errors are handled and passed up.
- +How code talks to the database or outside services.
- +Where shared utilities live, and the names to search before writing a new one.
- +Naming, file layout, and the patterns the team has chosen on purpose.
Keep it short and specific. A focused file the agent reads in full beats a long one it skims. We go deeper on this in CLAUDE.md best practices.
Result" states the intent without checking that any given change followed it. As the codebase grows, the file and the code drift apart. Treat this step as setting direction, not as enforcement.Step 2: Give the agent in-loop checks before it writes
The best place to keep code consistent is before the code is written, not after. If the agent can ask the codebase how it already does things mid-task, it fits in from the start instead of being corrected in review. That's what an MCP server is for: it gives the agent tools it can call while it works. (The Model Context Protocol is the open standard these tools speak.)
VibeDrift's MCP server is free, open source, local, and needs no login. One line wires it into your agent:
claude mcp add vibedrift -- npx -y @vibedrift/cli mcp
It gives the agent five tools to consult before and during a change:
- +
get_dominant_pattern— what's the established convention here (error handling, data access, auth)? - +
find_similar_function— does a helper for this already exist, so the agent doesn't build it again? - +
check_file_drift— does this file already differ from its neighbors? - +
validate_change— would this specific change add drift? - +
get_intent_hints— what conventions has the team written down inCLAUDE.mdor.cursorrules?
This is the step that turns Step 1 from a hope into a check. The conventions you wrote down get read by a tool the agent calls on purpose, with real answers about the actual repo instead of the agent's guesses. It works with Claude Code, Cursor, Windsurf, or any MCP client. Full per-client setup is in the MCP guide.
Step 3: Measure the drift with a scan and a score
You can't manage what you can't see. Before and after a big agent session, run a local scan to get a number on how consistent the codebase really is:
npx @vibedrift/cli .
It runs in about two seconds, your code never leaves the machine, and it's free, open source, and unlimited. The output is a Vibe Drift Score: a 0–100 score with a letter grade, plus findings that tell you where to look. Each finding names the dominant pattern, the files that break from it, and a suggested fix. Five checks run under the hood:
- Architecture — does the structure agree with itself?
- Security — are protective patterns applied the same way everywhere?
- Redundancy — duplicate helpers and reinvented logic.
- Convention adherence — does the code follow the rules you declared?
- Scaffolding hygiene — leftover stubs and half-finished refactors.
For a closer look, vibedrift . --deep runs a Claude-checked analysis that catches drift the quick checks miss; it draws from your deep-scan budget. The fast local scan is the one you'll run all the time; the deep scan is for when you want a careful second opinion on a tricky module.
vibedrift telemetry disable or pass --local-only.Step 4: Gate CI so regressions can't merge
A score you check by hand is a score you'll forget to check. Make it automatic: run the scan in CI and fail the build when consistency drops below a floor you set. As a GitHub Action:
npx @vibedrift/cli . --json --fail-on-score 70
Add a VIBEDRIFT_TOKEN secret and the check runs on every pull request. If an agent's change pushes the codebase below 70, the check fails and the regression won't merge until someone brings it back in line. This is the enforcement layer: Step 1 sets the intent, Step 2 nudges the agent toward it, and Step 4 makes it a hard rule a human or agent has to meet before the code ships. The full walkthrough, including how to pick a threshold, is in gate drift in CI.
Choosing a threshold
Don't start at 100. Run the scan on your current main, see where you land, and set the floor a little below that so you don't block every PR on day one. Then raise it as you clean drift out. The goal is a one-way door: the score only goes up, never down, with each merge.
Step 5: Track drift over time
A single score is a snapshot. What you really want is the trend: is the codebase getting more or less consistent week over week, and which agent sessions or refactors moved the needle? Tracking drift over time turns consistency from a one-off cleanup into a number you can steer.
Drift trend is a Pro feature ($15/mo), which also includes 12 deep scans a month, in-editor deep checks through the MCP server, watch mode, and a git pre-push gate so drift gets caught before it even reaches CI. The free tier keeps unlimited local scans, the free MCP tools forever, and one deep scan a month, which is plenty to run the first four steps. The trend view is what you add when consistency becomes something you manage all the time rather than fix now and then. See pricing for the full breakdown.
Putting the playbook together
None of these steps works alone, and that's the point. Convention files set direction but erode. In-loop MCP checks stop most drift but can't catch everything. A scan measures what slipped through, a CI gate stops it from merging, and the trend tells you whether the whole system is holding. Layered together, they let agents write most of your code without the codebase quietly losing its grip:
- Declare conventions in
CLAUDE.md/.cursorrules. - Add the MCP server so the agent checks before it writes.
- Scan with
npx @vibedrift/cli .to get a Vibe Drift Score. - Gate CI with
--fail-on-scoreso regressions can't merge. - Track the trend so consistency only goes up.
The fastest way to see where your codebase stands today is one command:
npx @vibedrift/cli .
Frequently asked questions
AI coding agents are stateless across sessions. Each task starts fresh with no memory of how the rest of the repo solves the same problem, so it picks a locally reasonable approach that may not match the codebase's existing convention. Repeated over hundreds of edits, those small disagreements accumulate into drift: three error-handling styles, two data-access patterns, duplicate helpers, and a codebase that no longer agrees with itself.
They help, but they are necessary, not sufficient. Convention files set the intended direction and are the cheapest first step. But agents don't always read them fully, long files compete for context, and rules describe intent rather than verify it. They erode as the codebase grows. Pair them with an in-loop check the agent can call and a CI gate that fails on regressions.
Run a drift scan. VibeDrift's local scan, npx @vibedrift/cli ., reads the repo and returns a Vibe Drift Score from 0 to 100 with a grade and findings: the dominant pattern, the files that deviate from it, and the suggested fix. It runs locally in about two seconds, your code never leaves the machine, and it's free and open source.
Yes. Run the scan in CI with a score threshold, npx @vibedrift/cli . --json --fail-on-score 70, as a GitHub Action with a VIBEDRIFT_TOKEN secret. If a pull request drops the score below your floor, the check fails and the regression can't merge until it's brought back in line.
Local scans and the MCP tools are free and open source, forever. The free tier includes 1 deep scan a month; Pro is $15/mo for 12, and you can top up 5 more for $10 on any plan. Credits never expire.