Vibe CodingMay 12, 20265 min read

The Spec File Trick That Cuts My Claude Rewrites in Half

Stop describing features in chat. Write a spec file first, then point Claude at it. Here's the exact structure I use.

Most of the time when Claude produces garbage code, it's not Claude's fault. It's mine. I gave it a vague request, watched it guess, then got annoyed when the guess was wrong.

The fix isn't better prompting in the moment. It's writing a spec file before you start the work.

Why Chat-Driven Development Breaks Down

You open Cursor or Claude Code, type something like "add a webhook endpoint that handles Stripe events and updates the user's plan in Supabase," and hit enter. Claude goes off and builds something. Maybe it's close. Maybe it picks the wrong table. Maybe it forgets you already have a webhook handler and creates a second one.

You correct it. It rewrites. You correct again. Twenty minutes later you have something that works but the code is a mess of patched assumptions.

The problem is you compressed three things into one sentence: what you want, how it should behave, and how it fits the existing code. Claude only got the first one.

The Spec File Approach

Before any non-trivial feature, I write a short markdown file in a specs/ folder. Then I tell Claude to read it and implement it. That's the whole trick.

The file isn't a PRD. It's not a design doc. It's a tight, opinionated brief that answers the questions Claude would otherwise guess at.

Here's the structure I use for almost every spec:

  • Goal: One sentence. What this feature does and why.
  • Inputs: What triggers it. API call, webhook, cron, user action.
  • Outputs: What changes in the system. Database writes, responses, side effects.
  • Files to touch: The actual paths. New files and existing ones.
  • Files NOT to touch: The ones Claude might wander into but shouldn't.
  • Edge cases: What can go wrong and how to handle it.
  • Out of scope: Things I do not want it doing right now.

That last one matters more than people realize. Claude loves scope creep. Tell it not to add auth, not to refactor the helper, not to add tests yet. Whatever you're not ready for, name it.

A Real Example

Say I'm adding a Stripe webhook handler. The chat-driven version is "add a Stripe webhook handler." The spec version is a 30-line file that says:

Goal: Handle customer.subscription.updated events to sync plan changes to our users table.

Inputs: POST to /api/webhooks/stripe with Stripe signature header.

Outputs: Update users.plan and users.plan_renewed_at in Supabase. Return 200 on success, 400 on bad signature, 500 on DB error.

Files to touch: app/api/webhooks/stripe/route.ts (new), lib/stripe.ts (extend).

Do NOT touch: lib/auth.ts, anything in components/.

Edge cases: Unknown event types should return 200 and log. Missing user should log a warning and return 200, don't error.

Out of scope: Other event types, retries, idempotency keys (next pass).

Now I run Claude with "implement the spec in specs/stripe-webhook.md." The output is almost always closer to right on the first try. And when it's not, I update the spec, not the chat.

Why This Works Better Than Just Better Prompts

A few reasons.

The spec is reusable. If Claude gets confused mid-implementation and loses context, I just point it back to the file. I don't have to re-explain.

It catches my own bad thinking. Writing the spec forces me to make decisions I'd otherwise punt on. Half the time I realize I don't actually know what I want until I try to write it down.

It's a paper trail. When I come back in two weeks and wonder why the webhook handler ignores certain events, the spec tells me. The git log doesn't.

And it makes sub-agents work way better. If I'm running parallel Claude tasks, each one gets its own spec. No bleeding between contexts.

The Part Most Skip Writing the spec is half of it. The other half is how you hand it to Claude and what you do when the implementation drifts. This is the workflow I run on every f...

This section is for Inner Circle members.

Get the full breakdown, exact prompts, and step-by-step workflows.

Unlock with Inner Circle →

Inner Circle members get the meta-prompt, the drift protocol, and the exact folder setup I use across every 47 Industries repo. If you're tired of fighting Claude's first-draft guesses, that's where it lives.

KZZY

Written by KZZY

47 Industries has been home since the beginning, from 3D printing operations to leading all software development across MotoRev, BookFade, and the 47 platform.

Ready to Build?

Get a quote on your project. We build websites, web apps, mobile apps, and SaaS products for businesses across Florida and the US.