AI Code Review Caught the Bugs That Looked Completely Fine
AI code review is when you point a language model at your entire codebase and let it read every single file, line by line, looking for bugs, security holes, and dead code a human would skim past.
That is it.
No magic.
You just let a machine do the boring exhaustive read that you, a human with a to-do list, will never actually do.
This week I pointed one at the website you are reading right now.
mattkeddie.com.
The blog you are on. Built with Next.js and Supabase, running on Vercel.
I had Claude Code read the whole thing: 52 source files, about 6,400 lines of TypeScript.
One pass.
Here is exactly what it found, what I fixed, and the receipt.
The case study is the site you are reading
I did not test this on a toy project.
I pointed it at my own live site. The one earning my name in search.
In one pass it found 14 issues.
Most were small. Two were not.
The scariest bugs were not the ones throwing errors. They were the ones sitting there looking perfectly fine.
Let me show you the two that mattered, plus the security hole, because that is where the lesson lives.
The security hole nobody clicks until someone does
The first real find was an open redirect in the magic-link sign-in flow.
In plain English: when you sign in with one of those "click this link to log in" emails, the site sends you somewhere afterward.
A crafted link could have sent a just-signed-in user to a look-alike phishing page.
You log in. You trust the site. Then it bounces you to a fake one designed to steal what you just typed.
Found. Fixed. Same day.
You will never notice this kind of bug by clicking around. It only fires when an attacker builds the bad link on purpose.
That is the whole problem with reading code by hand. You test the happy path. The attacker tests the path you skipped.
AI code review found two features that were silently dead
Here is the part that changed how I think.
Two entire features on this site were dead. Not broken in a loud way. Dead in a quiet way.
The first was an SEO ranking tracker. It was broken in three independent places at once. Every single run processed 0 keywords. It ran. It reported success. It did nothing.
The second was an image and media library. Uploads were never recorded in the database. So the page always showed "no images." Forever.
Both of these looked idle.
Not broken. Idle.
An empty state that is indistinguishable from a failure state hides the failure.
You look at the media library, see "no images," and think "I just haven't uploaded any yet."
You look at the ranking tracker, see no movement, and think "I guess nothing changed this week."
Wrong both times. The features were corpses wearing a clean shirt.
Both fixed.
The publish button that lied
There was one more.
Clicking "publish" reported success. The post stayed unpublished.
The database update matched 0 rows because of a row-level-security rule, then returned "ok" anyway.
Green checkmark. Nothing happened.
This is the same trap as the dead features. Success that is indistinguishable from failure.
Fixed.
The receipt
Everything above got fixed and shipped the same day.
One pull request. 19 files changed. 458 lines added, 157 removed. Merged, deployed, and verified live in production.
Same day I started.
Not a sprint. A session.
"But I would have caught these eventually"
No, you would not have.
That is the uncomfortable part.
You do not click your own sign-in link with a malicious redirect attached. You do not stare at an empty media library and assume it is broken. You assume it is empty because you have not used it yet.
These bugs survived precisely because they look like normal life.
A human skips the boring exhaustive read. That is not a character flaw. It is just what humans do.
An AI does not skip it. It reads file 47 with the same attention as file 1.
That is the entire edge. It is not smarter than you. It is just willing to read all of it.
The reframe: idle is a disguise
Here is the one idea to keep.
A broken feature that errors is easy. It screams. You fix it.
A broken feature that goes quiet is the dangerous one. It blends into the furniture.
So stop trusting "looks fine."
The empty page might be empty. Or it might be a failure wearing an empty page as a costume.
The only way to tell the difference is to read the code that fills it. All of it.
How to run this on your own thing
You do not need permission and you do not need a big budget.
Open Claude Code, point it at your repo, and tell it to read every file and list the bugs, dead code, and security issues it finds.
Then fix them in the same session.
If you have ever built a free tool that quietly stopped working, like the SEO audit skill I shipped earlier, this is how you find out before a user does.
And if you want the same exhaustive read pointed at your processes instead of your code, that is the same muscle I used to turn workflows into repeatable SOPs.
Read everything. Trust nothing that looks fine.
This is the weekly habit, not a one-time scan
Every empty page is a question: is this empty, or is it broken and pretending?
The difference is not that I got smarter this week.
It is that I let a machine read the 6,400 lines I was never going to read myself.
That is the whole series. One expensive problem from my week, the exact tool, the exact fix, the receipt.
Every Friday. Five minutes. Use it Monday.