Spec-driven development (SDD) makes the specification the source for planning, tasks, implementation, and acceptance. Its value comes from turning a vague request into behaviours that a reviewer or test can check, regardless of the workflow’s name or the document’s size.

What is spec-driven development?

Spec-driven development is a workflow in which a specification defines what to build before implementation begins, then stays connected to the plan, tasks, and acceptance checks. GitHub’s current open-source Spec Kit exposes those steps as commands you run inside your agent. In Martin Fowler’s comparison of Spec Kit, Kiro, and Tessl, the tools use different artifacts while keeping the specification upstream of generated code. The current Kiro IDE review examines that tool’s spec workflow, agent controls, and production readiness separately.

Spec Kit’s current full path has nine commands in this order:

  1. Constitution. The rules that hold for every feature in this repo: language, test command, what never gets touched.
  2. Specify. The behaviour this one feature must have, in plain English, with no implementation detail.
  3. Clarify. The agent asks about the parts you left ambiguous, and you answer before anything is planned.
  4. Plan. The technical approach: which files, which libraries, which data changes.
  5. Checklist. A reviewer checks the requirements for completeness and clarity before implementation begins.
  6. Tasks. The plan is broken into steps small enough to review one at a time.
  7. Analyze. The spec, plan, and tasks are checked for conflicts and omissions.
  8. Implement. The agent works the task list.
  9. Converge. The implementation is checked and refined until the required checks pass.

Three modes sit under the same label, and picking the wrong one is the most common mistake. Spec-first means you write the spec, build from it, and let it go stale on purpose: the code is the truth afterwards. Spec-anchored means the spec lives beside the code and you update both when behaviour changes. Spec-as-source means you only ever edit the spec and the agent regenerates the code from it.

For an app that already has customers, use spec-anchored. Spec-as-source is a trap for a non-technical founder: it sounds like the dream (never edit generated code again) but it leaves the generator in charge of implementation choices, including authorization boundaries. You can still inspect the generated code, and you should. Spec-first is fine for a throwaway prototype and misleading anywhere else, because the stale document gets quoted back at you as if it were still true.

Outside that taxonomy, “spec-first” also gets used loosely for the whole order of operations, so check which meaning someone intends. Either way, toolkit or plain markdown file, the agent needs the spec in its working context and the definition of done must include checks that can fail. Merely creating spec.md does not prove the implementation follows it.

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 the server checks on every protected route, proven by an API test that gets 401 with no session and a page test that redirects without returning private data.” Both can produce code that runs on the first try. The spec gives you conditions that can fail under a test; the prompt leaves correctness implicit.

A vibe prompt A spec line
Build me a checkout pageCheckout: the server re-derives every price from the database; a test logs in as a second account and confirms it can’t set its own price.
Add loginAuth: a protected API returns 401 without a session; a protected page may redirect to login but returns no account data.
Let people upload filesUploads: a signed URL scoped to the owner’s row; a test requests another user’s file ID and is denied.
A vibe prompt
Build me a checkout page
Add login
Let people upload files
A spec line
Build me a checkout page
Checkout: the server re-derives every price from the database; a test logs in as a second account and confirms it can’t set its own price.
Add login
Auth: a protected API returns 401 without a session; a protected page may redirect to login but returns no account data.
Let people upload files
Uploads: a signed URL scoped to the owner’s row; a test requests another user’s file ID and is denied.

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 a spec is actually made of

A spec does not need to be a requirements novel. A useful small version has three short lists: what the feature must do, which boundaries need special care, and how to verify the work. Add assumptions and exclusions when they would change the implementation, which is most of the time.

# 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.

## Out of scope
- Refunds, saved cards, guest checkout. Do not build them; do not stub them.

## Assumptions
- Prices are stored in cents in the products table and are never sent by the client.

## 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 with “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 longer version gives a reviewer specific conditions to accept or reject.

The two short sections people skip are the ones that save the most time. “Out of scope” stops the agent from inventing a refunds flow you then have to review. “Assumptions” is where a wrong belief becomes visible before it becomes code: if prices are actually stored in dollars as floats, that line is wrong and you find out while reading, not during a chargeback.

Spec-driven development tools: Spec Kit, OpenSpec, Kiro, Tessl, or plain markdown

