AI Coding Tools

Spec-Driven Development with AI: Write the Plan Before the Code (2026)

Aug 14, 202612 min read

Spec-driven development (SDD) treats the spec as the single source of truth: you write a spec and a plan with acceptance criteria first, then let an AI agent generate code and tests against them. Compared with "vibe-only" (firing off one thin prompt and hoping), SDD sharply cuts the cases where AI drifts from your requirements, wanders off-architecture, and burns tokens on endless rework loops. This post hands you a real, copy-and-use spec.md + plan.md, and shows how to run the loop right inside Claude Code.

What is spec-driven development?

Spec-driven development is a method that treats the specification (spec) as the single source of truth: you write down "what needs to be built, why, and what done looks like" before the first line of code, then let an AI agent generate code, tests, and docs that follow that spec. In short: the spec drives the AI, instead of the AI guessing what you meant.

The heart of it is that phrase, "single source of truth." In the old way of working, requirements live scattered across your head, a few chat messages, and a thin ticket. The AI can read very little of that, so it has to infer the rest - and inference is where bugs are born. SDD forces you to gather every important constraint into one document that both humans and agents can read: the goal, the scope, the acceptance criteria, and even the things you deliberately do not want done (non-goals).

This is not a return to waterfall's "write a giant document before you code." A spec in SDD is short, living, and usually only one or two screens long. It is context before code - just enough context for a smart agent to get it right on the first pass, instead of you patching it by hand three or four times over. Thoughtworks calls this a pattern that is reshaping how software gets written with AI (Thoughtworks, 2025).

Why does writing a plan first beat "vibe-only"?

Let us name the core problem with vibe-only using a term that sticks: the "ambiguity tax." Every spot where your requirement is still fuzzy, the AI is forced to fill in the blank. It fills it with an average guess drawn from its training data, not with your actual intent. You pay that tax back in the form of rework loops: "no, that is not what I meant," "you missed this case," "why did you change that whole other file?"

If you are new to the hands-off, let-the-AI-lead style, read what vibe coding is first for context - SDD is the step that puts discipline on top of vibe coding, not a rejection of it. Vibe-only is great for fast exploration; but the moment a task has clear requirements, it exposes three risks:

  • Requirement drift: the AI ships something that runs but is not what you needed - missing edge cases, misread business logic, naming and interfaces that break your conventions.
  • Architecture drift: every prompt becomes an ad-hoc design decision. After ten prompts, the codebase is a patchwork nobody intentionally designed.
  • Ballooning token cost: every "please fix this again" loop makes the agent re-read the context and regenerate code. Three or four rounds of rework cost many times more tokens than one good spec up front.

Spec-driven flips the order: you pay the "thinking cost" once, at the front, while it is still cheap. Writing acceptance criteria forces you to answer the very questions the AI would otherwise have to guess at. Once the context is clear, the agent has almost no gap left to guess wrong in. This is also why a mature vibe coding workflow always has a plan-writing step woven into the middle, instead of prompting nonstop.

Spec vs plan vs task - what is the difference?

These three words often get blurred together, but drawing a clean line between them is the key to SDD. In short: a spec answers "what and why," a plan answers "how, and in what order," and a task is the smallest unit of execution.

ElementAnswersContainsPrimary reader
SpecWhat & whyGoal, scope, acceptance criteria, non-goals, edge casesHuman + AI review together
PlanHow, and in what orderOrdered steps, files to touch, how to test, risk/rollbackAI agent executes
TaskThe specific next thingOne small unit, finished & verifiable in a single passAgent (or you) does one at a time

Common mix-ups: stuffing the how into the spec (the spec gets micromanaged too early and loses flexibility), or writing a plan that skips acceptance criteria (the agent never knows when it is allowed to call it done). A trick for holding the line: if an answer is about "what the user or system needs," it belongs in the spec; if it is about "what we type, which file to edit first," it belongs in the plan.

A REAL example: a spec + plan before any code

Enough theory. Here is a real artifact for a small feature I often use to illustrate this: adding a rate limit to the login endpoint. Copy these two files, tweak a few lines for your project, and you are good to go. First, the spec.md - it only says "what and why," never how:

# spec.md - Rate limit for the login API

## Goal
Block brute-force against POST /api/login by limiting the number of
attempts per IP + email, returning a clear error when the limit is passed.

