Most people who „vibecode" today make the same mistake. They open an agent, type „build me an app" and wait for magic. For a while it looks magical. Then it falls apart in production and the code is a mess.
I do it the other way around. Before the agent writes a single line, most of the work is already done. It isn't about prompting. It's about laying the rails the agent then runs on by itself. Here's how it looks for me.
1. I don't start with code. I start with the problem.
The first thing isn't „write me X". I sit down with Claude and we break apart what I'm actually solving and why. The real problem, the options, the risks. Only once the intent is clear do I deal with the how. An agent is only as good as the brief it gets. Vague prompt = vague result.
2. Specs and guardrails, not „just figure it out"
This is where I spend the most time, and it's the most important part. I set the rails like this:
- the language and framework version (I run top of the top, but functional, not hype that breaks in a month),
- the architecture and conventions (strict for me: max 300 lines per file, KISS, DRY, no cleverness),
- what must not change and where the agent should stop and ask.
I keep CLAUDE.md short and to the point. There is no magic line limit, but a bloated file won't be read properly even by the agent, so I split it. My setup looks roughly like this:
CLAUDE.md # short project context
.claude/
rules/
testing.md # how and when we test
conventions.md # style, file boundaries
agents/
reviewer.md # review subagent
And the key distinction most people miss: CLAUDE.md is advice, a command hook is the guarantee. The things that truly must not fail (run tests before commit, don't write outside src/, don't start a migration without confirmation) don't belong in instructions. The agent can „reason" its way around them. They belong in a command hook, a plain shell command that runs deterministically outside the agent's reasoning. For example a checkpoint after every session:
// .claude/settings.json
{
"hooks": {
"Stop": [{
"hooks": [{ "type": "command", "command": "bash scripts/auto-commit.sh" }]
}]
}
}
The agent finishes, the hook deterministically saves the state to git. You never lose work in progress. CLAUDE.md is the project's memory, the hook is its reflex.
3. The plan, and let it get torn apart
Before any code I run plan mode (a read-only mode where the agent only analyzes and touches nothing) and have it write a plan.
Then I do the thing most people skip. I throw that plan at several models and let each one tear into it. For me that's Claude Opus, Sonnet and Haiku, and then I run Codex on it too. Each finds a different hole: one the architecture, another an edge case, a third security. I rewrite the plan from their notes. Only then the first line of code.
And that this isn't theory? This very article went through exactly that. I ran it past several models and two of them independently and identically caught a factual error I would have shipped otherwise. I do the same with a code plan. An hour on the plan saves a day of fixes.
4. Only now the code, and not one agent
Once the rails are up, writing the code itself is almost boring. And that's the point. I don't run a single agent: during focused coding I have about three projects going at once, some with several agents I manage like a dispatcher. A complex task doesn't fit in one context window, so I split it across several agents, each with its own context.
What holds it together are fast feedback loops: fast tests, fast compilation. When the agent gets a response in seconds, it flows. When it waits minutes, it breaks on patience.
What didn't pay off
No hype without the other side. Stuffing the agent's context to the brim is the road to hell, less and precise is better. And vibecoding without knowing how to code is a trap. The one who gets the most out of agents is the one who can build without them. If you don't know what the result should look like, you won't notice the agent handed you a stripped down version.
My checklist before I let an agent touch code
- I know what problem I'm solving (not just „what I want to build")
- Stack and versions pinned
CLAUDE.mdshort, rules split into.claude/rules/- Command hooks for what must not fail (tests, write boundaries)
- The plan survived critique from several models
- Fast tests are running
The winner is the one who can build an environment where the agent can't do real damage and knows exactly what you want. Anyone can prompt. Not this.