Start with plain markdown. Each SDD toolkit below creates its own artifacts and lifecycle, so the tool is worth adopting only once those artifacts are earning their keep.

ToolWhat it createsHow you drive itWhen it is overkill
Spec Kit (GitHub)A .specify/ folder in the repo, then a constitution, spec, plan, checklists, and task list per featureIts full path runs constitution, specify, clarify, plan, checklist, tasks, analyze, implement, and convergeA one-file change, or any repo where nobody will actually read the generated plan
OpenSpecopenspec/specs/ for current behaviour and openspec/changes/ for each change, with artifacts such as a brief, specs, design, and tasksIts default path runs explore when needed, propose, apply, then archive, with sync available when current specs need updatingYou have one feature and no change history to keep straight
Kirorequirements.md, design.md and tasks.md per feature, plus steering files product.md, structure.md and tech.mdKiro’s built-in spec workflow, inside the Kiro IDEYou do not want to move your work into another editor
TesslMarkdown specs in a specs/ folder that you approve before the agent builds against themtessl install tessl-labs/spec-driven-developmentYou want the spec to stay a document you own rather than part of a pipeline
Plain markdownOne spec.md next to the feature, in the repoYou paste it into the agent and point back at the path every sessionNever. It is the floor

Checked August 2026: Spec Kit installs with uv tool install specify-cli and namespaces its commands (/speckit.specify, not /specify), and GitHub says it works with 30+ coding agents including Claude Code. OpenSpec installs from npm and also lists 30+ supported tools. Kiro’s steering files (product.md, structure.md, tech.md) are loaded into every interaction by default, which makes them a rules file, not a spec.

The honest summary of “Spec Kit vs OpenSpec”: Spec Kit gives you one lifecycle per feature and a constitution for the repo. OpenSpec keeps a standing record of what the system does now, separate from a folder of proposed changes you archive once they ship. If you keep losing track of what was decided and why, OpenSpec’s shape helps. If you keep shipping features nobody can accept or reject, Spec Kit’s shape helps. Neither writes your acceptance criteria for you.

Spec-driven development in Cursor

Cursor ships no spec feature. The closest native piece is plan mode, which does a different job: press Shift+Tab from the chat input to rotate into it, and the agent reads the codebase, asks clarifying questions, and writes an implementation plan you can edit as markdown. Checked August 2026, Cursor’s planning documentation says plans are saved in your home directory by default, with a “Save to workspace” button that moves one into the repo. A plan is how the work will be done. A spec is what must be true when it is finished, and plan mode never asks you for that half.

So keep them as two files. Write the behaviours, fragile areas and definition of done at a fixed path in the repo, point plan mode at it, and let the plan stay a plan. Standing rules are a third thing again: Cursor’s rules documentation puts project rules in .cursor/rules as .mdc files, version-controlled, applied always or on a glob match or when the agent judges them relevant or by @-mention, and names AGENTS.md as a simple alternative. If you want the whole lifecycle rather than three files you maintain by hand, Spec Kit lists Cursor among its supported integrations, under the key cursor-agent.

Spec-driven development with GitHub Copilot

Copilot’s spec workflow is Spec Kit, which GitHub builds and Copilot is a first-class target for. Running specify init with the copilot integration installs the /speckit.* commands into the repository. Checked August 2026, Spec Kit’s integrations reference gives the default Copilot layout as .github/skills/, holding one speckit-<command>/SKILL.md per command, plus an alternative commands layout that writes .agent.md files into .github/agents/ with .prompt.md companions in .github/prompts/.

Repository instructions are a separate layer, and Copilot reads several kinds of them. GitHub’s response-customization documentation names .github/copilot-instructions.md for the whole repository, NAME.instructions.md files under .github/instructions for path-specific rules, and AGENTS.md, CLAUDE.md or GEMINI.md as agent instruction files, with the caveat that those are “currently not supported by all Copilot features”. Prompt files (*.prompt.md) are reusable prompts you invoke by hand in VS Code, Visual Studio and JetBrains, not standing context. None of these is a specification. They are what Copilot should always know, not what this one feature has to do.

Spec-driven development with Claude Code

The spec only works if Claude Code can see it at the moment it writes the code. Everything else in this section follows from that.

