Every guide to spec-driven development tells you the same thing: write a spec before you let the agent write the code. What almost none of them tell you is what happens when you skip that step, because they’re written by tool vendors and workflow consultants, not by anyone who went and measured it. Across 26 real vibe-coded apps AxonBuild has audited, the ones built with no spec at all averaged 52 out of 100, and not one came out green. That’s the missing half of the definition: what shipping without one actually produces.
What is spec-driven development?
Spec-driven development is writing a checkable description of what the app has to do before the agent generates any of it: the behaviours it must support, the areas where a wrong-but-plausible change costs money or leaks data, and the test that proves it’s actually done. GitHub’s open-source spec-kit runs that as four steps: specify, plan, tasks, implement. Kiro, the spec-first IDE Martin Fowler examined alongside spec-kit and Tessl, collapses it to three: requirements, design, tasks. The tools disagree on shape and agree on the order. The spec exists before the code does, whether the agent reading it is Copilot, Gemini, or Claude Code.
Some people call this spec-first development instead of spec-driven development; the two names describe the same order of operations, and the order holds whether the spec came out of spec-kit, Kiro, or a markdown file you wrote yourself. Spec-driven development with Claude Code, or any other assistant, works the same way: point the tool at the spec file before you prompt the feature, and it reads the spec, builds against it, and the definition of done is still the checkable list, not how clean the demo looks.
A spec is the demo’s promise written down where a test can check it.
Spec-driven development vs. vibe coding: the difference is what you can check
A vibe prompt describes an outcome you can see: a page that loads, a button that works. A spec describes an outcome you can verify. Where a vibe prompt says “add a login page,” a spec says “a session cookie a server checks on every protected route, proven by a test that hits one with no session and gets refused.” Both can produce code that runs on the first try. Only one produces code you can prove runs correctly, because only one names the thing that has to stay true and gives you a way to check it stayed true.
The right column is the same feature. It just says what has to be true and how you’d find out if it wasn’t.
What spec-less shipping actually produces
Spec-less shipping has a measured record: 26 real apps built the vibe-coding way, no spec behind any of them, went through the same audit, and zero came out green, with a mean score of 52 out of 100. At least 23 of the 26 had zero working automated tests, which means the same absence twice over: nobody wrote down what the app had to keep doing, and nobody wrote a check that would have noticed when it stopped. A spec and a test are two names for the same discipline. One states the behaviour, the other proves it held.
The pattern held across a production-readiness audit of 26 real apps, none of them built from a spec, and the findings repeat the same failure a spec would have caught before the first line of code shipped: a delete that cascades into a table nobody meant to empty, a webhook signature check that fails open the moment its secret goes missing, an endpoint rate-limited in name only. Every one of those is a fragile area a spec would have had to name, and every one of them shipped anyway, because nothing forced anyone to name it first.
Even careful builders aren’t exempt
The corpus isn’t 26 strangers’ sloppy code. Five of the 26 apps are my own, built with more care than a first-time prompt, and I didn’t write a spec for any of the five either. I ran them through the same audit anyway: all five came back red, with scores from 36 to 63. Care without a spec still came out red. That’s the uncomfortable part of dogfooding your own method: the audit doesn’t soften because the person who built the app is the one holding it.
What a spec is actually made of
A spec isn’t a requirements novel. The minimal real version is three short lists: what the feature has to do, which areas break expensively if a change gets them wrong, and how you’d know the work is finished. AxonBuild’s own build rules keep exactly this shape for the areas that would cost the most if an agent got them wrong, and a spec is the same discipline pointed one step earlier, at what to build instead of what not to touch while building it.
# Spec: checkout
## Behaviours
- A logged-in user can add an item, pay, and see order confirmation.
- A second account can never see or change the first account's cart or order.
## Fragile areas
- Payments and webhooks: src/lib/payments/*
- Price calculation: the server re-derives every price from the database, never the client.
## Definition of done
- [ ] A test logs in as account B and confirms it can't read or reprice account A's order.
- [ ] A test posts a tampered price and confirms the server ignores it.
- [ ] `pnpm test` passes on both.
Compare that to the prompt most of the corpus started from: “build me a checkout page.” Nothing in that sentence names the second account, the tampered price, or the test that would catch either one. The spec’s extra length buys something specific: it’s the only version of the two a reviewer, human or automated, can actually fail.
The spec is upstream; the rules file is during-build
A spec and a rules file divide the work in time: the spec is written once, before the agent starts, and defines what to build; a rules file, the CLAUDE.md or AGENTS.md or .cursorrules kind, is read on every turn and names what not to break while the agent works: which paths are fragile, what not to touch without a passing test. That’s a real discipline and it’s the fix for why an AI-built app gets harder to change every week, but it’s a during-build guardrail, not an upstream definition of what to build in the first place. Skip the spec and the rules file still can’t tell the agent what “done” means, only what not to break.
None of this requires a rebuild to adopt. Write the three lists for the next feature before you prompt it, not after, and “ready” stops being a feeling and becomes a state the app either meets or doesn’t. The audit record says most vibe-coded apps ship without ever writing that down. That’s the gap a spec closes, and it closes it before the agent generates a single line.
Common questions about spec-driven development
Is spec-driven development just waterfall again?
No. Waterfall front-loads the entire project into one document that isn’t revisited until the end. A spec here is scoped to one feature or one change, gets rewritten as often as the feature does, and its output is a short, falsifiable list, not a project plan. The similarity is only that both put writing before building; the scope and the update cadence are what actually differ.
Do I need a spec for a weekend project?
Only for the parts that would cost you something if they’re wrong. A weekend project that nobody depends on yet can skip it entirely. The moment a client, a launch date, or another person’s data enters the picture, write the three lists for whatever touches that: the behaviour, the fragile area, and the test that proves it. Everything else can stay a prompt.
What’s the difference between a spec and a PRD?
A PRD describes what a feature should do for the user and the business: who it’s for, why it matters, what success looks like. A spec, in the spec-driven-development sense, is narrower and more mechanical: the behaviours, the areas that break expensively, and the exact test that has to pass. A PRD can exist without ever being checkable. A spec that isn’t checkable has failed at the one job it has.
Don't guess where you stand.
The free 2-minute Beyond the Demo Scorecard estimates where you stand across 12 readiness areas and shows what to check first.