Skip to main content

Best practices

Reading the diff is the habit vibe coding needs

Mohammad Qadri ·

A developer reading a side-by-side code diff on a monitor with a handwritten spec on a notepad beside the keyboard

Reading the diff means going through the exact lines an AI coding tool changed, before you accept them, and forming a view on each one. Vibe coding as it was first described did the opposite: Andrej Karpathy's February 2025 post described accepting AI-generated changes without reading the diffs at all. That works for a throwaway weekend project and stops working the moment the code holds real data, real money or real users, because the two things an unread diff hides best are quiet architectural damage and quiet data exposure. Both now have evidence behind them: GitClear's analysis of hundreds of millions of lines shows duplication and rework climbing year after year, and 2026 security scans have found AI-built apps leaking sensitive data through the same small set of mistakes. Reading the diff is the cheapest correction available, and it is a skill, not a virtue.

What a diff is, and what reading one means

Every AI coding tool works the same way at the point of contact: it proposes changes to files, and you accept or reject them. The diff is the record of those changes. Lines removed on one side, lines added on the other, with enough surrounding context to see where they land. If you use a chat-style tool you may see it as a block of code with red and green markers; in an editor or a pull request you see it file by file.

Reading it means something more specific than looking at it. You go through the changed lines and form a view on each: what it does, why it is there, and what it touches that you did not ask about. The last of those is the one that pays. An agent asked to add a password reset flow may also change your session handling, loosen a database rule, or add a dependency you have never heard of. None of that appears in the summary it writes for you. All of it appears in the diff.

The original description of vibe coding named the opposite habit with unusual precision. In his February 2025 post, Andrej Karpathy described a way of working where changes are accepted without reading the diffs, and errors are pasted back in without much scrutiny, so that the code grows beyond his comprehension. The academic write-up of that post treats it as the founding definition of the term. Read it in full and you notice the scoping he attached: he was describing throwaway weekend projects and low-stakes experiments, not production systems. The scope travelled less widely than the phrase did.

The person who coined it now emphasises oversight

By early 2026 Karpathy had moved away from the framing. His preferred term became “agentic engineering”: agentic because the default is that you are not writing the code directly most of the time, you are orchestrating agents that do, and engineering because there is craft and expertise in doing it well. The New Stack covered the change in February 2026.

That is not a cosmetic rename. “Forget that the code exists” and “act as oversight” are opposite instructions about the same activity, and the second one requires a mechanism. Oversight of an agent that writes files is, in practice, reading the diff. There is no other place the work is visible.

Writers who have tried to draw the line have landed in the same spot. A March 2026 piece in AI in Plain English puts it bluntly: read every diff, not skim, read, and if the agent changed 200 lines then you read 200 lines. Its wider argument is that a developer’s value is no longer typing speed or API recall, but the clarity with which they define a problem and the accuracy with which they judge the result. A separate account of a vibe engineering process makes the same distinction: vibe coding instructs the end goal, verifies it appears to work, and deploys, while the engineering version reads the plan, reads the code, and debugs. Architecture is the thing you only see by reading.

What unread diffs do to a codebase

The strongest quantitative evidence is GitClear’s longitudinal work on real repositories, including code from large technology companies alongside its enterprise customers. Its analysis of 211 million lines found AI assistants correlating with more duplicated and copy-pasted code and less refactoring, with duplicated blocks becoming more common during 2024. Moved code, which is the fingerprint of someone reorganising and reusing what already exists, fell below 10% of changed lines in 2024, a 44% drop on the year before. Devclass reported the findings in February 2025.

The trend did not reverse. GitClear’s 2026 maintainability research tracks churn rising from a pre-AI baseline of about 3.3% to 5.7% in 2024 and 7.1% in 2025, roughly doubling in two years. Moved code continued to fall while copy/paste continued to climb over the same period. Put together, the picture is developers becoming more likely to duplicate than to refactor. The share of new code revised soon after being committed also rose, which is the signature of code that was not right when it landed.

GitClear’s own reading of this is worth repeating, because it is not an argument against the tools. Churn is not automatically bad; untracked churn is, because teams see the productivity gain and never see the rework bill. The suggested fixes are measurement, better prompts, stricter review and quality gates. Every one of those is downstream of somebody actually reading what changed.

There is a mechanism here that makes sense once you have watched an agent work. A model asked to add a feature has limited awareness of what already exists in your codebase. Writing a fresh function that works is easier for it than finding the one you already have and extending it. Accept that fifty times and you own five near-identical implementations of the same idea, three of which will be fixed when a bug is found and two of which will not.

What unread diffs do to security

The defect profile of AI-co-authored code is not uniform. A February 2025 study summarised on Wikipedia’s vibe coding entry found elevated rates of logic errors, incorrect dependencies and flawed control flow, with misconfigurations and security vulnerabilities more common, alongside readability problems such as inconsistent naming. Misconfiguration is the category that matters most here, because it is the one that reads as harmless in a diff summary and catastrophic in production.

That is exactly what the 2025 and 2026 incident reports show. Researchers testing apps built with tools like Lovable found user data leaking through the same class of flaw, a missing or mistaken database access rule, and a second researcher reproduced the problem with a short script that pulled out debt balances, home addresses and API keys. XDA’s account of finding leaking vibe-coded apps describes how little effort it takes to stumble across them. At larger scale, a 2026 scan of vibe-coded applications found a number of them exposing sensitive data, reported by VentureBeat.