## Why
Login currently has no limit -> passwords are easy to guess and the DB
can be overloaded.

## Acceptance criteria
- Max 5 failed attempts / 15 minutes per (IP, email) pair.
- Over the limit -> HTTP 429 + body { error: "too_many_attempts", retry_after }.
- A SUCCESSFUL login resets the counter for that (IP, email) pair.
- Automated tests for: under the limit, at the limit, over the limit, and reset.

## Non-goals
- NO CAPTCHA (deferred to a later phase).
- NO rate-limiting other endpoints this time.

## Edge cases
- Many users behind the same NAT/IP -> key on (IP, email), not IP alone.
- Clock/timezone: use UTC for the time window.

Next is the plan.md - now, and only now, it says "how, and in what order." Note the files-to-touch column and the rollback section:

# plan.md - Implementing login rate limit

## Steps (in order)
1. Add an attempt-counter store (Redis, key = login:{ip}:{email}, TTL 15m).
 -> File: src/lib/rate-limit.ts (new)
2. Write a checkLoginRateLimit middleware that reads/increments the counter.
 -> File: src/middleware/login-rate-limit.ts (new)
3. Attach the middleware to POST /api/login BEFORE the auth handler.
 -> File: src/routes/auth.ts (edit)
4. On successful login -> delete the counter key for that (IP, email).
 -> File: src/routes/auth.ts (edit)
5. Write tests for the 4 cases in the acceptance criteria.
 -> File: tests/login-rate-limit.test.ts (new)

## How to test
- npm test tests/login-rate-limit.test.ts
- Manual: send 6 wrong requests in a row -> the 6th must return 429.

## Risk & rollback
- Redis down -> fail-open (let it through) or fail-closed? Choose fail-open +
 log a warning, so infra failures do not lock out every user.
- Rollback: removing the middleware in step 3 returns the system to its
 original state.

What happens when you let the AI run against this plan: the agent works in the right order, creates all the files, and stops at the right point because the acceptance criteria spell out what "done" means. No more casually refactoring the whole auth module or forgetting the counter-reset case. Same agent, same task - the difference is whether it has a map.

The spec-driven workflow with AI (6 steps)

This is the loop I use for almost every mid-to-large feature. It maps almost one-to-one onto the brainstorm -> plan -> cook -> ship workflow:

  1. Idea & context: state the problem to solve and the real constraints (stack, conventions, things that must not be touched). This is where you gather the project's "truth."
  2. Write the spec: fill in Goal / Non-goals / Acceptance criteria / Edge cases. Force yourself to be concrete on the acceptance criteria - wherever you are vague, the AI will guess.
  3. Review the spec (human + AI): ask the agent to read the spec and flag contradictions, missing cases, or impossible requirements - before a single line of code exists.
  4. Write the plan & split into tasks: turn the spec into ordered steps that name the files to touch, how to test, and rollback. Slice it until each task is verifiable in a single pass.
  5. Let the agent code task by task: run one task at a time, no jumping ahead. After each task, have the agent check its work against the plan.
  6. Verify against the acceptance criteria: run the tests and go line by line through the criteria. Only when every criterion is green is the feature done - not when it "looks like it runs."

The crux: steps 3 and 6 are where SDD saves you the most. Catching a bug at the spec stage is dozens of times cheaper than catching it in code.

Doing spec-driven right inside Claude Code

You do not need any special tooling to start - Claude Code already ships with three things that are enough to stand up a lean SDD loop:

  • Plan Mode: Claude Code drafts a plan and lets you approve it before it touches any files - exactly the "plan first, code later" spirit (Anthropic docs, 2026). See how to get the most out of it in planning with Claude Code (Plan Mode).
  • CLAUDE.md as a standing guardrail: put long-lived conventions, boundaries, and non-goals into this file so the agent always reads them - it turns repeated constraints into fixed "truth" for the repo. This is context engineering in its simplest form.
  • GitHub Spec Kit: an open-source command set that turns SDD into an explicit workflow, /specify -> /plan -> /tasks, usable with Claude Code and many other agents (GitHub Blog, 2025).

Want a spec-driven workflow that is prebuilt? If you would rather not hand-wire CLAUDE.md + Plan Mode + Spec Kit yourself, the AgentKit bundle — now $149 (from $198) for Claude Code packages brainstorm/plan/cook/ship skills and review subagents that follow the same spec -> plan -> code -> verify flow. I have a full write-up in what AgentKit is - read it to decide for yourself, no need to rush a purchase.

