Vibe-coding is a horrible idea. So is dismissing AI-assisted coding.
TL;DR: Vibe-coding is a horrible idea. It adds unnecessary complexity, it doesn’t always follow instructions, and sometimes it just does incredibly stupid things. An equally horrible idea is throwing out the baby with the bathwater: assuming that AI assisted coding is a dead end. In skilled hands, it can lead to significant boosts in productivity and even code quality. Kind of like the way a chainsaw is both a marvel of modern productivity and can still be responsible for thousands of injuries every year.
Details
Chainsaws are an amazing technology. In the hands of someone skilled, a chainsaw allows you to chop wood 5 times as fast as an axe. In untrained hands, however, it is responsible for around 30,000 injuries a year in the US alone.
I see vibe-coding as essentially wielding a chainsaw blindfolded: you are trusting the chainsaw to do sane things, when chainsaws have several known failure modes. The most serious is what’s known as “kickback”: when all of a sudden the chainsaw jerks and if you’re not careful, can hit you in the face or chest.
Even basic understanding of kickback and how to avoid it makes a huge difference to the safety of chainsaws. For that reason, it’s important to understand what the failure modes of the current generation of AI-assisted coding are.
I’ve now completed 5 medium-size projects using Claude Code and Cursor, and here are the failure modes I’ve discovered so far:
10–20% “random acts of stupidity”
I have seen AI-assisted coding tools do insanely dumb things that really have you wondering what is going on in those billions of parameters. They seem to happen 10 to 20% of the time. I mean really stupid things, all of these are real:
- I point it and ask it to fix a bit of code, and instead of fixing it, it “mocks” it out.
- In change 1, it fixes the issue. In change 2 — immediately after change 1 — it undoes the fix.
- Randomly change constants. Especially if one constant is older. One particularly sore point is changing constants defining the version of an LLM to use. I’m usually using the latest version, and because it was trained before the latest version, it assumes the new version is a bug and “fixes” it.
The solution is simple: review every line of code that an AI coding assistant generates. No exceptions. Every time I have tried to do things in “vibe-code” style it has ended in disaster and took me several times longer than if I had reviewed the code all myself. This is akin to saying “don’t chainsaw while blindfolded, drunk or not paying attention.”
They add complexity
The solutions from AI coding agents are more complex than if a human had coded them. The code they generate often is duplicative. It frequently handles corner cases that are not at all likely.
They have a tendency to overengineer things instead of building up incrementally. In one case, I “vibe coded” a file, and then reviewed it carefully. I was able to reduce the file size from 700 lines to 300 lines with no loss of useful functionality.
Solution: pay attention, and don’t only look at the changes one by one. Every so often, take a step back and look at whether lots of small decisions add up to globally good decisions.
They don’t always follow instructions
This — for me — is probably the greatest annoyance, especially with Claude Code. You can tell Claude Code what it should do in a file called CLAUDE.md. Whether Claude Code will actually do those things is another matter entirely. I have told Claude Code repeatedly to not add fallbacks and to not concern itself with backwards compatibility. My CLAUDE.md has a ridiculous number of variants of “UNDER NO CIRCUMSTANCES WILL YOU ADD FALLBACKS” to it, but it still adds unnecessary fallbacks. I am not talking about useful fallbacks but more like “if a future version of Python has a bug” type fallbacks.
Solution: there is no solution for this other than … you guessed it … carefully checking every step it takes.
Chasing its own tail
Very frequently I will present an AI assistant with a debug log and ask it to fix it. Maybe 70% of the time it is able to fix it itself. But 30% of the time, it can get stuck chasing its own tail.
What I mean by this is that it will try to fix the bug, then realize that the change didn’t fix the bug. Then it tries to introduce a new fix that has the same issue. And then eventually, it ends up closing the cycle.
My rule of thumb is if the AI assistant hasn’t fixed the bug in 3 attempts, it will never solve the issue and you need to intervene: giving it a clue for it to follow, looking at the code itself, or telling it the direction it is heading is a dead end.
Then why use them at all?
Given these pretty significant issues, why would we want to use AI assisted coding at all?
I have seen a reactionary trend where people’s reaction to vibe-coding is to dismiss AI assisted coding altogether. That is the pendulum swinging too far in the other direction.
As with many things, the best approach is a happy medium.
Why?
It genuinely boosts efficiency
If and when I can avoid the traps above, there is little doubt that it boosts my efficiency by somewhere in the 3–5x range; depending on the stage of the project and the time. I recently completed a 5,000 line python project in 9 working days. And this is code I am happy with/proud of/is almost production quality — this isn’t experimental code. It’s code that I wouldn’t be embarrassed to show to another engineer I respect and ask them to review.
It improves code quality
This is perhaps the most subtle aspect of all: given the challenges above, how exactly, can this technology improve code quality?
The answer is that used correctly, it alters the landscape of being lazy. The sad reality (at least for this engineer) is that you sometimes incur technical debt because doing things “the right way” is just boring and time consuming.
But what if there is a tool that makes doing the right thing almost no harder than adding a TODO for yourself? Then you’re much more inclined to use it.
One of the reasons I don’t need backwards compatibility is because it is more efficient now to change every reference (even the complex ones) to code that uses latest version. I find myself undertaking refactors now that I would not have considered before.
Concluding thoughts
The efficiency boost of AI-assisted coding is too big to ignore: in skilled hands, the sheer amount of work you can get done with AI assistance is huge. In much the same way that humanity has moved on from axes to chainsaws, there’s little doubt all development will become AI assisted a few years from now. Yes there are still people who use axes, but it tends to be for specialized or niche reasons.
But if we are to use these techniques, we need to learn the right way to use these tools. Just as you would never use a chainsaw blindfolded because the chances of injury are so high, you should never use vibe-coding tools on production codebases.