The common thread in those failures is that the app worked. It signed users in, it showed the right data to the right person in the browser, and it looked finished. The flaw was in a rule the reader never opened, in a diff nobody read. Our page on the risks and limits of vibe coding goes further into the failure modes; the point for review is narrower. A working demo is not evidence that the access rules are right, and only two things can tell you that they are: a test that tries to read someone else’s data, or a person reading the rule.

How to read a diff you did not write

Reading unfamiliar code is slow if you start at line one and go down. Start with the questions instead, roughly in this order.

  • Scope. Which files changed, and did you expect all of them? An agent that touched twelve files when you asked for one small change is telling you something before you read a single line.
  • Blast radius. Did anything change outside the feature you asked for? Shared utilities, configuration, build scripts, middleware, dependency manifests. These are where a small edit reaches everything.
  • Data access. Every new query, endpoint or database rule gets read properly. Who can call it, and whose rows can they see? This is the category with the incident record behind it.
  • Secrets and credentials. Any key, token or connection string appearing in the diff is a stop-and-fix, not a note for later.
  • Dependencies. New packages get named and justified. If you cannot say what a package is and who maintains it, you have not finished reading.
  • Duplication. Does this new function already exist somewhere in your code under a different name? This is the question that keeps churn down, and it is the one a model is least able to answer for you.
  • Deletions. The red lines matter as much as the green. Removed validation, removed error handling and quietly disabled tests all look like tidying.

One habit does more than the rest: write the spec before you prompt. Even a paragraph, even bullet points. The AI in Plain English piece argues this single habit separates careful work from careless more than any tool choice, and the reason is that a diff is only reviewable against an intention. Without a spec you are reading the code and asking “does this look plausible?”, which is a question you will always answer yes to. With one you are asking “is this what I asked for, and what else did it do?”, which is answerable. Our post on writing a clear prompt for an AI coding tool covers how to get that specification into a form the model can follow.

Keep diffs small enough to be read

Most people who say they do not have time to read diffs are actually saying their diffs are too big, and that is a workflow problem rather than a discipline problem. Ask for one change at a time. Commit at each point the code works, so that each diff has a single subject and a clean boundary. When an agent has been running for a while and produced a 600-line change across fifteen files, the honest options are to read all of it or throw it away and ask again in smaller pieces. Skimming it is a third option that feels like the first and behaves like accepting it unread.

Small diffs also make the model better, not just the review. A narrow request with a stated intention produces a narrow change. A broad request produces a sprawl of plausible code that you then cannot check, which is how a prototype turns into something nobody wants to touch. The best practices section sets out the wider loop that this fits into.

What to automate, and what stays human

Some of the reading can be handed to machines, and should be. Dependency scanning, secret scanning, linting and type checking catch a defined set of problems faster and more consistently than any person, and they belong on every AI-assisted branch rather than in someone’s memory. Automated review tools can flag suspicious patterns in a change before you open it. What none of them do is judge whether the change was the right change, whether it duplicates something you already own, or whether the data rule it added matches your intentions. That judgement is the human part, and it is the part that Karpathy’s “oversight” is pointing at.

For a team, the useful move is to write down which changes must be read line by line and which can pass on automated checks alone, then enforce it. Our post on what an AI code policy must say on security and IP covers setting that threshold, along with why keeping a record of the human contribution matters for ownership. A rule that cannot be checked, in review or in CI, is not a rule.

Where it is genuinely fine not to read

Not every project earns the effort, and pretending otherwise is how good practice gets ignored. A prototype on your own machine, with no real user data, no payments and no route to the internet, can be accepted wholesale and thrown away on Friday. That is the case Karpathy described, and it is a legitimate use of the tools: you are buying speed with code you never intend to maintain.

The cost arrives when a prototype quietly becomes a product. It gets a domain, then a login, then a customer’s spreadsheet, and nobody goes back to read the 4,000 lines that were accepted when none of that was true. If you are going to skip the reading, decide out loud that this is throwaway work, and treat the first real user as the moment you either read all of it or rebuild the parts that matter. Reading a diff at the point it is written takes a few minutes. Reading it eighteen months later, in an incident, takes considerably longer.


Written with AI assistance and reviewed under our editorial policy. Vibe coding changes quickly; details reflect sources current on 2026-09-06. Some passages are the author's opinion. Spotted an error? tell us.

Frequently asked questions

Does reading every diff cancel out the speed of vibe coding?
It reduces the raw speed and changes what the speed buys you. You still avoid writing the code, which is most of the work, and reading a small, single-purpose diff takes a fraction of the time it would have taken to author it. Where teams lose the gain is by leaving diffs large enough that review becomes its own project.
What should I look at first in a large AI-generated change?
Start with which files changed and whether you expected all of them, then read anything touching data access, credentials or configuration in full. Those categories carry the incident record: missing database access rules and misconfigurations are among the most common ways AI-built apps have leaked user data.
Can an AI review the diff for me?
Partly. Automated scanners and AI review tools catch a defined set of problems, such as exposed secrets, vulnerable dependencies and obvious pattern errors, and they belong in your pipeline. They cannot tell you whether the change was the right change or whether it duplicates code you already own, which is the judgement that keeps a codebase maintainable.
Is vibe coding still the right name for this way of working?
The term is widely used and worth understanding, but its coiner has moved on from it. Karpathy's preferred description in 2026 is agentic engineering, on the basis that you are orchestrating agents and acting as oversight rather than forgetting the code exists, which is a different practice with different habits.

All posts