Spec-driven tools in 2026

A few popular options, from lightweight to fully packaged:

ToolStrengthBest for
GitHub Spec Kit (OSS)Clear workflow /specify /plan /tasks; free, works with many agentsAnyone who wants a standard SDD convention, not tied to one IDE
Kiro IDE (AWS)Spec-first IDE that generates spec/design/task right in the editorAnyone who prefers one fully integrated environment
Claude Code + Plan Mode/CLAUDE.mdNothing extra to install; standing guardrail; approve the plan before codePeople already on Claude Code who want to start now
AgentKit workflowPackages the brainstorm->plan->cook->ship flow + review subagentsAnyone who wants a prebuilt process instead of wiring it up

There is no single "correct" tool. Plain Markdown + Plan Mode is enough for most features; the heavier kits only pay off when you do SDD often and want to standardize it across a team.

When do you NOT need spec-driven?

SDD is a tool, not a religion. Forcing a spec onto everything backfires. Skip SDD when:

  • One-off scripts or throwaway tasks - writing the spec takes longer than just doing it.
  • Exploratory prototypes/spikes: the goal is to learn fast, not to get it right yet. Vibe-only fits better at this stage.
  • A one-line bug fix whose cause you already understand - you do not need acceptance criteria to change one character.
  • Requirements that shift by the hour: the spec will go stale faster than you can write it.

Two traps to watch for even when SDD does fit: over-spec (writing a spec so detailed it turns rigid and kills flexibility) and spec rot (the spec is never updated when the code changes, becoming a document that lies). A good spec is one that is just enough for the agent to get it right and still easy to change - not the longest one.

Frequently asked questions (FAQ)

How is spec-driven development different from vibe coding?

Vibe coding is firing off prompts and letting the AI lead, which suits fast exploration. Spec-driven puts a spec with acceptance criteria in place as the source of truth before any code, which suits features with clear requirements. SDD is the step that adds discipline to vibe coding, not a rejection of it.

Is a spec different from a plan?

Yes. A spec answers "what and why" (goal, scope, acceptance criteria, non-goals). A plan answers "how, and in what order" (steps, files to touch, how to test, rollback). The spec is more stable; the plan can change when the approach changes.

Do I need dedicated tooling, or is Markdown enough?

Plain Markdown is enough to start - just a spec.md and a plan.md. Tools like GitHub Spec Kit or Kiro only help standardize the process once you do SDD regularly or across a team.

Does spec-driven slow you down?

Slower at the start, faster overall. You spend a few extra minutes writing the spec but cut many rework loops when the AI would have drifted. For small/throwaway tasks it really is not worth it - just vibe then.

Can I use spec-driven with Cursor or Copilot?

Yes. SDD is a method, not tied to one tool. You can keep spec.md/plan.md in the repo and have any agent (Claude Code, Cursor, Copilot) follow them. GitHub Spec Kit was designed to be multi-agent in the first place.

How long should a spec be?

Long enough that the agent does not have to guess anything important, usually one to two screens. If the spec is longer than the code it produces, you are over-speccing. The real test is: clear acceptance criteria and clear non-goals.

Conclusion + next steps

The principle fits in four words: spec first, code later. You pay the thinking cost once at the front - where it is cheapest - so the AI does not repay the ambiguity tax with expensive rework loops. Next up: read the brainstorm -> plan -> cook -> ship workflow to see where SDD sits in a full working loop, and planning with Claude Code (Plan Mode) to get hands-on right away.

Want Claude Code to be stronger right away? If you would rather have the spec -> plan -> code -> verify flow prebuilt into skills and subagents instead of wiring each piece yourself, AgentKit for Claude Code (agentkit.best, the ak CLI) packages exactly that flow - with a money-back guarantee and lifetime updates for the kits.

Try AgentKit (20% off via link) ->

J

Jasmine

Author · Jasmine Daily

The writer behind Jasmine Daily - jotting down thoughts, experiences, and everyday moments. Honest, unhurried, imperfect.

Jasmine Daily

There's more waiting to be read.

If this piece spoke to you, browse a few more pages from the journal.

Read next

Related posts