Put the spec at a stable path in the repo, for example docs/specs/checkout.md, and name that path in your CLAUDE.md so the agent knows where to look. Do not paste the spec into chat and assume it stays. A long session gets compacted, and compacted context is a summary: the exact wording of your acceptance criteria is exactly the kind of detail that gets summarized away. Re-read the file by path at the start of each work block, and again before the agent starts implementing.

If you want the full lifecycle as commands rather than as a file you maintain by hand, Spec Kit installs alongside Claude Code:

uv tool install specify-cli
specify init my-project --integration claude

That gives you /speckit.specify, /speckit.plan, /speckit.tasks and the rest inside the Claude Code session. The plain-markdown version of the same workflow is: write the three lists yourself, ask Claude Code to read the file and produce a task list before touching any code, approve the task list, then let it work. Use plan mode for the read-and-plan half so nothing gets edited while you are still deciding.

The division of labour between the two files is worth getting right. CLAUDE.md is repository-wide and always on: the test command, the fragile paths, the things that must never happen in this codebase. The spec is per feature and temporary in scope: what this one change must do and how you will know it did. If you find yourself copying spec lines into CLAUDE.md, that behaviour was probably a repo-wide rule all along. If you find yourself copying CLAUDE.md rules into every spec, delete them from the specs.

Adding a spec to an app that already exists

Do not write a spec for the whole app. You will spend a week documenting behaviour you are not about to change, and the document will be wrong in places you never notice.

Pick the one feature you are about to touch. Write the three lists for that feature only: what it must do, which boundaries are fragile, how you will verify it. Then, before adding anything, have the agent read the current code for that feature and list every place where the real behaviour contradicts what you just wrote. That list is the interesting output. It is usually short, and it usually contains at least one thing you believed was true and is not.

Fix the contradictions first, then build the new work against the spec. Repeat per feature. After five or six features you have specs covering the parts of the app that actually change, which is the only part that needed them.

Where spec-driven development goes wrong

You now review markdown instead of code, and markdown hides bugs better. A spec that reads beautifully can describe a system with a hole in it, and nothing about the prose will tell you. Reviewing “the server re-derives every price” feels like verification, but only the test verifies it.

The full workflow costs more than it saves on small changes. Running a production-feature workflow for a copy fix is theatre. The cost is real (your reading time, the agent’s tokens, the round trips) and on a one-line change the benefit is zero. Use the workflow where a mistake would cost you something.

The spec drifts the moment someone edits code directly. Someone changes behaviour in the editor without touching the document, and the spec quietly becomes a lie that still looks authoritative. Spec-anchored only works if updating both is part of the change, not a chore for later.

A detailed spec creates a false sense of control. The agent can satisfy every line you wrote and still ship an unchecked authorization boundary, because you did not write a line about it. The spec constrains what you thought of. It says nothing about what you did not.

What 26 audits show about missing acceptance criteria

Across 26 production-readiness audits, no app reached the corpus’s green band and at least 23 had no working automated tests. Those figures describe a dated June-July 2026 sample, not all AI-built software. The audits also did not collect reliable evidence about whether every team had written a specification, so they cannot establish that missing specs caused the findings.

The corpus is still useful here because it shows the kinds of acceptance criteria that were absent from the executable evidence. A delete crossed an unintended data boundary, a webhook verification path failed open when its secret was missing, and a rate limiter existed without protecting the expensive endpoint. A spec could have required tests for each behaviour. The audit evidence shows the missing checks; it does not reconstruct the development process that produced them. The data-loss example has its own analysis in data-loss bugs in AI-built apps.

A spec still needs executable acceptance checks

Five apps in the same corpus were my own projects. All five landed in the red band, with scores from 36 to 63, after going through the same automated audit and human verification process. That result is a useful warning against trusting familiarity with the code. It is not a controlled comparison of spec-driven and prompt-driven development.

A specification closes one gap only when its acceptance criteria become real checks. “Users cannot read another account’s order” is a requirement. A two-account authorization test is the evidence. Keeping both in the same workflow makes drift visible when the implementation changes.

Spec vs CLAUDE.md, AGENTS.md and steering files

