Bram Cohen wrote a post this week calling the cult of vibe coding insane. The piece is sharp. He's right about the code quality problem. He's wrong about where the practice came from.
The practice isn't new. The name is. I started programming in 2011. In every year since, most shipping developers had a "just get it running, don't read it" mode. jQuery snippets pasted into a <head> tag. Top Stack Overflow answers copied verbatim. npm install pulling 1,400 transitive dependencies nobody inspected. The only change is the machine now types the snippet for you.
What's different is throughput. The slop budget that used to cap out at what one person could paste in a day now scales to ten times that, done by one.

What Cohen actually said
Cohen's definition: "you make a point of literally making no contribution to what's going on under the hood, not even looking at it." He's pointing at the Claude team's codebase, where he found structural duplication — "a lot of things that are both agents and tools" — that nobody wanted to identify because "Looking under the hood is cheating."
His conclusion is the part worth printing on a mug: "Bad software is a decision you make." Not the tooling's fault. Not the AI's fault. Yours.
His suggested fix is the interesting part. He doesn't say stop using AI. He describes his own practice — starting with "This function makes my eyes bleed," talking through the problem with the model, then having the AI do the cleanup. AI for the hands. Human for the eyes. That distinction is the whole argument.
You've been vibe coding for 15 years
Run the test on every era I've actually worked through:
jQuery, 2011. This was my first year writing code anyone paid attention to. The workflow was: find a plugin, copy the snippet into a <head> tag, confirm it worked. The plugin pulled in two more plugins you also pasted. Your site worked. You had no idea what ran on page load. Plugin directories had hundreds of files with copy-paste install instructions and zero explanation of internals. The rule was "if the thing moves, ship it."
Stack Overflow, 2012 onward. Top-voted answer. Paste. Works. Move on. Snippets got copied verbatim into production, often with the original variable names still in them. That was the norm, not the exception. Senior developers on your team did this. Principal engineers did this. The only people pretending otherwise were in the tutorials.
npm, 2014 onward. create-react-app. 250MB of node_modules. 1,400 packages. You read maybe two of them. In 2016 a single eleven-line package got unpublished and half the internet's build pipelines broke. The lesson wasn't that the author was wrong. It was that the average JavaScript project was shipping hundreds of dependencies it had never inspected.
In every era since I started, the median shipping developer had a "don't look under the hood" mode. The industry kept running. Some code rotted. Some got cleaned up later. The ratio held.
What changed in 2025 isn't the mode. It's the rate. One person with Cursor or Claude Code can produce the amount of unread code that ten people produced copy-pasting Stack Overflow. The mode scales. The cleanup doesn't scale the same way.
Where Cohen is right
He's right where long-lived code lives.
When you're shipping a throwaway script, nobody cares. When you're shipping a 30-line landing page for a campaign that ends in two weeks, nobody cares. When you're shipping the payments path for a company that's been running for a decade, somebody cares a lot.
The honest version of the rule: the longer the code lives, the more someone has to read it. Not you necessarily. Maybe future-you. Maybe the person who inherits it. Maybe the person who shows up at 2am because a customer is double-charged and the AI-generated SQL is clobbering a balance table.
This is what Cohen is protecting. He's not arguing against velocity. He's arguing against pretending review isn't a step.
A one-line fix that almost didn't happen
Yesterday I was working on a subsystem in nanika called nen — a background thing that watches mission outcomes and marks findings as superseded when a later run resolves them. The AI wrote a function called supersedeFindings. Takes a list of IDs and writes a reason code into the superseded_by column.
The code looked fine. The tests passed. Here's the SQL it generated:
UPDATE findings SET superseded_by = ? WHERE id IN (?, ?, ?)Review caught this. The UPDATE had no guard on the existing value. If a finding had already been superseded out-of-band — by a human marking it manual:false-positive or by a different mission writing mission:ws-abc — this UPDATE would overwrite that reason silently. The audit trail, which exists specifically to tell you who closed a finding and why, would get clobbered by whichever mission ran last.
The fix was one clause:
UPDATE findings SET superseded_by = ?
WHERE id IN (?, ?, ?) AND superseded_by = ''Five words. AND superseded_by = ''. Commit 76903e59.
Nothing about this is exotic. Any senior database person looking at a supersede operation asks "what if it's already superseded?" in the first thirty seconds. The AI didn't ask. The AI wrote the straightforward thing, which was wrong. The tests passed because the tests checked "does it update?" not "does it preserve prior state?" Review asked the right question.

This is what Cohen is pointing at. Not "AI is bad." The code was 95% there. The missing 5% is the part a human has to look at.
The thing that's actually new
The reason this conversation feels urgent now isn't that we invented a new bad habit. It's that the ratio changed.
Before AI, the rate-limiting step on unread code was how fast a human could paste. Now the rate-limiting step is how fast a human can review. Those are not the same speed. Review is slower than generation, always has been.
The honest framing: AI moved the bottleneck. It didn't invent the hazard. The hazard was already there in every npm install, every copied plugin, every drag-and-drop form. What's new is that the hazard comes faster, scales per-developer, and doesn't leave obvious attribution — you can't git blame an AI session.
Cohen's "bad software is a decision you make" lands harder now for the same reason a busy highway is deadlier than a quiet one. Same bad decision, more chances to make it.

What to actually do
I don't think you stop. I don't think anyone stops. The practice works — for the code that doesn't need to live. What I try to do, and what I think Cohen is pointing at, is draw the line more honestly.
For throwaway code: vibe away. Nobody cares.
For code that lives: read the diff. Ask the dumb question ("what if this field already has a value?"). Run the code against something real, not just the tests the AI wrote for itself. Keep the audit trail. Find the review gap and close it.
None of this is new either. What's new is how much is coming at you. The answer is the same answer it was in 2011 and 2014 and 2018: if you want the code to last, somebody has to read it.
You can decide who. You can even decide it's the AI. You can't decide nobody.