Vibe Coding: How to Review AI-Generated Code You Didn't Write
Vibe coding makes 'it compiles' feel like a finished review. Here's how to actually read, trace, and verify AI-generated code before you accept responsibility for every line.
The short answer: the real risk of vibe coding isn't that the AI writes bad code — it's that you accept code you don't actually understand, and "it compiles" quietly becomes your whole review. The fix is to treat every generation like a pull request from a talented junior who's never been paged at 3am: read the dangerous parts first, trace the risky paths by hand, run it yourself, and refuse to accept any line you can't explain. The agent wrote it, but the moment you merge it, every line is yours.
I've shipped a lot of agent-generated code, and the failures almost never came from the agent being dumb. They came from me skimming a plausible-looking diff, seeing green checks, and moving on. The code looked like code I'd have written, so I gave it the trust I'd give my own — which is exactly the trust it hadn't earned. Reviewing what you didn't write is a different skill than writing it, and vibe coding makes that skill the whole job.
"It compiles" is not a review
When you write code yourself, you build understanding as a side effect — every line passed through your head. When an agent writes it, that understanding doesn't exist yet, and the compiler won't give it to you. A clean build means the syntax is valid. A passing test suite means the cases you thought to write are covered. Neither tells you whether the authorization check actually runs, whether that catch swallows the error you needed, or whether the happy path you demoed is the only path that works.
The trap is that agent output is fluent. It reads like something a competent engineer wrote, so your brain pattern-matches it to "fine" and skips the real read. Fluency is not correctness. The most dangerous diff is the one that looks obviously right.
Read it like a PR from a talented junior
Here's the mental model that fixed this for me: the agent is a genuinely talented junior engineer who has read every codebase on the internet and has never once been woken up by a production incident. It knows every pattern. It has no scars. It will confidently hand you the tutorial version of a thing — the version that works in the demo and falls over on the first real user.
So review it the way you'd review that junior's first PR: generously, but not trustingly. The same thing I wrote about in code review is culture, not a checklist applies here, with one shift — the author can't learn from your feedback, so the review's entire value lands on you catching the problem before it ships.
Read the risky parts first
Don't read the diff top to bottom. Read it in risk order, because your attention is finite and the agent's mistakes cluster in predictable places. My order:
- Auth and authorization. Does the check actually run on the server, on every path, before the sensitive action? Agents love to gate the UI and forget the API.
- Data writes. Anything that mutates, deletes, or migrates. A wrong read shows you bad data; a wrong write destroys good data.
- Money and anything you can't take back. Payments, billing, emails to real users, irreversible side effects.
- External calls. Every network boundary is a place the happy path assumption breaks — timeouts, retries, partial failures.
- Error handling. Where do errors go? A swallowed exception is how a broken write looks successful.
If those five are right, the rest is usually cosmetic. If any of them is wrong, nothing else matters.
Never accept a line you can't explain
This is the single rule that catches the most. Before you accept a block, explain out loud — to a colleague, a rubber duck, yourself — what it does and why it's correct. If you can't, you haven't reviewed it; you've waved it through. "The AI probably knows" is not an explanation. You're the one who'll be paged.
And when you hit something you don't understand, don't patch around it. The instinct is to tweak the confusing part until the symptom goes away — but now you've built a fix on top of code you didn't understand, which is confusion compounding. Reject and re-prompt instead. Ask the agent to explain its decision, or regenerate the whole block with a tighter constraint. A fresh clean generation beats a patched confused one every time.
Trace the risky paths, then run it yourself
Static reading isn't enough for the top of that risk list. For auth, money, and data writes, trace the path by hand: follow the request from the boundary to the database and back, naming every check it passes through. If you can't name them, they might not be there.
Then actually run it. Not the demo path the agent built to — the ugly paths. Send the malformed input, the empty array, the expired token, the double-click that fires the request twice. Agents build to the happy path because the happy path is what the prompt described. The bugs live everywhere else, and the only way to find them is to go there yourself. "I ran it" has to mean more than "I ran the one case it was designed for."
Use agents and skills deliberately
The best reviewer of a generalist agent's output is a specialist agent pointed at the exact risk. A general-purpose agent optimizes for "produce working code"; a specialized one optimizes for "find what's wrong with this code" — and that's the review you actually need.
- A security-and-hardening skill pointed at the auth, input handling, and secret usage in a generation — the top two items on the risk list — catches the class of mistake a generalist agent introduces and then confidently overlooks.
- An api-and-interface-design skill to review boundaries and contracts before clients depend on them, so a confused interface doesn't harden into one you can't change.
- A coding-standards skill to flag the
anycasts, dead error handling, and silent dependency creep that slip past a human skim.
The meta-point: make a second agent argue with the first one's output. A specialist reviewing a generalist catches exactly the errors that make vibe coding risky — and it never gets tired on the fiftieth diff the way you do. Just remember the specialist is another talented junior; its review is an input to yours, not a replacement for it. That's the same honest read on these tools I landed on after six months of living with AI coding assistants.
The responsibility never transfers. The agent generates; you decide. When that code pages someone at 3am, "the AI wrote it" is not a sentence anyone wants to hear, least of all from the person who merged it. This is one of the vibe-coding deep-dives — start from the vibe-coding precautions overview, and when you're reviewing for the scariest bucket, pair this with the security and networking precautions checklist.
The vibe-coding series
Things to keep in mind while building with AI agents — this post is one part of the full checklist.
- Start here: the precautions overview
- Architecture for your user count
- Choosing a backend
- Security & networking
- Frontend precautions
- Spec & prompt discipline
- Testing & verification
- Dependency safety
- Data & database precautions
- Error handling & observability
- Cost control
- Keeping it maintainable
- Deployment & platform choice
Frequently asked questions
How do you review code written by AI?
Review it like a pull request from a talented junior who's never been paged at 3am. Read the risky parts first — auth, data writes, money, external calls, error handling — trace those paths yourself, and never accept a line you can't explain out loud. 'It compiles' is not a review.
Should I trust AI-generated code if it passes tests and compiles?
No. Compiling proves the syntax is valid; passing tests proves the cases you wrote are covered. Neither proves the code is correct, secure, or doing what you think on the paths nobody tested. Treat green as the start of review, not the end of it.
What should I do when AI generates code I don't understand?
Don't accept it and don't patch around the confusing part. Reject the generation and re-prompt — ask the agent to explain the decision, or regenerate with tighter constraints. Patching code you don't understand just hides the confusion inside something you now own.