DHH Hasn't Written a Line in Two Months. Here's What He Checks Instead.
Published on 2026-09-02
DHH, creator of Ruby on Rails, told Lex Fridman he hasn't typed a line of code shipping to Omarchy Quattro in two months. He runs 16 Agent threads in parallel — and watched Basecamp 5's architecture get destroyed by Vibe Coding PRs that each passed review. The lesson isn't AI vs. engineers. It's that the bottleneck moved.
DHH Hasn't Written a Line in Two Months. Here's What He Checks Instead.
David Heinemeier Hansson — the creator of Ruby on Rails, the CTO of 37signals, a man who has been paid to type code for 25 years — told Lex Fridman something in late August that should make every engineering manager uncomfortable:
"I have not written … any of the code."
He wasn't talking about autocomplete. He wasn't talking about a Copilot suggestion he pasted in. He meant that for the past two months, zero lines that shipped to Omarchy Quattro were typed by his own hands. Every line went through an Agent. He runs about sixteen Agent threads in parallel across four to five machines, and he built a small tool called Herdr to keep tmux sessions and notifications from driving him insane.
Thirteen months earlier, DHH was still dismissing AI coding as a distraction.
That is the story — not "AI replaces programmers." It's that the cost of writing just collapsed, so the cost of deciding what to write is now the whole game.
The Basecamp 5 case: every PR was right, the system was wrong
The most useful part of the interview isn't DHH's personal workflow. It's what happened to Basecamp 5.
The design team started using AI to submit pull requests. The pace picked up. Each PR, taken on its own, was defensible — somebody could explain why the change made sense. Tests passed. Reviews approved.
Then someone zoomed out.
DHH: "Those changes, taken together, destroyed the system architecture."
This is the failure mode that no individual contributor, no PM, and no Code Review will catch on its own. One Agent rewrote the login flow. Another refactored the cache. A third extracted a "shared" abstraction that wasn't actually shared. All three merged green. The login flow now assumes a cache contract that no longer exists. The cache calls a layer that two refactors ago was the database adapter. The "shared" abstraction is duplicated, with subtle naming drift, in four places.
DHH Hasn't Written a Line in 2 Months. What He Checks Instead
You don't see this in PR review. You see it in production at 2 AM, six weeks later, when the on-call engineer can't find the source of a bug because the source is in three different repos pretending to be one.
Local correctness is not global coherence. That's the sentence to write on every team whiteboard in 2026.
The architectural damage didn't come from bad code. It came from many good changes that lacked a shared constraint. The missing piece wasn't a better review process — it was a rule written before the Agents started, defining which boundaries could not be crossed.
What DHH still does by hand — and the rule he gives teams
DHH didn't quit engineering when he stopped writing code. He still reviews the architecture, the model layer, and any change touching critical business logic — line by line, when it matters. Ordinary code he lets the Agent run.
His formulation, paraphrased: implementation can be delegated, judgment cannot.
That sentence is the operating manual for the next five years of software work. It doesn't mean "the senior engineer must personally read every PR." It means the senior engineer must own the answer to three questions before any Agent starts work:
What are the boundaries this change is not allowed to cross? Models, schemas, contracts, rate limits, invariants.
What other Agents are touching this same surface right now? If two Agents think they own the same module, one of them is wrong before either starts.
What does "done" look like, beyond "tests pass"? What observable metric moves when this ships?
If those three answers aren't written down, the Agent isn't the bottleneck — your missing documentation is.
A useful diagnostic: if a PR from a junior developer and a PR from an Agent are reviewed identically, your review process is the problem, not the PRs. Code review was built for "did this human write something reasonable?" It was not built for "did five parallel Agents respect a shared boundary nobody documented?"
The sixteen-thread problem
DHH's daily setup is roughly sixteen Agent threads across four to five machines. That number is not a flex. It's a warning.
Humans can't attentively follow sixteen concurrent engineering conversations. The first thing that breaks is the bottleneck of "wait for the Agent, read the diff, send the next prompt." DHH solved the latency side with Herdr — Agents notify only when they need a human or have a result. The hard part is the architecture side.
The rule he ended up with, after watching this break a few times:
Safe to run Agents in parallel: dependency upgrades, test-writing, migration scripts, dedup, bug investigation, anything with a small blast radius and a verifiable output.
Not safe to run in parallel: anything touching shared state, shared schema, shared caches, or shared contracts. Even if the tasks look independent, the boundary between them isn't.
Worst of all: tasks that look independent but share a hidden contract. Two Agents refactoring "different" services that both call the same auth library. Both tests pass. Both ship. Production breaks because they picked different versions of the auth library's retry semantics.
If you can't write down, in one sentence, the boundary between two Agent tasks, you do not run them in parallel. You run them in serial against the same model of the system.
Every Agent thread must return four artifacts
The other thing that breaks fast is the handoff. An Agent finishes, dumps a diff into a chat window, and waits. Now the human re-reads the code, re-derives the context, re-checks the assumptions — at which point you haven't moved the bottleneck, you've just moved it.
DHH's workaround: every Agent thread must return four things, or the human doesn't accept the work.
Change summary — one paragraph, written for the human who wasn't there. What changed and why, in plain language.
Test result — what ran, what passed, what didn't, and what wasn't covered.
Risk callout — what could go wrong in production. Be specific: "this changes the order of writes in the migration, so concurrent requests during deploy might lose data." Not "be careful."
Rollback plan — what to do if it's wrong. Revert? Feature flag? Drain traffic? Schema migration forward-only?
Miss any one of the four, and the human re-enters the repo to fill it in. That defeats the point.
This sounds bureaucratic. It isn't. It's the minimum information density required to hand work between humans and Agents without losing context. The same rule works between human engineers, which is why code review templates keep growing — the template is trying to formalize what Herdr is trying to formalize for Agents.
Stop measuring code
DHH, on the most common engineering metric still in use:
"Lines of code is a stupid metric."
It's worse than stupid now. It's actively harmful. An Agent can generate thousands of lines in a day. If your team's review, performance, and OKR systems still reward line counts, you are paying people — human or Agent — to write maintenance debt.
5000 lines that don't move a user-facing metric, don't reduce incidents, and don't shorten the delivery cycle are not progress. They are scheduled work for the engineer who has to read them in six months. The engineer who deletes 300 lines and ships faster has done more for the company than the one who adds 5000.
The replacement metrics aren't new. They've always been the right ones, just buried under the easier proxies:
Did the user's problem get solved? Look at task completion, retention, support volume.
Is the change maintainable? Cyclomatic complexity, blast radius, mean time to understand a module.
Did online metrics move? Latency, error rate, conversion, whichever is the system's purpose.
Did the incident rate drop or rise? Including incidents that didn't page because someone caught them in review.
Did the delivery cycle shorten? From idea to production, not from "PR opened" to "PR merged."
If your team can't answer those five questions after a sprint, the problem isn't the Agents. It's that you've been measuring the wrong thing for so long that the truth hurts.
The job that survives, and the job that doesn't
DHH didn't dodge the employment question. Twenty-five years of typing code, and he said plainly: if he had to re-enter the job market today, getting paid for hand-coding would be hard.
"The mechanical process is under threat."
He's not wrong. The mechanical layer — translating a known intent into syntax, remembering the API, refactoring a known pattern — is exactly what Agents are good at. The interesting jobs that remain are not "faster typists."
What's scarce now:
Defining the problem. Most software failures start as vague asks ("make the dashboard faster") and never get sharper. The person who can turn vagueness into a precise spec, with measurable success criteria, is the one the Agents orbit.
Choosing the approach. There are usually three plausible architectures for any non-trivial change. Picking the one that survives contact with the next two years of requirements is craft, not typing.
Setting boundaries. "This layer cannot be touched" / "this contract is public" / "this data shape is frozen" — the rules that keep parallel Agents from collaborating to destroy the system.
Accepting the result. Reading what shipped, asking what could go wrong, and being the one who signs off. Not rubber-stamping. Owning.
These four things were always the senior engineer's job. The difference is that in 2026, they are all the senior engineer's job. The typing layer — which used to take 60-70% of the day — is now close to free. The four things above used to compete for the remaining 30%. Now they get the whole day.
That's not a smaller job. It's a harder one, because the cost of getting it wrong used to be limited by how fast you could ship a fix. Now an Agent can ship the wrong fix in seconds.
What to do on Monday
You don't need Herdr. You don't need sixteen threads. You do need four changes you can make this week:
1. Write the architecture constraint before the first Agent starts. If two PRs could disagree about a boundary, you owe the project a written rule, not a hopeful review. A short doc, called ARCHITECTURE_INVARIANTS.md, listing what is frozen. Read it before kicking off any Agent.
2. Run Agents in parallel only on independent state. Default to serial. When two tasks look parallel, ask: can they disagree about a shared contract? If yes, run them in series against a shared model of the system.
3. Make every Agent thread return four artifacts. Change summary, test result, risk callout, rollback plan. Paste this into the PR template. If a human engineer can't produce them either, you've just discovered a process gap.
4. Stop rewarding code. Start rewarding outcome. Pull lines merged out of performance reviews. Put problem-solved, online metric movement, and incident rate in. Do this in the next sprint planning. Don't wait for HR.
The thing DHH actually proved
DHH didn't prove that AI replaces engineers. He proved something more useful: when the cost of producing code collapsed, the work that mattered didn't shrink. It got harder.
The teams that lose in 2026 are the ones still rewarding typing. The teams that win are the ones that finally took seriously what good engineering managers have been saying for a decade — that the typing was never the point, the decision was — and started allocating the whole day to it.
DHH stopped writing code. He didn't stop engineering. The line between those two things just became the most important line in your org chart.
The story isn't "AI replaces programmers." The story is that the bottleneck moved, and most teams haven't noticed yet.