An optimistic, yet opinionated take on Vibe Coding

I’ve been exploring different dimensions of Vibe Coding over the past couple of months. It’s a nuanced topic, yet it often gets framed in extremes. The discussion surrounding it are hyperbolic to say the least. At one end of the spectrum, we hear about PMs spinning up full-stack products over a weekend and landing YC funding. At the other, veteran engineers—who arguably stand to benefit the most—dismiss it outright.

My goal here is to share my experiences -in a grounded yet opinionated manner.

To start with, the term “Vibe Coding” was popularized by a coder of exceptional skill. If you’ve ever seen educational contents from Andrej Karpathy, you’ll notice how he casually condenses 25 lines of code into one—without a single syntax error. The vibe is strong. But how that vibe resonates can vary significantly from person to person.

Let’s dig into what actually influences whether we can “vibe” with code effectively.

The Generator-Verifier Gap Matters—A Lot

The concept of the Generator-Verifier gap emerged during the era of Generative Adversarial Networks (GANs). At its core, it reflects a fascinating asymmetry: an agent (human or AI) may be unable to generate a solution, yet still fully capable of evaluating, ranking, or verifying one. Think of a casual chess player who can’t come up with a grandmaster move—but can still recognize a good one when they see it.

In the context of Vibe Coding, the LLM is the generator. But what happens when the human prompter isn’t an effective verifier?

Verification can be defined in multiple ways, but one practical angle is test coverage. If a codebase passes all the tests, we might be tempted to assume it’s solid. However, that assumption hinges on how well those tests are designed. A weak suite of tests can mask a large Generator-Verifier gap, leading to unstable, unreliable software. From this standpoint, the ability to design (not necessarily write) effective tests becomes a key marker of a strong verifier. Another good aspect of taking a test-based approach is – it narrows down your potential entries into an unfamiliar tech stack (from learning perspective).

Treat Tests as Gradient Signals

Let’s continue with the test-driven perspective. One reason LLM coding agents perform well is because coding lends itself to fast, verifiable feedback via tests. But we can push this a step further. Suppose there exists, somewhere in the space of all possible codebases, an “ideal” one—highly scalable, robust, well-documented, and resilient to edge cases. That’s our global minimum.

In reality, we often settle for local minima—functional but far from optimal. Tests act like gradient signals in optimization: they nudge ua toward better solutions iteratively. So, it’s worth designing tests with this broader trajectory in mind. It’s very possible to write useful tests that, when taken together, offer no clear path to improvement. In the context of Vibe Coding, this can lead to frustrating dead ends and hard-to-maintain code.

LLMs Generate Reversions—They Don’t Revert

This is a subtle but important point. When we ask an LLM to “revert” some code, it often doesn’t really perform a Ctrl+Z – even if it has access to the CLI and filesystem. Rather, it mostly tries to regenerate a version of the code that resembles the prior state, but it often includes remnants of the rejected logic from the context window. The result is rarely a clean rollback. If we’re not careful, we can end up corrupting a perfectly working state—especially deep into a coding session.

Because of this, version control needs to be practiced more deliberately than ever. Commit frequently. Preserve working checkpoints—even minor ones. It’s a small discipline that pays off significantly when navigating the iterative nature of Vibe Coding.

I will keep adding new patterns here as I go.

Leave a comment