The problem: code is king, and the king forgets
Part 1 · The problem
For decades, code has been king. Specifications were scaffolding — built, consulted, and discarded once the "real work" of coding began.[1][4] With an AI coding agent, that habit gets worse, not better: the spec shrinks to a prompt, the prompt vanishes with the chat, and the only surviving statement of what the software should do is the code itself.
That surviving statement is a bad one. Code says what the system does, not what it was supposed to do. When behavior and intent disagree, nobody can tell which one is the bug.
Spec-Driven Development (SDD) flips the script: the specification becomes the durable, executable center of the work, directly generating working implementations rather than merely guiding them.[1][4] The spec is written first, sharpened until it is unambiguous, and every later artifact — the technical plan, the task list, the code — is derived from it and checked against it.
Spec Kit is GitHub's open-source toolkit for working this way with any AI coding agent.[1] It ships a ready-to-use spec-driven process as a set of slash commands, works with more than 30 agents, and reached version 1.0.0 one year after its first commit — a number its maintainer calls "just a number", because as agents make change cheap, the value moves from stability to adaptability.[1][2] The process itself is a multi-step refinement, not one-shot code generation from a prompt.[1]
"Spec Kit" is the toolkit, the github/spec-kit repo.[1] "Specify" is its CLI — the specify command you install.[1] "The agent" is whichever AI coding agent you use; commands appear as /speckit.specify in most agents, $speckit-specify in skills-mode agents like Codex — the steps are identical either way.[3] This is part three of a series: part one gave the agent good habits, part two built the org around the agent, and this one makes the spec the source of truth. Each stands alone.
The project: one LinkLoft feature, twice
Part 2 · The project
We keep the running project of the series: LinkLoft, a small TypeScript URL shortener. A user shortens a URL into a slug, visitors get redirected, and the owner sees hits per link.
The feature this time is password-protected links: an owner can put a password on a link, and visitors must enter it before the redirect fires. It sounds one-prompt simple, and that is the point — it hides real questions. How many wrong attempts before lockout? Does protection interact with the expiry feature? Is the password stored hashed? What does a visitor without the password see?
"Done" for this tutorial means: the feature exists twice. Version one comes from a single prompt, and we watch what that costs. Version two travels the full Spec Kit path — constitution, spec, clarifications, plan, tasks, implementation, convergence — and we compare what survives.
As always, you do not need to build along. The project is a lens: watch what each command does to it, then apply the same moves to your own repo.
Setup: install Specify, init the project
Part 3 · Setup
Spec Kit needs Python 3.11+, git, and the uv package manager (or pipx).[1] Installation is two commands: install the CLI, then initialize the project for your agent.
uv tool install specify-cli
specify init linkloft --integration claude # or: specify init . --here
cd linkloft
init lets you pick the agent interactively, or you name it with --integration.[1][3] For CI or an agent harness with no keyboard, add --non-interactive so init never hangs on a picker.[1] The CLI manages itself too: specify self check looks for newer releases, and specify self upgrade updates in place.[1]
What init writes is a .specify/ directory of templates and scripts, plus command files for your agent — the slash commands the rest of this tutorial runs.[1][3] Adding Spec Kit to a repo that already contains code works as well; the docs carry a dedicated guide for existing projects, and the brownfield loop for evolving specs alongside a living codebase.[3][9]
Spec Kit tracks which feature you are working on through .specify/feature.json, not through the checked-out git branch — no git is required at all.[3] The opt-in git extension adds numbered feature branches like 001-password-links for organizing version control, but even then, checking out a branch alone does not switch the active feature; the state file does.[3]
Naive v1: the prompt is the spec
Part 4 · Naive v1
Before the toolkit, we build the feature the way most AI-assisted features get built. One prompt, straight to the agent.
Add password protection to LinkLoft links. Owners can set a password,
visitors have to enter it before being redirected.
The agent delivers in minutes: a password column, a form before the redirect, a check in the handler. The demo works. We ship it.
Celebrate this honestly — for a prototype, one-shot generation is a superpower. The costs are all deferred, and they arrive over the next month.
Where v1 fails
Part 5 · The failures
Five failures, each with a name, each mapped to a part of the toolkit that removes it.
Failure 1: the vanished what. The prompt was the only statement of intent, and the chat is gone. The code stores passwords in plain text — was that acceptable, or a bug? Nobody can check, because there is nothing to check against.
Failure 2: the silent gap. The prompt never said what happens after five wrong attempts, or whether a protected link can also expire. The agent guessed both, silently. One guess shipped a lockout nobody asked for.
Failure 3: the drifted plan. A teammate later "fixed" the feature from a second prompt. Now the code, the half-remembered intent, and the new behavior disagree three ways, and no artifact records which is right.
Failure 4: the unfinished finish. The agent said "done". Two acceptance-level behaviors were missing — the plain-text storage and a bypass through the API route — and nothing systematically compared the claim against the intent.
Failure 5: the one-off process. Whatever discipline we improvised here lives in one person's head. The next feature, and the next teammate, start from zero; there is no shared, customizable process to hand them.
Hold these five. The upgrades remove them in order.
Upgrade 1 — The constitution: rules every step obeys
Part 6 · Constitution
The first command runs once per project, before any feature. /speckit.constitution creates the project's governing principles — the development guidelines every subsequent step is evaluated against.[1][3]
/speckit.constitution LinkLoft principles: security first — all user
inputs validated, secrets and passwords never stored in plain text.
Prefer the standard library over new dependencies. Every feature ships
with tests for its acceptance scenarios.
The output is a constitution document the later commands actually consult: /speckit.plan checks its design against these articles, and the plan template carries explicit pre-implementation gates — a simplicity gate, an anti-abstraction gate — that force a written justification when a design wants to violate a principle.[3][4] The plain-text password of v1 dies here, one project-level sentence at a time.
This is also the first appearance of Spec Kit's quiet central mechanism: template-driven quality. Every artifact in the toolkit is generated into a structured template whose sections, checklists, and gates constrain the model — preventing premature implementation detail, forcing explicit uncertainty markers instead of confident guesses, and requiring constitutional compliance to be recorded rather than assumed.[4]
LinkLoft has a constitution. No feature exists yet under the new process, but every artifact from here on is generated against these principles, and violations must be justified in writing at a gate.
Upgrade 2 — The spec loop: specify, clarify, checklist
Part 7 · The spec loop
Now the feature enters — as a specification, not a prompt. Three commands take it from a description to a spec worth building against.
flowchart LR
S["/speckit.specify
write the spec"] --> C["/speckit.clarify
resolve ambiguity"]
C --> K["/speckit.checklist
test the requirements"]
K --> P["→ /speckit.plan"]
/speckit.specify: describe the what and the why
You describe what to build and why — deliberately not the tech stack.[1][3] The command scans existing specs to assign the next feature number, creates the specs/001-password-links/ directory, and generates spec.md from the structured template: user stories, functional requirements, acceptance scenarios.[1][4]
/speckit.specify Owners can protect a link with a password. Visitors
must enter it before the redirect. Owners can remove protection.
Protection must work together with link expiry.
The template forces the uncertainty of v1 into the open: anything the description leaves unstated is marked as needing clarification instead of being silently guessed.[4] Failure 1 dies here — the what now lives in a file, in the repo, with a number.
/speckit.clarify: resolve the marked ambiguity
/speckit.clarify reads the spec, asks you targeted questions about the underspecified areas, and folds the answers back into spec.md.[1][3] For LinkLoft it asks exactly what v1 guessed: the wrong-attempt policy, the expiry interaction, what an unauthenticated visitor sees. The docs recommend running it before any planning, so you never plan on top of ambiguity — and you can focus it, for example on one behavior area.[3] Failure 2 dies here, question by question.
/speckit.checklist: unit tests for English
/speckit.checklist generates a custom quality checklist for the spec itself — the docs call it "unit tests for your requirements": is every requirement complete, clear, consistent, unambiguous?[1][3] Checklists are reviewer-owned: you mark an item done only when you judge that requirements-quality criterion satisfied, and a checked item never means implementation work happened.[3] Later, /speckit.implement reads this checkbox state as a gate and asks before proceeding if items are unchecked.[3]
specs/001-password-links/spec.md exists: numbered, versioned, and clarified. The lockout policy and the expiry interaction are decisions in a file, not guesses in lost chat. A requirements checklist records that a reviewer actually judged the spec ready.
Upgrade 3 — The design loop: plan, tasks, analyze
Part 8 · The design loop
The spec says what; three more commands decide how, break the how into work, and check that nothing drifted on the way.
/speckit.plan: now, and only now, the tech stack
/speckit.plan is where implementation detail belongs. You state your stack and architecture, and the command generates the design artifacts from the spec: the plan itself, plus supporting documents for the data model, API contracts, and test scenarios, and a quickstart capturing the key validation paths.[1][3][4]
/speckit.plan TypeScript on the existing LinkLoft stack. Passwords
hashed with the platform's standard crypto library, no new
dependencies. Protection check lives in the redirect handler.
Two checks run inside the plan. It reads the feature's requirements and acceptance criteria from the spec, and it verifies constitutional compliance — the security-first and standard-library articles from Upgrade 1 — at the written gates.[3][4]
/speckit.tasks: a dependency-ordered breakdown
/speckit.tasks reads plan.md (and, when present, the data model, contracts, and research files) and derives an executable, dependency-ordered tasks.md: contracts and entities become concrete tasks, and independent tasks are marked [P] with safe parallel groups outlined.[1][4] Teams that track work on GitHub can push the list outward: /speckit.taskstoissues converts the generated tasks into GitHub issues.[1]
/speckit.analyze: cross-artifact consistency
Before building, /speckit.analyze reads spec.md, plan.md, and tasks.md together and reports conflicts, coverage gaps, and ambiguities across them.[1][3] It is deliberately read-only: if it flags a problem, you fix the artifact at the source and re-run.[3] Failure 3 — the three-way drift — dies here, because disagreement between artifacts is now a reported finding, not a discovery made in production.
The feature directory now holds a constitution-checked plan, contracts and a data model, and a dependency-ordered task list — and an analysis pass confirms the three layers agree before any code exists.
The full path — constitution, specify, clarify, plan, checklist, tasks, analyze, implement, converge — is the production-feature path. For smaller features the docs recommend a shorter one: specify, plan, tasks, implement, converge.[3] The optional commands are quality gates; skipping them is a scoping decision, not a shortcut around the process.
Upgrade 4 — The build loop: implement and converge
Part 9 · The build loop
Only now does code get written — and "done" stops being a claim the agent makes about itself.
/speckit.implement: execute the task list
/speckit.implement executes the tasks in tasks.md in dependency order.[1][3] Before it starts, it reads the checklist state from Upgrade 2 as a gate, asking before proceeding if items are unchecked.[3] You can run it once for the whole feature, or scope it phase by phase for large ones.[3]
/speckit.converge: check done against the spec
/speckit.converge assesses the actual codebase against the spec, the plan, and the tasks.[1] If it finds gaps — an unimplemented acceptance scenario, a bypassed route — it appends the missing work as new tasks in tasks.md; you run /speckit.implement again and converge again, repeating until it reports Converged.[1][3] For LinkLoft's protected links, the loop is what catches v1's two escapes: the API route that skipped the password check surfaces as an appended task, not a user report. Failure 4 dies in this loop.
Password-protected links exist again — built from the task list, gated by the checklist, and iterated through implement→converge until the codebase demonstrably matches the spec. The spec, plan, tasks, and code now agree, and the agreement was checked by a command.
Upgrade 5 — Beyond core: extensions, presets, bundles
Part 10 · Beyond core
Failure 5 was the one-off process. Spec Kit's answer is a customization system with a strict priority order, so the process itself becomes a shareable, versioned artifact.[1]
Extensions: add new capabilities
Extensions add commands and templates the core does not have — new workflows, external-tool integrations, whole new phases.[1] You discover and install them from the CLI: specify extension search, then specify extension add <name>.[1] Two ship with the project and are worth knowing by name:
- The bug extension gives bug fixes a repeatable assess → fix → test shape:
/speckit.bug-assessvalidates the diagnosis from the report,/speckit.bug-fixfixes the assessed cause, and/speckit.bug-testconfirms the fix resolves the original symptom — each fix scoped, evidence-based, and documented from root cause to verification.[1] - The assess extension takes a raw idea through intake → research → define → shape → decide and ends in a documented go / needs-clarification / kill decision.[1] It is standalone; an idea that gets a "go" hands off to
/speckit.specify.[1]
Presets: change how the core works
Presets override the templates and commands that core and extensions ship — changing how Spec Kit works without adding capabilities.[1] Organizations use them to enforce a compliance-oriented spec format, add mandatory security-review gates to plans, enforce test-first task ordering, adapt the flow to a methodology, or localize the whole workflow to another language; multiple presets stack with priority ordering.[1] Installation mirrors extensions: specify preset search, specify preset add <name>.[1]
Bundles: a whole role in one command
A bundle packages a curated set of extensions, presets, steps, and workflows into one versioned, role-oriented setup — a product manager, business analyst, security researcher, or developer provisioned with a single specify bundle install.[1] Bundles resolve from a priority-ordered catalog stack (project over user over built-in), specify bundle info shows exactly what install will add, installs are idempotent, removal never breaks another bundle's components, and everything works offline against pinned sources.[1]
The team's process is now an artifact: a preset encodes LinkLoft's spec format, the bug extension gives every fix the assess→fix→test shape, and a new teammate gets the whole setup from one bundle install. Failure 5 is gone — the process ships with the repo.
How it holds together underneath
Part 11 · Underneath
Four mechanics explain most of what you will observe day to day.
flowchart TD
O["1 · Project-local overrides
.specify/templates/overrides/"] --> PR["2 · Presets
.specify/presets/templates/"]
PR --> EX["3 · Extensions
.specify/extensions/templates/"]
EX --> CO["4 · Spec Kit core
.specify/templates/"]
Resolution order. Templates resolve at runtime, top-down: project-local overrides beat presets, presets beat extensions, extensions beat core.[1] Command files, by contrast, are written into your agent's directory at install time; when two components provide the same command, the highest-priority version wins, and removing it restores the next one automatically.[1]
Feature state. The active feature is the directory recorded in .specify/feature.json (or the SPECIFY_FEATURE_DIRECTORY variable), which is why the toolkit works without git and why switching branches alone never switches features.[3]
Agent independence. The same process runs across 30+ agents because the commands are plain prompt files or skills, generated per integration by specify init; specify integration list shows what your version supports.[1][3] Automation scripts ship in Bash, PowerShell, and Python variants, chosen at init.[3]
Dogfooding. Spec Kit is developed with Spec Kit for substantial changes — the automated feature-assessment workflow initializes the CLI from the current checkout and runs the assess extension against incoming feature requests — while small fixes use the normal PR process.[1] The project is honest about the boundary, which is itself a useful lesson in adopting SDD: not every change needs the full path.
The toolkit also names its three intended arenas: greenfield 0-to-1 generation, creative exploration with parallel implementations, and brownfield iterative enhancement — with a dedicated guide for evolving specs in existing codebases.[1][9]
The philosophy is explicit: intent-driven development where the what precedes the how, rich specs built with guardrails, multi-step refinement over one-shot generation, and heavy reliance on the model's ability to interpret a good spec.[1] The commands automate the mechanics; writing an honest spec is still your job.
Situation → command: the quick map
Part 12 · The map
All ten core-and-optional commands, the two bundled extensions, and the CLI verbs this tutorial touched.[1][3]
| Situation | Command |
|---|---|
| New machine | uv tool install specify-cli |
| New or existing project | specify init <name> --integration <agent> |
| Once per project: set the ground rules | /speckit.constitution |
| Describe what to build and why | /speckit.specify |
| Resolve marked ambiguities before planning | /speckit.clarify |
| Choose the tech stack and design | /speckit.plan |
| Quality-test the requirements themselves | /speckit.checklist |
| Break the plan into ordered tasks | /speckit.tasks |
| Track tasks as GitHub issues | /speckit.taskstoissues |
| Check spec, plan, and tasks agree | /speckit.analyze |
| Build the tasks in dependency order | /speckit.implement |
| Verify the code matches the spec | /speckit.converge (repeat with implement until Converged) |
| Fix a bug with evidence | /speckit.bug-assess → /speckit.bug-fix → /speckit.bug-test |
| Assess an idea before committing | /speckit.assess-intake → …-research → …-define → …-shape → …-decide |
| Add a capability / change the format | specify extension add · specify preset add |
| Provision a whole role at once | specify bundle install <bundle-id> |
| Update the CLI itself | specify self check · specify self upgrade |
Checklist and where to go next
Part 13 · Conclusion
Your features are spec-driven when all of this is true:
- Specify is installed, and each project ran
specify initfor its agent.[1] - The project has a constitution, and plans justify any deviation at a written gate.[3][4]
- Every feature starts as a numbered spec in
specs/, stating what and why — never the stack.[1][3] - Ambiguities are resolved by
/speckit.clarifybefore planning, not guessed during coding.[3] - The stack enters at
/speckit.plan, and/speckit.analyzeconfirms spec, plan, and tasks agree.[1][3] - "Done" means
/speckit.convergereports Converged, not that the agent said so.[1] - Bug fixes follow assess → fix → test; big ideas get a go/kill decision before a spec.[1]
- Team customizations live in presets, extensions, and bundles — shipped with the repo, not in someone's head.[1]
Read next, in this order:
References
- github/spec-kit — repository README (MIT, v1.0.0).
- Spec Kit Turns One — and Ships 1.0.0 — maintainer's anniversary post.
- Quick Start Guide — Spec Kit docs.
- Complete Spec-Driven Development Methodology — spec-driven.md.
- Spec Kit community — extensions, presets, bundles, walkthroughs.
- Supported AI Coding Agent Integrations.
- Extensions reference.
- Presets reference.
- Evolving Specs — the brownfield loop.
- Agentic SDD — full command reference.