How to vibe code (and not lose control)
People keep asking me what course to take. Here's the course: install any agent, write a prompt. That's it.
People ask me this constantly — inside the company, outside, at events. How do I use Claude Code. What do I need to learn for Cursor. Can I recommend a course, a training, a bootcamp.
Usually mixed with distrust. You watch someone claim they solo-build complex systems with an agent, and it feels like there must be a secret. A hidden technique. A magic prompt nobody’s sharing.
Two years ago, there was some truth to that. Generating code with AI in 2024 required prompt engineering skills and creative workarounds. You had to know model quirks, work around context limits, structure requests in very specific ways.
That’s over.
As of February 2026 — models got smarter, agents got tools (MCP, skills, tool use), and they follow instructions reliably. Pick any agent: Cursor, Claude Code, OpenAI Codex, Antigravity with Gemini. Write what you want in plain language. Get a swarm of agents solving your task.
Want to use autonomous agents? Install Cursor. Done. Stop reading.
Still here?
Good. Because the real question was never “how do I start getting results.” Any tool gives you results on day one.
The question is: how do you make those results repeatable? How do you keep the codebase from rotting? How do you not go bankrupt on tokens?
Three ways it goes wrong
I’ll start with my own failures.
The $87 loop. Agent got stuck in a refactoring cycle. 45 minutes, $87 in tokens. I noticed by accident — checked the dashboard for an unrelated reason. Without hard spending caps, you find out from the invoice. Some teams burn through $6,000/month this way, most of it on loops that produce nothing.
The QA database. I missed a db:drop in a Makefile. The agent suggested it, I approved without reading carefully, went on to the next task. Twenty minutes later: “did you just drop the entire QA database?” The agent acts. You trust. That’s the root cause of every agent accident.
The rot. A week of productive vibe coding. Everything works. Tests pass. Three weeks later — duplicated logic in four places, three different patterns for the same abstraction, config values hardcoded in a dozen files. Technically correct. Practically unmaintainable.
None of these are tool problems. The agent did exactly what I asked. I didn’t ask for the right things.
Principles
Tool-agnostic. Work the same in Cursor, Claude Code, Codex, or whatever ships next month.
1. Context beats prompt
The agent doesn’t analyze your goal. It continues your input. Everything unstated gets ignored or hallucinated.
A brilliant prompt with no context produces generic code. A mediocre prompt with good context — architecture docs, naming rules, existing patterns — produces code that fits the system.
This is why experienced engineers get better results. Not prompt skills. Better context.
Before you start prompting — set up rules files, an architecture doc, examples of existing patterns. The agent should know the rules before it writes a line.
Most common failure: “the agent will figure it out.” It doesn’t. Vague context produces code that’s technically correct and fits nothing.
2. Architecture before code
Define the structure first: layers, components, responsibilities, boundaries. Without this, you can’t even verify whether the output fits.
The most expensive failure mode in AI-assisted development isn’t wrong syntax. It’s wrong integration. Code that works in isolation and breaks everything around it — ignores an existing cache, duplicates logic from a utility, doesn’t follow the ORM’s conventions.
Fix the architecture before the first prompt.
3. One prompt, one job
Multiple goals in one prompt → the agent averages or loses focus. UI + API + data model in one request = mediocre everything.
One task, one level of abstraction, clear input and output. Need multiple layers? Do them in sequence. This keeps behavior predictable and review easy.
Common trap: “Refactor this.” No goal → random changes, surface renames, pointless restructuring. Be specific: “Remove duplication in SchemaMapper. Extract field comparison into a separate function. Leave the rest unchanged.”
4. First attempt is a draft
Not a failure. A draft. The natural cycle:
prompt → generate → review → correct → repeat
Expecting one-shot results is the most common mistake I see. The tool isn’t broken — you haven’t formulated the task precisely enough yet. Control comes from a repeatable process, not from the first try.
Related mistake: fixing symptoms. Bug surfaces, agent patches it, bug returns next week. Diagnose first: “Find the root cause, provide analysis, don’t write code yet.” Then fix.
5. Agents over-complicate by default
Given freedom, agents reach for libraries, abstractions, and patterns that aren’t needed. Not a bug — default behavior. The training data is full of framework code, so the model defaults to frameworks.
Your job: set boundaries. Allowed dependencies, code style, level of generalization. Without constraints, you get a solution more complex than the problem.
Define output before you start. “detect_schema() returns a JSON array with fields name, type, unit. It will be serialized to YAML for the UI.” Expected format, type, usage context — stated upfront. Without this, the output looks fine and doesn’t integrate.
The workflow
Scale this to the task. A one-line fix doesn’t need a plan. A feature that touches eight files does.
Research
For non-trivial work — make the agent study the codebase first. Not skim. Study.
“Read this module” produces skimming. “Study the payment processing flow in detail — data model, queue integration, error handling — write a report in research.md” produces understanding.
The written artifact is the point. Not a chat summary — a file. You read it, verify the agent actually understood the system, catch misunderstandings before any code exists. If the research is wrong, the plan will be wrong, and the implementation will be wrong.
For small tasks — skip this. For anything that touches multiple files or existing patterns — don’t.
Plan
Implementation plan in a markdown file. Not in chat — a file you can open, edit, and send back.
Should include: approach, files to modify, code snippets showing changes, trade-offs considered. One trick that consistently improves plans: give the agent a reference implementation from another module or open source. “This is how they handle pagination. Plan how we can do something similar.” Agents build on concrete references better than they design from scratch.
Annotate
Open the plan. Add notes directly into the document. Correct assumptions. Reject approaches. Add constraints.
Real examples:
“use drizzle:generate for migrations, not raw SQL”
“no — PATCH, not PUT”
“remove caching entirely, we don’t need it”
“the queue already handles retries, this is redundant — remove it”
Send back: “I added notes. Address them. Update the plan. Don’t implement yet.”
That last sentence is the guard. Without it, the agent starts coding the moment it thinks the plan is acceptable. It’s not acceptable until you say so.
This cycle runs 1–6 times depending on complexity. Each round takes a generic plan and shapes it to fit your system. The markdown becomes shared state between you and the agent — you think at your own pace, annotate precisely, re-engage without losing context.
Implement
When the plan is right: “Implement everything. Mark tasks as completed. Don’t stop. No unnecessary comments. Run typecheck continuously.”
By this point, all decisions are made. Implementation is mechanical. That’s the goal — make the coding part boring. All creative work happened in the annotation cycles.
Iterate
Your role shifts from architect to supervisor. Corrections become terse:
“You didn’t implement deduplication.”
“This belongs in the admin app. Move it.”
“wider”
“2px gap at the top”
Reference existing code constantly: “This table should look like the users table — same header, same pagination.” More precise than describing from scratch.
If the agent went in a wrong direction — don’t patch. Revert. “I reverted. Just the list view now, nothing else.” Narrowing scope after a revert beats fixing a bad approach.
What to set up once
Rules files. Code style, naming, allowed dependencies, testing patterns. In Cursor: .mdc files. In Claude Code: CLAUDE.md. Format doesn’t matter. Having them does.
Architecture doc. Three questions: What layers exist? What’s stable vs. changing? What boundaries can’t be crossed?
Naming conventions. Without them: StuffManager, MyUtil, HelperService. With a rule like [Entity][Role] you get UserFetcher, TokenValidator. One example beats ten explanations.
Config separation. Thresholds, paths, feature flags — in config files, not in code. Without this rule, the agent hardcodes everything. You’ll find magic numbers in production six months later.
When to skip all this
For bugfixes, small tweaks, well-understood changes — just prompt and go. The full workflow is overkill when the blast radius is small and the pattern is obvious.
I don’t have this perfectly calibrated. The annotation cycle is the best approach I’ve found for features, but on small teams moving fast it can feel heavy. I’m still tuning where the cutoff is. A one-line fix doesn’t need plan.md. A new feature that touches eight files does. Everything in between — use judgment.
Part 2 covers Cursor-specific setup. Part 3 covers Claude Code workflow. Coming soon…


