The most expensive bug I shipped last year took four days to undo, and I shipped it because I broke rule 12 of my own vibe coding best practices. The agent had handed me a one-line fix at 11pm. It looked fine. It passed the test I had written. I tapped commit and went to sleep feeling like the future had finally arrived.
The fix was wrong. Not subtly wrong, the kind of wrong where the cost of repair grows by the hour, like a small leak under a kitchen sink that you only notice when the floorboards start to bow. I had shipped a fix I did not understand. By the time I dug it out, I had not just lost four days of forward motion, I had also lost the trust of two early users who had been getting weird payment receipts.
This post is everything I wish someone had handed me before I started. These rules are what survived after 30 small-to-medium projects with Claude Code, Cursor, and a few weeks of stubborn experiments with agentic engineering on the side. They are not aesthetic. They are scar tissue.
I (Kai) wrote most of this. Priya jumps in around rule 8. Near the end we have a fight about one of the rules and we did not resolve it on purpose.
Why 15
Not 10. Not 20. Fifteen is what was left after I tried to write 30 and crossed off the ones that were really restatements of others, plus the ones that sounded smart on a Tuesday but failed me by Friday.
I tried to keep these as imperative sentences a junior engineer could pin to a monitor. If a rule needed three caveats and a chart to make sense, it was not yet a rule. It was a research note pretending to be a rule. The rules that survived feel almost embarrassingly obvious in hindsight, which is, I think, the right test.
I am not pretending these are the only best practices. They are mine. Yours will be slightly different. The point is to have rules at all, written down, before you sit at the terminal at 11pm with a deadline.
The 15 rules
Rule 1: Read every line the agent writes.
Every line. Not skimmed. Not "I will read it after the test passes." Read it before you accept the diff.
The thing nobody tells you about vibe coding is that the failure mode is rarely a typo or a missing import. The failure mode is plausible nonsense. A function that does almost the right thing, with a parameter inverted or a default that bites you only on a Tuesday in February. You will not catch this with tests, because you wrote the tests against the same wrong mental model.
I treat agent-written code the way an editor treats a freelancer's first draft. Friendly, but adversarial. I ask, line by line: "Why is this here? What does it assume? What happens if that assumption breaks?" This costs me about 25 percent more time than just hitting accept. It saves me roughly 4 hours of debugging per week. The math is not close. Read every line.
Rule 2: Test before you trust.
A green test is not a guarantee. It is a hypothesis that has not been falsified yet.
This is the rule I broke when I shipped the four-day bug. The agent wrote a test, the test passed, and I treated "passes" as "works." Those are not the same word. The test only tested the case I thought to mention. The bug lived in the case I forgot.
Now I add an adversarial step. After the agent writes a feature plus tests, I ask it for three failure modes that the current tests would not catch. Then I write tests for those, by hand if I have to. About one in three answers exposes a real gap. The remaining two thirds are usually paranoia, which is fine. Paranoia is cheap. Production fires are not.
If you only adopt one rule from this post, this is the one. Tests are not trust. Tests are how you decide whether to start trusting.
Rule 3: Your CLAUDE.md is your contract.
CLAUDE.md is not documentation. It is a contract between you and the agent about what good code looks like in this project. Stack, conventions, banned patterns, the things you keep correcting it about.
The day I started taking my CLAUDE.md seriously was the day my context bills dropped by a third. I was paying, every session, to re-explain that we use pytest not unittest, that we never mock the database, that all dates are stored UTC, that error responses follow a specific envelope. None of that was load-bearing context for the agent to figure out fresh. It was my job to write it down, once, and let the file do the talking forever after.
If you want the long version, the definitive guide to CLAUDE.md and rules files covers structure, hierarchy, and the gotchas. The short version is: if you have explained the same convention to your agent twice, the convention belongs in CLAUDE.md before the third time.
Rule 4: Plan before you code, especially with /ultraplan.
There is a temptation, when you have an agent that can produce code in seconds, to skip planning. Why plan when you can prototype?
Because prototypes lie. They tell you the thing is easy when actually you have just dodged the hard part. I have lost more weekends to "let me just try" than to any other failure mode. The agent will happily build the wrong thing very quickly.
For anything that touches more than two files, I run ultraplan in the cloud first and read the plan before I let the agent write a single function. The plan usually surfaces a question I had not thought of, like "what happens to existing rows when you add this column" or "this endpoint is rate-limited and your retry loop is going to get you banned." Ten minutes of planning has saved me, on average, three hours of unwinding per feature. That is a 18x return on the cheapest possible investment. Plan first.
Rule 5: One feature, one prompt, one commit.
The discipline that took me longest to learn. Vibe coding rewards a certain kind of monastic restraint that is the opposite of the dopamine the tool itself produces.
When you ask the agent for "the search feature plus pagination plus the email export plus a small UI tweak," what you get back is a tangle of changes that are impossible to review and impossible to roll back independently. If one of them is wrong, all of them are wrong, and your git history is a single 1,200 line commit titled "search stuff."
One feature. One prompt. One commit. If the agent drifts and starts adding scope, I cut the session and start fresh. The git log of a healthy vibe coding project looks like a stenographer's notebook, lots of small clean entries, each one a sentence you can read without context. The git log of an unhealthy one looks like a ransom note.
Rule 6: Keep your prompts boring; let the work be interesting.
Early on I treated prompts like little essays. Tone, framing, motivation. "We are building a beautiful, modern reservation system that..." As if the agent needed to be inspired.
It does not. It needs to be briefed. The best prompts I write now read like internal tickets at a boring company. Goal, constraints, files to touch, files to leave alone, definition of done. Two paragraphs, maybe three. No flourishes.
The work, the architecture, the trade-offs, those are where your creativity goes. Not into the prompt. A boring prompt produces predictable output, which is what you want at 11pm with a deadline. An interesting prompt produces a surprise, and surprises in production are almost never the good kind. I think of it like aviation checklists. The pilots who survive long careers are the ones who run the same dull script every flight, even when they have flown the route a hundred times.
Rule 7: Save the failure modes as memories.
Every project I have run for more than a month has accumulated a handful of "Claude does this wrong every time" moments. The Postgres date column it keeps interpreting as a string. The fixture it keeps reaching for that I deleted three months ago. The Tailwind class it insists is real but is not.
These belong in memory. The full mechanics live in the persistent context deep dive, but the rule itself is short: when the agent makes the same mistake twice, do not correct it a third time without writing it down. The third correction is the loudest signal you will ever get. Ignore it and you will spend the rest of the project paying tax on a fact you already learned.
I keep a .claude/memory/lessons.md file in every project now. Each entry is two sentences. "Claude likes to use datetime.utcnow() here. Use datetime.now(timezone.utc) instead." That is it. Boring. Effective.
Rule 8: Treat the agent like a junior teammate, not a senior one.
The agent is fast and confident. Those are also the two qualities of a dangerous junior engineer.
When a senior teammate hands you code, you skim it, ask one or two questions, and merge. When a junior teammate hands you code, you read every line, ask about edge cases, make sure the tests are real, and gently push back on choices that look elegant but are actually clever for cleverness's sake. Vibe coding works when you bring the junior teammate posture to every session.
This is the rule Priya and I argue about, so I will let her tell her version below.
Priya here: the rules I had to unlearn from traditional engineering
Kai handed me the keyboard. Hi.
I came to vibe coding from twelve years of Django, where the engineering culture I grew up in had its own rituals. Code review by humans. Pair programming. Architecture decision records. Slow. Deliberate. I assumed all of that would map directly onto agent-assisted work. Most of it does not. The rules I had to unlearn were as important as the ones I picked up.
The biggest one for me was rule 9.
Rule 9: Worktrees, not branches, for parallel work.
In traditional engineering you switch branches all day. git checkout feature/x, do some work, git checkout main, pull, switch back. The cost of switching is annoying but small. Your editor reloads, your tests re-run, you get on with it.
With agents in the mix, branch-switching is poison. The agent has built up context about the files you were touching, the patterns it noticed, the failing test it was midway through fixing. Switching branches throws all of that away, and the next session you start, you pay to rebuild it from scratch. I was burning through tokens like a teenager with a credit card.
Worktrees changed everything for me. Each feature gets its own folder, its own agent session, its own warmed-up context. I switch by changing terminal tabs, not by checking out branches. The mental model is closer to a gardener with multiple raised beds than a coder with one workbench. Each bed has its own soil. You move between them. You do not till them all into one patch.
Rule 10: Re-read your own code at the end of every session.
This is the one I find hardest to do, and the one that has saved me the most.
At the end of a session, before I close the terminal, I git diff and read every line that landed today. Not the agent's output, mine. The decisions I authorized. The trade-offs I waved through because I was tired. About once a week I find something I would not have shipped in the morning. I revert it on the spot, leave a note for tomorrow's me, and go to bed.
The reason this works is that the version of me at 11pm is different from the version of me at 9am, and the morning version is the one whose name is on the commit. If I would not let agent code through without review, I should not let tired-me code through without review either. Same posture. Same suspicion. Same kindness.
Okay, Kai, back to you.
Kai again
Thanks. Picking up at 11.
Rule 11: Cost is feedback. Watch the meter.
Your token bill is not a tax. It is a signal.
A session that costs six dollars is not bad because of the six dollars. It is bad because something in your workflow burned the model's attention on the wrong thing. Maybe you re-explained your stack three times. Maybe the agent spelunked through a folder you should have excluded. Maybe you let it generate a 400 line refactor that you should have scoped down to 80.
I check costs at the end of every project week now. Not to feel guilty, to learn. The pattern I notice most: the projects where I skipped CLAUDE.md cost about 2.3x more than the ones where I kept it tight. That is not a vague feeling, that is a number from my Anthropic dashboard. The real cost analysis post goes deeper into the patterns. The rule is short. Watch the meter, and treat surprise spikes the way a sailor treats a sudden drop in wind. Something has changed. Find out what.
Rule 12: Refuse "magic" answers. If you do not understand the fix, do not ship it.
This is the rule I broke for the four-day bug. It is the rule I think about most.
Agents will sometimes hand you a fix that works and you cannot explain why. The instinct is to ship it because the test is green and the demo is on Friday. Resist. If you cannot explain the fix in plain English to a teammate, you do not understand the bug. If you do not understand the bug, you do not know what else it broke. You only know that one symptom went away.
The discipline is small. After the agent proposes a fix, I make myself write a one-paragraph explanation, in my own words, of what was wrong and why this resolves it. If I cannot, I ask the agent to explain, and I keep asking until the explanation lives in my head, not just on the screen. The debugging vibe-coded apps survival guide walks through this in more detail. It is not about being clever. It is about not shipping mysteries.
Rule 13: Pair vibe coding with version control discipline.
Commit small. Commit often. Branch before risky sessions. Push at the end of every day.
Vibe coding makes it psychologically easy to skip these steps because the agent moves so fast you forget to pause. But the moment things go wrong, version control is the only undo you have. I have seen people lose two days of work because they "were going to commit at the end" and then the agent rewrote three files at once in a way they did not realize.
My rough guideline: if you have been at the terminal for 20 minutes without a commit, something is off. Either you are doing too much in one go (see rule 5), or you are not pausing enough to read what landed (see rule 1). The git log is your safety net and your memory and your pair programmer all at once. Treat it with respect, even when, especially when, the agent is making it tempting to forget.
Rule 14: Build the smallest thing that proves the idea.
Of the 30 projects I am drawing rules from, maybe 6 became real things people use. The other 24 were experiments that taught me something and then got shelved.
Vibe coding tilts you toward overbuilding. Because each component costs almost nothing to add, you start adding them. Auth, why not. Email, sure. A nice settings page. A dark mode toggle. Suddenly you have built a small SaaS instead of a one-page test of a hypothesis.
I now ask one question before any new project starts: "What is the smallest version of this that would tell me whether the idea is alive?" For most things, the answer is a single page with one form and a CSV file as the database. If the smallest version is boring, the bigger version probably will be too. If the smallest version makes people pull out their phones to show their friends, you have something. The first-app guide for beginners is structured around exactly this principle. Build the proof, not the product.
Rule 15: The rule of three. If you have explained the same thing three times, write it down.
This is the meta-rule, the one that generates new rules.
The first time I notice a pattern I tolerate it. The second time I get mildly annoyed. The third time it goes into CLAUDE.md, into a memory file, or onto a sticky note above my monitor. The rule of three is how my CLAUDE.md grew from 14 lines to about 80, and how my memory folder grew from empty to genuinely useful.
The deeper point is that vibe coding only compounds if you let it. If you correct the same mistake every session, you are running in place. If you write it down once and never correct it again, your future sessions get cheaper, faster, and better without any new effort. This is the entire game. The rule of three is what turns a tool into a practice.
The rule we keep arguing about
Rule 8. Junior teammate, not senior.
Priya thinks I am being too suspicious. Her view is that "junior teammate" produces a kind of low-grade paranoia that slows you down on tasks where the agent is genuinely competent. "You read every line of a CSS change?" she asked me once. "Yes," I said. "That seems like a waste." She would prefer something like "treat the agent as a senior on small surface-area changes and a junior on anything that touches state."
I think she is half right and I cannot quite let go of the rule. The reason is that I am bad at predicting which changes are small surface area. The CSS change that broke our login last quarter was a CSS change. The one-line config edit that took out staging was a one-line config edit. The cost of being wrong about "this is a small change" is asymmetric. Wrong on the small side, you waste a minute reviewing trivial code. Wrong on the big side, you spend a weekend with a fire extinguisher.
We have not resolved it. We probably will not. Some rules are temperaments more than truths, and the honest move is to flag them as such instead of pretending we have the answer.
A boring closing
There is no triumphant ending here. These are 15 rules I keep on a single index card next to my keyboard. They will be 14 rules in a year, or 17, depending on what the next 30 projects teach me.
If you are just getting started, what is vibe coding lays the groundwork. If you want more tactical advice, the 50 Claude Code tips post is a much longer grab bag. If you want the official source on the tools themselves, the Claude Code documentation and Anthropic's engineering blog are both worth a slow read on a Sunday. Stack Overflow's 2025 developer survey is the best public data I know of on how the rest of the industry is actually using these tools, which is a useful sanity check against your own habits.
We would love to hear your rules. Especially the ones you broke to learn. Tell us the four-day bug. We will tell you ours.