← Back to blog

Describe the intent and code comes out. The speed vibe coding unlocked, the gap that 'vibes aren't verification,' and the verification harness that fills it — with code.

· TRAIL Labs
Vibe CodingLLMVerificationworktree

Vibe Coding — Erasing the Friction of Building

> Part 2 of "The Evolution of Driving LLMs." ① Prompting · ② Vibe coding · ③ Agents · ④ Harness engineering · ⑤ Open models.

Part 1 covered the limits of a single prompt — no state, no tools, no verification. In the world of code, the first thing to shake those limits was vibe coding. In February 2025, a line from Andrej Karpathy became its name: "forget the code even exists, and fully give in to the vibes."

Describing intent produces code fast but breaks without verification; bolting an isolate-run-verify loop onto generation stabilizes it

What vibe coding unlocked — the friction of building vanished

The core of vibe coding is that it raised the level of abstraction by one notch. Where we used to write every line, now you state the intent — "I want to build something like this" — and the LLM fills in the code. You look at the result and steer it with words.

That solved two things. First, speed — prototyping dropped from hours to minutes. Second, access — you no longer have to memorize all the syntax; a clear intent is enough to make something. The friction of building fell away.

But vibes aren't verification

The catch is that vibe coding inherited one limit straight from prompting: the absence of verification. Code looking like it runs doesn't mean it's right.

  • **It looks like it works** — confirm only the happy path and it quietly breaks on the edge cases.
  • Code you don't understand piles up — you didn't write it, so you can't debug it, and technical debt accrues fast.
  • Security and correctness go missing — "it runs" and "it's correct" are different things, and vibes don't guarantee the latter.

The famous joke about vibe coding is "works until it doesn't." It works right up until it doesn't — and then nobody knows why.

Don't stop vibing — bolt on verification

The fix isn't to quit vibe coding. Keep the fast building, but add a verification loop after generation: intent → generate → actually run → verify → merge if it passes. This is the rule we use for code, too. Build in an isolated workspace, run it for real, and only then merge.

# ① Vibe: drop the output straight onto main — only *looks* like it works
# ② Harness: isolate → generate → verify by actually running → merge only if it passes
git worktree add ../wt-feature -b feature/x   # isolated workspace
#   (the LLM implements inside wt-feature)
cd ../wt-feature
pytest -q && pnpm typecheck                    # verify by *running*, not assuming
#   merge if it passes, retry if not — main never breaks

It comes down to one line: "don't finish on assumption — look at the real result." You lay a floor of verification under the speed vibe coding created. Isolation makes failure safe; running turns "looks like it works" into "it works."

To sum up

Vibe coding erased the friction of building, unlocking speed and access. But it carries prompting's "no verification" with it, so without a verification harness you get stuck at "works until it doesn't." Build fast, but isolate and run to verify — that's the hair's breadth that lifts vibing into real practice.

Up to here, a human ran the loop — we built, ran, and fixed. So what if the model runs the loop itself, using tools and observing results? That's the next part: agents.

More posts