DEV Community

Twio_AI
Twio_AI

Posted on • Originally published at twio-ai-engineering.Medium

Can You Vibe-Code Without Understanding the Code? I Tried

Lessons from 100,000+ lines of LLM-written code at a two-person startup.

twio is an AI workspace for mortgage advisers, built by two engineers. Since our first commit in early 2026, the repo has grown to nearly 2,000 commits and over 100,000 lines of code — almost all of it written by LLMs. Along the way I reversed my position completely: I started out believing "if there's a bug, let the LLM fix it — why bother understanding the code?" I now believe you have to own every architectural decision the LLM makes, from day one.

I believed the promise

Vibe coding sounds irresistible: agents running in loops, code you never read, bugs pasted back for the model to fix. And on small web projects it genuinely works — the app runs, iteration is fast. I also let LLMs build things fully autonomously, with the same result: fine while the project was small, painful once it got complex or crossed a few tens of thousands of lines.

What I had missed is that the term was scoped from birth. When Karpathy coined vibe coding, he added a qualifier: "not too bad for throwaway weekend projects." I had absorbed the swagger and lost the qualifier.

The moment it flipped

What changed my mind wasn't a bug. It was an ordinary design discussion. The LLM and I talked through a feature, and it produced a plan that looked perfectly reasonable. Then it hit me: I had no way to tell whether the plan was sound — and no way to tell whether the code it produced was right.

I wasn't making an engineering decision. I was rolling dice.

You can shrug and trust the model; in a small project the cost of that is invisible. But as the codebase grows, the plans go wrong more and more often, until pretending stops being an option.

Why it breaks down

Three mechanisms, none of them bad luck.

The bottleneck moved; the cost didn't vanish. Vibe coding removes the cost of writing code. The cost of verifying it is merely deferred — with interest. Every piece of code nobody understands is a liability; small projects feel fast because the debt isn't due yet.

Errors compound. Every unreviewed diff adds a little entropy, and an LLM working in a messier codebase produces messier output. That's why the decline isn't linear — past some point it snowballs.

LLMs reviewing LLMs doesn't save you. I tried the review-agent recipes. They miss the problems that matter, because reviewer and author share the same blind spots. And human review has a prerequisite: you can't review what you don't understand.

Peter Naur said all of this forty years ago in Programming as Theory Building: a program's real substance isn't the code but the theory in its builders' heads — the architecture, the trade-offs, the why it's shaped this way. If every line is AI-generated and no human ever builds that theory, the code exists but the theory never did. My "can't judge the plan" moment was me discovering I held no theory.

Different symptoms, one disease

Use these tools long enough and you learn their temperaments. GPT loves sprawling master plans that ship code nobody asked for. Cursor's plans are sometimes pointed the wrong way, sometimes just under-thought. Claude tends to propose the safest plan, not the best one. And nearly all of them share one instinct: no bold refactoring — they hate deleting code, tiptoe around existing structure, and only ever add.

These aren't vendor bug lists. They're symptoms of one disease: there is no referee in the system. When nobody is present to ask "is this plan right? should this code die?", every model slides toward entropy.

Where vibe coding still wins

Prototypes, one-off scripts, spikes, anything you'd happily throw away and rewrite — vibe coding is the optimal strategy there, and I still use it that way. Karpathy's qualifier was right all along. The mistake is extending it to software you intend to maintain.

What we do instead

The principle is simple: the engineer owns understanding and decisions; the LLM writes the code. At twio that has settled into four habits.

Plans are signed off before code is written. Every feature starts as a design discussion; I judge the direction, surface the trade-offs, and make the call. Our working agreement — a CLAUDE.md loaded into every LLM session — requires the model to stop and ask the moment a plan starts getting complicated, instead of silently picking the heavier option.

Rules written against the model's instincts. The agreement's core clauses invert default LLM behavior: simplicity matters more than functionality; refactor, don't just accumulate; delete, don't preserve. Models add by nature, so deletion has to be written policy.

Review to understand, not to nitpick. Reviewing isn't hunting bugs line by line. It's staying fluent in the architecture — knowing what the code actually does — so that when the next plan lands, you can tell which approach genuinely fits the project.

One commit per stage. Big tasks are cut into small, self-contained increments, each type-checked and tested before its own commit. I never review one giant diff — only a chain of small ones I can actually read.

None of this stops the LLM from being wrong. It guarantees something better: when a mistake happens, someone who holds the theory is in the room. The architecture still lives in my head, and I can call every plan right or wrong.

The part that isn't outsourced

What AI makes obsolete isn't the programmer — it's the typing. Turning vague requirements into a precise spec, judging whether a plan is right, owning the outcome: none of that has been outsourced by an inch. With the marginal cost of producing code approaching zero, it matters more than ever.

Building twio taught me this the concrete way: you can outsource the typing, but not the understanding. And understanding has no shortcut — it accumulates from the very first line.

Top comments (0)