How to review AI-generated code before you merge it
Read the whole diff yourself before you merge, against the branch it came from. Look for what tests and AI reviewers can’t see. That means work you didn’t ask for, checks that were deleted or loosened, APIs that don’t exist, and behaviour that changed without a word. Then hand your notes back to the agent that wrote the code, so it does the fixing.
What should you check in AI-generated code?
Six things, roughly in the order they cost you if they ship. None of them needs you to understand every line first.
- Scope. Did it change only what you asked for? Agents fix a neighbouring bug, rename a helper, reformat a file. Every file you didn’t expect in the diff is a question to ask before anything else.
- Deleted or weakened checks. A skipped test, a loosened assertion, a validation that’s gone, a type cast to get past the compiler. It’s the quickest way for an agent to make a failing check pass, and the tests will be green.
- Invented APIs and dependencies. A function, flag or option that doesn’t exist, or a new package you never agreed to. Read the imports and the lockfile diff, not just the code that calls them.
- Swallowed errors. An empty catch block, an error logged and dropped, a fallback value that hides a failure. The happy path works, so nothing tells you.
- Quiet behaviour changes. A default that moved, a config value, a migration, a changed response shape. Anything existing users would notice, with no test that says it was meant to change.
- Secrets and leftovers. Keys, tokens, absolute paths from the agent’s machine, and debug logging it forgot to take out.
Agent-written changes also arrive all at once, with no author to ask, and they keep moving while you read, because the agent is still going. That last one is what breaks a review tool you have to reopen after every edit.
Is an AI code reviewer enough?
No, but it’s a useful second pass. An AI code review tool reads the diff and posts findings, usually on the pull request. It’s good at local mistakes: a null that isn’t checked, an off-by-one, a missing await.
What it can’t know is what you asked for. It reviews the code against the code, so work you didn’t want, or a check that was quietly deleted to make a test pass, can read as perfectly reasonable. Run one if you have it. Then read the diff yourself, because you’re the only reviewer who knows the intent.
DiffHub isn’t an AI reviewer. It shows you the diff and keeps the notes you write.
Where should you read an agent’s diff?
Wherever you’re going to act on it. Four of the five options below are terminal-shaped and one isn’t, and that difference matters more than how any of them renders a diff.
| Tool | Where it runs | Verdict |
|---|---|---|
| revdiff | TUI, Go binary | Best if you want the annotations piped straight into Claude Code or Codex. |
| hunk | Terminal, npm or Homebrew | Best if you want agent notes rendered inline and never leave the terminal. |
| cmux diff | cmux pane | Best for a quick pass. Already installed, costs nothing, no watch yet. |
git diff main...HEAD | Any shell | Best when you have exactly one question. Nothing to install. |
| DiffHub | Browser tab, or cmux split | Best for a large change you will read, edit, and re-read in one sitting. |
hunk describes itself as “Terminal diffs for humans & agents” and ships a watch mode, so on the refresh question it and DiffHub agree. They disagree about the terminal. revdiff is “a TUI for reviewing diffs, files, and documents with inline annotations”. Both are MIT licensed and free. Both quotes are from their own pages, read 2026-08-10.
cmux users have asked for the refresh too: issue #7101 requests live reload for cmux diff and names watching an agent’s file changes as the reason. It was open on 2026-08-10.
How do you hand review notes back to the agent?
Write them where you read the diff, then give the agent all of them at once. In DiffHub:
- Run
npx diffhub@latestin the repository the agent changed. - Hover a line, click the plus, and write what’s wrong and what you expect instead.
- Press Copy & clear in the status bar. Every comment becomes one Markdown prompt.
- Paste it into the agent that wrote the code.
npx diffhub@latestTwo comments come out like this:
## Code Review Comments
Please address the following:
- **src/api/orders.ts:42** (new side): [must-fix] This catch returns an empty list, so a failed request looks like no orders. Let the error through.
- **src/api/orders.test.ts:18** (old side): [question] Why was this assertion removed? Put it back unless the behaviour really changed.Each line names the file, the line and the side of the diff. “old side” means the comment sits on a removed line, so the agent knows to look at what was there rather than what’s on disk now. The viewer has no label picker. Start a note with [must-fix] or [nit] and it reaches the agent as written, which is enough to tell a blocker from a passing thought.
The other tools do this too. revdiff writes structured annotations to stdout when you quit and ships plugins for Claude Code and Codex. hunk renders agent notes inline. The loop matters more than the tool. Reviewing any agent’s diff covers it step by step, and reviewing Claude Code’s changes covers that one agent.
What does DiffHub need, and when is it the wrong answer?
| Fact | Value | Source |
|---|---|---|
| Where the review happens | A browser tab, or a cmux browser split | first-party |
| Published package | diffhub 1.0.0 | npm registry, read 2026-09-22 |
| Install cost | 35.6 MB unpacked, 1,829 files | npm registry, dist.unpackedSize |
| Runtime floor | Node 20.11, or Bun 1.0.23 | apps/cli/package.json engines |
| Listens on | 127.0.0.1, port 2047 | apps/cli/bin/diffhub.mjs |
| Inline render ceiling, per file | 500 changed lines, or 500,000 bytes of patch | apps/cli/lib/diff-file-stat.ts |
| Comment store | .git/diffhub-comments.json, written atomically | apps/cli/lib/comments.ts |
- It generates no findings. If you want a model to review the code for you, that’s an AI code review tool, a different category.
- It’s 35.6 MB unpacked against revdiff’s single Go binary. If install weight matters to you, that’s a real reason to pick something else.
- It needs Node 20.11 or Bun 1.0.23 on the machine. There’s no standalone binary.
- cmux mode is macOS only and expects cmux.app at /Applications/cmux.app. Everywhere else, it’s an ordinary browser tab.
- A file with 500 or more changed lines, or 500,000 bytes of patch, isn’t rendered inline. Generated lockfiles and vendored bundles hit this constantly.
What else do people ask about reviewing AI-generated code?
Can AI review AI-generated code?
Yes, and it catches real bugs. It reviews the code against the code, though, so it can’t tell you the agent did work you didn’t ask for. Use it as a second pass, not the only one.
Does DiffHub review the code for you?
No. It shows the diff and keeps your comments. The findings are yours, and DiffHub turns them into one prompt the agent can act on.
Should you review agent-written code if the tests pass?
Tests tell you the code does what the tests say. They don’t tell you the agent touched forty files where three would’ve done, or that it deleted a check it couldn’t satisfy. Read the diff.
Is it safe to review private code this way?
DiffHub runs on 127.0.0.1 and makes no outbound requests, so the diff never leaves your machine. An AI reviewer has to send the code to a model, so check where that model runs before you point it at private code.
Are these diff tools free?
revdiff, hunk and DiffHub are MIT licensed and free. cmux diff ships with cmux. git diff is git. Licences read from the projects’ own pages on 2026-08-10.