Vibe coding went from Andrej Karpathy’s tweet to Collins Dictionary’s Word of the Year in underneath twelve months. In Y Combinator’s Winter 2025 batch, 25% of startups had codebases that had been 95% or extra AI-generated. GitHub has reported that Copilot was accountable for a median of 46% of code being written throughout programming languages, and 61% in Java.
So sure, it has turn into the brand new regular and everybody’s doing it however sadly, most individuals are doing it badly. The instruments like Claude Code and Cursor are wonderful however most vibe coders use them like autocomplete on steroids, like a genie: simply immediate randomly and look forward to it to prepare dinner. But belief me the output seems to be loopy at first look till the codebase is a multitude the agent itself cannot navigate, lol.So on this information, we cowl 5 issues which may make you nearly as good as a developer who went to high school for this. Maybe higher.
1. Use CLAUDE.md and Rules as Persistent Context
# Project: Acme SaaS
## Stack
- Node.js + Express backend
- PostgreSQL with Prisma ORM
- React + TypeScript frontend
- Stripe for billing (worth IDs comply with format: price_[plan]_[interval])
## Key companies
- /companies/billing.py — all Stripe logic lives right here, don't create parallel billing code
- /companies/auth.py — JWT + refresh token sample, see present implementation earlier than touching auth
- /lib/db.ts — single Prisma consumer occasion, import from right here
## Conventions
- All API responses: { knowledge, error, meta } form
- Errors all the time use AppError class, by no means plain Error
- Every DB question wants specific discipline choice, no choose *
## Do not contact
- /legacy/funds/ — deprecated, being eliminated in Q3
- /auth/oauth.py — frozen till SSO ships
When you add a brand new service or set up a brand new conference, replace the file instantly. It turns into the agent’s reminiscence between classes.
One thing more: context rot is actual. A 2025 Chroma study of 18 fashions discovered measurable accuracy drops as conversations grew longer, even on easy duties. A 40-message session protecting three options is slower and fewer correct than three separate 15-message classes. Open a brand new dialog for every distinct process. Pin solely the recordsdata related to that process.
Build your individual zero-code agent totally free
Try right here
2. Make the Agent Plan Before It Builds
The default habits of each agentic instrument is to begin writing code the second you describe one thing. For a self-contained process like “add a field to this form” that’s superb however for something with actual scope it should create issues you don’t discover till you’re deep into the implementation.
Here is a concrete instance. You are constructing a crew invitation system: a consumer enters an e-mail, the system sends an invitation, the recipient clicks a hyperlink, creates an account, and will get added to the crew. Sounds easy however that function touches your customers desk, your groups desk, a brand new invites desk, your e-mail service, your auth movement, and your JWT era. If the agent misunderstands how your auth movement works and builds the invitation acceptance logic in opposition to a unique assumption, you’ll not discover out till the function is generally executed.
Before any function with scope, ship this primary:
Before writing any code: analyze the codebase, then give me a step-by-step plan
for constructing the crew invitation system. List each file you'll modify, each
file you'll create, each DB migration wanted, and any assumptions you're
making concerning the present code. Do not write code but.
A superb plan output seems to be like this:
Files to change:
- /routes/groups.ts — add POST /groups/:id/invite and POST /groups/accept-invite
- /companies/e-mail.ts — add sendTeamInvite() utilizing present Resend consumer
- /prisma/schema.prisma — add Invitation mannequin
Files to create:
- /companies/invites.ts — token era, validation, expiry logic
DB migration:
- invites desk: id, team_id, e-mail, token (distinctive), expires_at, accepted_at
Assumptions:
- Invite tokens expire after 48 hours
- Inviting an already-registered e-mail nonetheless goes by way of the invite movement
- No invite restrict per crew at the moment
Read that a few occasions and ensure: Is the 48-hour expiry proper? Did it miss the speed limiting you want? Is it utilizing the e-mail service accurately? Fix the plan earlier than a single line of code will get written.
The different facet of that is immediate specificity. The extra exactly you describe what you need, the much less the agent has to deduce.
| Vague | Specific |
|---|---|
| “Add payments” | Integrate Stripe Checkout for the Pro plan ($29/month). On success, set consumer.plan = ‘professional’ and consumer.stripe_customer_id. On cancellation redirect to /pricing. Use present BillingService in /companies/billing.ts. |
| “Build an API” | REST endpoint POST /api/experiences. Accepts { start_date, end_date, metric } in request physique. Validates dates with Zod. Queries the occasions desk grouped by day. Returns { knowledge: [{ date, count }], complete }. |
| “Fix the slow query” | The GET /api/customers endpoint takes 4 seconds. The customers desk has 800k rows. Add a database index on created_at and rewrite the question to make use of pagination (restrict 50, cursor-based). Do not change the response form. |
3. Use a Separate Review Agent for Security and Logic
Coding brokers are optimized to finish duties, to not perceive why each guardrail exists. Columbia DAPLab has documented recurring failure patterns throughout main coding brokers, together with safety points, knowledge administration errors, and weak codebase consciousness. That makes blind belief harmful: the identical agent that fixes a bug can even take away the test that was stopping a worse one.
The clearest actual instance of this: within the Replit agent incident of 2025, the autonomous agent deleted a venture’s major manufacturing database as a result of it determined the database wanted cleanup. It was following its optimization goal. It was additionally violating an specific instruction to not modify manufacturing knowledge. And sadly, no human reviewed what it was about to do.
The agent that wrote your code just isn’t in a superb place to catch its personal errors. Claude Code helps subagents: separate brokers that run in utterly remoted contexts with no reminiscence of what the primary agent constructed. You outline them in .claude/brokers/:
---
title: security-reviewer
description: Reviews code for safety points after implementation is full
instruments: Read, Grep, Glob
mannequin: opus
---
You are a senior safety engineer doing a pre-ship assessment.
For each route added or modified, test:
- Is authentication enforced? Can an unauthenticated request attain this?
- Is the consumer licensed? Can consumer A entry consumer B's knowledge?
- Is enter validated earlier than it hits the database?
- Are there any hardcoded secrets and techniques, API keys, or credentials?
Report: file title, line quantity, particular challenge, recommended repair.
Do not summarize. Report each challenge you discover.
After your major agent finishes constructing the invitation system:
Use the security-reviewer subagent on all of the recordsdata we simply created or modified.
Here is what an actual reviewer output seems to be like:
/routes/groups.ts line 47
Issue: POST /groups/accept-invite doesn't confirm the token belongs to the
e-mail handle of the logged-in consumer. Any authenticated consumer who is aware of a sound
token can settle for any invite.
Fix: Add test that invitation.e-mail === req.consumer.e-mail earlier than accepting.
/companies/invites.ts line 23
Issue: Token generated with Math.random() — not cryptographically safe.
Fix: Replace with crypto.randomBytes(32).toString('hex').
Neither of these would have been caught by the constructing agent. Both would have made it to prod.
Escape.tech’s scan of 5,600 vibe-coded apps discovered over 400 uncovered secrets and techniques and 175 situations of PII uncovered by way of endpoints. Most of it’s precisely this class of challenge, authorization logic that works functionally however has holes.
Build your individual zero-code agent totally free
Try right here
4. Prompt in Layers, Not in One Giant Spec
Role task modifications what the agent prioritizes. “Build this feature” and “Act as a senior engineer who has been burned by poorly tested payment code before. Build this feature.” produce totally different outputs. The second one will add edge case dealing with, write extra defensive validation, and flag assumptions it isn’t certain about. The mannequin responds to framing.
Build options in layers, not unexpectedly. The commonplace mistake when constructing one thing like a Stripe integration is to ask for the entire thing in a single immediate. You get code that compiles however has the billing logic, webhook dealing with, and database updates tangled collectively. Instead:
Prompt 1:
Set up the Stripe Checkout session creation solely.
Endpoint: POST /api/subscribe
Accepts: { price_id, user_id }
Returns: { checkout_url }
Do not deal with webhooks but. Do not replace the database but. Just the session creation.
Review that. Make certain the Stripe consumer is initialized accurately, the fitting price_id is being handed, the success and cancel URLs level to the fitting locations.
Prompt 2:
Now add the Stripe webhook handler.
Endpoint: POST /api/webhooks/stripe
Handle these occasions solely: checkout.session.accomplished, buyer.subscription.deleted
On checkout.session.accomplished: set consumer.plan = 'professional', consumer.stripe_customer_id = buyer id from occasion
On buyer.subscription.deleted: set consumer.plan = 'free'
Verify the webhook signature utilizing STRIPE_WEBHOOK_SECRET from env.
Review that individually, test the signature verification, additionally that the consumer lookup is appropriate.
Each layer is reviewable and has a transparent scope. If one thing is flawed you recognize precisely the place.
Use pseudo-code when you recognize the logic however not the implementation:
Build a charge limiter for the /api/send-invite endpoint.
Logic:
- Key: user_id + present hour (e.g. "user_123_2026041514")
- Limit: 10 invitations per hour per consumer
- On restrict exceeded: return 429 with { error: "Rate limit exceeded", retry_after: seconds till subsequent hour }
- Use Redis if out there within the venture, in any other case in-memory Map is ok
This is extra correct than “add rate limiting to the invite endpoint” as a result of you may have specified the important thing construction, the restrict, the error response form, and the storage choice. There is nearly nothing left to guess.
The majority of builders transport AI generated code spend average to important time correcting it. Only round 10% ship it near as is. Those are largely skilled Claude Code customers with tight CLAUDE.md recordsdata and structured construct classes.
Read each diff earlier than committing. git diff earlier than each commit. When the agent has modified a file you didn’t ask it to the touch, both the immediate left room for interpretation or the agent overreached. Both are value understanding earlier than the code goes anyplace.
{
"permissions": {
"deny": [
"/auth/oauth.py",
"/.env",
"/.env.production",
"/legacy/**",
"/migrations/**"
]
}
}
Oh, migrations deserve particular point out. An agent that may write its personal migration recordsdata can silently alter your database schema. Keep migrations out of attain and write them your self after reviewing what the agent constructed.
Test instantly after each function. Not as a separate process later, proper after. “Now write unit tests for the invitation service we just built. Cover: token expiry, duplicate invite to same email, accept with wrong user, accept with expired token.” The agent that simply constructed the function is aware of the sting circumstances. Ask for assessments whereas that context is dwell.
Build your individual zero-code agent totally free
Try right here
That’s it. Share with whoever wants it. Happy prompting!