A spec and a rules file operate at different layers. The spec defines the feature’s required behaviour and acceptance conditions. A rules file, such as CLAUDE.md, AGENTS.md, or .cursorrules, gives the agent repository-wide constraints while it works: which commands to run, which paths are fragile, and which changes require extra care. Kiro calls its version steering files and other tools call it a memory bank, but the job is the same: standing instructions not tied to any one feature. How much of them loads varies by tool: CLAUDE.md, AGENTS.md and Kiro’s steering files load on every session, while Cursor loads a rule always, by glob, by relevance or only when mentioned, as the integration section above describes. Why AI-built apps get harder to change covers that during-build discipline, and the Kiro review covers what its spec workflow feels like in practice. A rules file cannot supply a missing feature definition, and a spec cannot supply missing repository instructions.

You can adopt the workflow on the next feature without rebuilding the app. Write the required behaviours, fragile boundaries, and acceptance checks before implementation. Then keep the spec beside the code and update both when the feature changes. Readiness becomes a set of conditions the app can meet or fail, rather than a judgment based on the demo.

Common questions about spec-driven development

Is spec-driven development just waterfall again?

No on both counts. Both waterfall and spec-driven development put explicit requirements before implementation, but that ordering does not require a frozen, project-wide document. A feature spec can be small, versioned beside the code, and revised when requirements or observed behaviour change. The important distinction is whether the team treats the specification as a maintained source of acceptance conditions.

Nor does it run against agile. A one-feature spec that gets revised when the behaviour changes fits inside a short iteration without any argument; agile objected to the frozen document rather than to writing requirements down. Calling the workflow the future oversells it and calling it dead undersells it, and both readings miss the part that decides whether it is any good on your project: it earns its keep where a wrong result costs you money, data or a customer, and it is theatre on a change nobody would notice being wrong. Judge any version of it, under any label, by whether its definition of done contains checks that can fail.

Is this model-driven development again?

The objection is fair, and the answer depends on which mode you pick. Model-driven development tried to generate code from formal models, and in most teams that tried it the formal models turned out to be harder to write and keep current than the code they replaced, which is the usual account of why it stayed a niche practice. Spec-driven development uses plain English and leaves the generated code in the repo where you can still read it, which is the difference that matters. Spec-as-source, where you edit the spec instead of manually editing generated code, is the mode that walks straight back into the old problem.

Is spec-driven development the same as TDD or BDD?

No, they sit at different levels. TDD writes a failing test before the code, and BDD writes behaviour as Given/When/Then scenarios; both start at the test. Spec-driven development starts one step earlier, with the feature’s required behaviour and acceptance conditions, then feeds the plan, the tasks, and the code. They fit together: the spec’s definition of done is where the TDD or BDD tests come from.

What’s the difference between a spec and a PRD?

A PRD usually frames the user and business problem: who the feature serves, why it matters, and how success will be judged. A feature specification defines the behavioural contract and acceptance conditions used for implementation. Teams use these names differently, and one document can serve both jobs. For spec-driven development, the requirement is traceability from stated behaviour to plan, code, and verification.

What’s the difference between a spec and a design doc?

A design doc explains how you intend to build something and why: architecture, trade-offs, alternatives you rejected. A spec states what must be true when the work is done, in conditions something can check. A design doc can be completely right and still leave you with no way to accept or reject the result, which is why most small features need the spec and can skip the design doc.

Which spec-driven development tool should I start with?

Plain markdown. One spec.md beside the feature, holding behaviours, fragile areas and a definition of done, gets you most of the benefit on day one with nothing to install. Reach for Spec Kit when you want the constitution-to-validate sequence as commands, or OpenSpec when you need a standing record of current behaviour separate from proposed changes. Kiro and Tessl ask you to adopt their environment, which is a bigger commitment than a first feature deserves.

Does spec-driven development work with Lovable, Base44 or Cursor?

Yes for Cursor and Claude Code, partly for the browser builders. Cursor and Claude Code read files out of the repo, so the spec can live at a fixed path and be re-read on every task. Lovable and Base44 do not give you the same guarantee that a specific file is read before each change, so paste the behaviours and the definition of done into the prompt for the feature you are building and keep the spec in a document you own. The acceptance checks are what matter; where the file lives is a detail.

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.