← writing

Two kinds of vibecoder

Two devs ship the same feature with AI on a Tuesday afternoon. Six months later their repos look nothing alike. Here is what the careful one actually does.

It's Tuesday, 4pm. Two devs on the same team just told Slack they finished the same feature. Both used Claude. Both pasted the ticket in, both got a working diff back, both ran the app and saw the green checkmark.

Dev A is still in their editor. They're reading the diff. They renamed handleData to parseInvoiceRows because that's what it actually does. They deleted three try/catch blocks Claude added "just in case" around code that literally cannot throw. They wrote one small test for the one tricky bit. It took them maybe 45 minutes after the AI was "done".

Dev B already pushed. They're on the next ticket. Their PR title is the ticket number. The description is empty. The diff is +812 lines.

Both of them call themselves vibecoders. Only one of them is going to enjoy this codebase in six months.

Fast forward to December

Dev A's repo still feels like a place humans live. Files are named what they do. Deletes are easy because nothing is doing five things at once. New features land in a couple of days because the patterns are obvious. When a junior joins, they can read a folder and guess what's in the next one. The PRs are 200 lines and boring.

Dev B's repo is a museum. There are three logger libraries because Claude reached for a different one each time and nobody pushed back. There's a 4000-line component called MainDashboard.tsx that handles auth, routing, charts, and a websocket. There are 17 utility files named some variation of helpers, utils, and common. There's a folder called old that is two months old. Nobody touches the god-component because the last person who tried spent a day on it and gave up.

Same tool. Same models. Same six months. Wildly different outcomes.

The thing nobody wants to hear

The point of this post is not "don't use AI". I use it every day. I wrote a CMS with it. I'm using it to draft this post and I'll still rewrite half the sentences because the rhythm is off.

The point is that AI is the typist. You are still the engineer. Claude can produce a working diff in 30 seconds. It cannot decide whether that diff belongs in your codebase. That part is your job and it always was. Vibecoding doesn't remove the engineering, it just removes the typing.

The careful vibecoder treats the AI output the way a senior treats a junior's first PR. Grateful it exists, then ruthless about what ships. The rushing vibecoder treats it like a finished product because it compiles and the tests they didn't write are passing.

What the careful one actually does

None of this is clever. It's just the boring stuff, applied every single time.

  • Read every diff before commit. Not skim. Read. If you can't explain why a line is there, that line is not allowed in.
  • Rename whatever sounds off. data, result, handler, processItem. If the name doesn't tell you what it does, fix it now. You will not come back later. Nobody comes back later.
  • Delete the over-helpful error handling. Claude loves to wrap things in try/catch and swallow errors with a console.log. If the function can't actually fail, the catch is noise. If it can fail, the catch needs a real plan, not a shrug.
  • One test per touched function. Not a full suite. One test that pins the behavior you actually care about. If the AI breaks it next week, you'll know in 200ms instead of in production.
  • Keep PRs small. If your diff is over 400 lines and it's not a generated file, split it. Future you reviewing future you's 2000-line PR is a war crime.
  • Push back on the AI. If Claude reaches for a new dependency to do something you could do in 8 lines, say no. Every dep is a thing your team will maintain forever.

That's the whole list. It's not a methodology. It's just caring.

You can spot them in 10 seconds

I review a lot of PRs. I can tell which kind of vibecoder opened the PR before I read a single line of code. The rushing one has a one-word title, no description, 14 files changed, three of which are package.json, package-lock.json, and a new utility folder. There's a commented-out block at the top of one file. There's a TODO: fix later that will be there in 2028.

The careful one has a title that's a sentence, a description with the why, four files changed, and the diff reads like prose. You finish reviewing it in 4 minutes and feel slightly smarter than when you started. 🟠

Pick one

The tools are not the problem. They're genuinely incredible right now. Claude 4.7 can hold a whole feature in its head and ship it. That's wild. That's also exactly why the discipline matters more, not less. When the typing is free, the only thing left that matters is taste and care.

So pick one. You can ship faster than ever and still respect the codebase. Or you can ship faster than ever and leave a swamp for whoever comes next, including, mostly, future you.

I know which dev I want on my team. I also know which one I'm trying to be on a Tuesday at 4pm when I'm tired and the diff looks fine and I just want to close the laptop.

Want more like this?

Occasional, opinionated, no listicles.
all writing →