GitHub's spec-kit Turns AI Coding from a Guessing Game into a Contract
spec-kit in Practice: How I Use the SDD Methodology to Solve AI Coding Hallucination Problems
Have you ever encountered this scenario: using Cursor to write a user permissions module, vibe coding for 3 hours, only to find when the code runs that the AI reversed the role inheritance logic — I clearly said I wanted RBAC0, but it wrote the inheritance direction for RBAC1. By the 5th revision, the AI had already forgotten the "no dynamic roles" constraint I mentioned at the very beginning.
I've run into this kind of mess at least ten times. It wasn't until last month, when I tried GitHub's official spec-kit, that I finally stopped oscillating between the AI's "freewheeling" and my "repeated rework."
Why Figure This Out?
Many people think SDD is just the old-fashioned "write docs first, then code" approach. That's a complete misunderstanding.
The core of SDD is turning the spec from a static document into an executable contract. Code is a derivative of the spec, not the other way around where documentation serves the code. This is fundamentally different from traditional "requirements documents" — requirements docs are thrown away after writing, but a spec, once written, continuously drives development: every time requirements change, you first change the spec, then have the AI regenerate the code based on the spec.
When I was vibe coding, I expressed requirements purely verbally. If the AI understood correctly, it benefited me; if it misunderstood, I took the blame. The logic of SDD is reversed: I spend 20 minutes first clearly writing out the requirements, constraints, and acceptance criteria. The AI must generate code according to this. If it doesn't run, it's the AI's problem, not my unclear requirements.
| Dimension | Vibe Coding | SDD (spec-kit) |
|---|---|---|
| Requirement Expression | Verbal description, potentially inconsistent each time | Spec file, requirements written once and read by AI every time |
| AI Understanding Deviation | You're unclear, AI guesses, high failure rate | Precise spec + acceptance criteria, low failure rate |
| Requirement Changes | After changes, AI might forget previous constraints | Change spec, regenerate, AI automatically tracks |
| Rework Cost | High, often still revising by the 5th version | Low, change spec, rerun implement once |
| Code Consistency | Becomes increasingly scattered with iterations | Code always stays consistent with the spec |
spec-kit is a product that turns this logic into a universal toolchain, not an accessory to any single AI coding tool — it currently supports 30+ coding agents including Claude Code, Cursor, Copilot, Gemini CLI, etc. It's officially maintained by GitHub. As of 2026-06-25, it has 115,317 stars, and the latest version is v0.11.8 (updated 2026-06-24). Activity is absolutely not a concern.
How Does It Work?
The core workflow of spec-kit consists of 5 steps, each with clear inputs, outputs, and acceptance criteria. You can skip some steps, but the cost is a higher chance of failure later.
Step 1: Write the Project Constitution (/speckit.constitution)
This step establishes the project's "fundamental law." All subsequent specs, plans, and code must comply with the rules in this file. Just like a national constitution is above all laws, the constitution is above all specs.
I'll use a to-do list REST API as an example. Execute the command:
/speckit.constitution
The AI will ask you a few questions, such as what language, what framework, what coding standards. My answers were: Go 1.22 + Gin + GORM + MySQL 8.0, error handling must return custom error codes, no panics allowed, no global variables allowed, no writing SQL directly in the handler layer.
The generated constitution.md will record all these rules in a structured way. Every subsequent specify, plan, and implement step will automatically adhere to these constraints.
Do not skimp on this step. The more detailed the constitution, the less room the AI has to guess later. The first time I used it, I only wrote "use Go," and the AI chose the standard library net/http instead of Gin. I had to redo the entire plan from scratch.
Step 2: Write the Requirements Specification (/speckit.specify)
This step only writes "what to do," completely avoiding technical implementation details. You need to describe user stories and acceptance criteria, not the tech stack.
/speckit.specify
My requirement was: "Create a to-do API that supports creating, querying, updating, and deleting to-dos. Each to-do includes a title, content, deadline, and status (incomplete/complete). Support filtering by status."
The generated spec.md automatically breaks down into user stories and acceptance criteria:
## User Stories
1. As a user, I can create a to-do so I don't forget things to do
2. As a user, I can filter to-dos by status to easily distinguish completed from incomplete
## Acceptance Criteria
- Creating a to-do must include a title; missing title returns a 400 error
- Deadline format must be RFC3339; incorrect format returns a 400 error
- Filtering by status returns only to-dos with the corresponding status
Step 3: Clarify Ambiguities (/speckit.clarify, optional but highly recommended)
I skipped this step the first time and later regretted it when changing requirements became a nightmare.
This step has the AI list out ambiguous points in the spec for you to confirm. For example, my spec above didn't specify whether deletion is soft or hard delete, whether deadlines are allowed to be in the past, or whether batch deletion is supported. The AI will list all these ambiguities and ask you.
/speckit.clarify
After answering, the spec is automatically updated. I've since developed a habit: no matter how simple the requirement, I always run clarify. It helps avoid at least 80% of requirement misunderstanding pitfalls.
Step 4: Write the Technical Implementation Plan (/speckit.plan)
This step translates requirements into a technical plan, specifying concrete implementation details. The tech stack constraints from the constitution are automatically applied.
/speckit.plan
The AI generates a technical plan based on the constitution and spec, including directory structure, interface definitions, and database table structure:
## Directory Structure
├── handler/
│ └── todo.go
├── service/
│ └── todo.go
├── model/
│ └── todo.go
└── router/
└── router.go
## Database Table Structure
CREATE TABLE `todos` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` text,
`deadline` datetime NOT NULL,
`status` tinyint NOT NULL DEFAULT '0' COMMENT '0-incomplete 1-complete',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Step 5: Generate Task List (/speckit.tasks)
This step breaks the plan down into executable tasks, each with clear acceptance criteria, similar to test cases in TDD.
/speckit.tasks
Each task in the generated tasks.md is small and explicit:
## task001, Initialize project structure
Acceptance criteria: Directory structure matches the plan definition, service can start normally
## task002, Implement to-do creation endpoint
Acceptance criteria: POST /api/todos can create a to-do, parameter validation is correct
Step 6: Execute Implementation (/speckit.implement)
This is the final step. The AI implements the code task by task according to the task list; you don't need to write any business logic manually.
/speckit.implement
After each task is completed, unit tests are automatically run. Once all pass, you are prompted to accept.
If I later need to change a requirement, like adding a "priority" field to to-dos, I don't need to modify the code. I directly modify spec.md, then execute /speckit.converge to check the consistency between the code and the spec, and then rerun /speckit.implement. The AI will automatically update the corresponding code.
There's a design philosophy here worth pondering. spec-kit completely separates "what to do" from "how to do it." The spec only governs intent, the plan only governs the technical path, and the code is merely the final expression of both. This means you can switch tech stacks at any time — just change the technology choices in the plan and re-implement; the spec doesn't need to change at all. Tomas Vesely, author of the GitHub official blog, even tried compiling a Go project's spec directly into another language, throwing away all the code and regenerating it.
Getting Started: From Installation to First Implementation (10 minutes)
Environment for this article: macOS / specify-cli v0.11.8 / Claude Code / Python 3.10+ / uv
Step 1: Install specify CLI
# Install specified version using uv
uv tool install specify-cli --from git+https://github.com/github/[email protected]
# Verify installation
specify --version
✅ Verification: Output specify-cli v0.11.8 indicates successful installation
Step 2: Initialize the Project
# Create project, specify Claude Code integration
specify init todo-api --integration claude
cd todo-api
✅ Verification: A .specify/ directory appears in the project directory, containing a constitution.md template and templates/ subdirectory
If you use other tools, just change the integration during initialization:
# Cursor users
specify init todo-api --integration cursor-agent
# Copilot users
specify init todo-api --integration copilot
# View all supported integrations
specify integration list
Step 3: Go Through the 5-Step Core Workflow
Execute in order:
/speckit.constitution → /speckit.specify → /speckit.clarify → /speckit.plan → /speckit.tasks → /speckit.implement
✅ Verification: After each step completes, check if the corresponding .md file is generated in the .specify/specs/ directory
Common Errors and Solutions
Error 1: uv tool install fails, prompting incompatible Python version
Cause: specify-cli requires Python 3.10+. If your system Python version is below 3.10, this error occurs. Solution:
# Use uv's built-in Python
uv tool install specify-cli --from git+https://github.com/github/[email protected] --python 3.12
Error 2: AI does not generate constitution.md after executing /speckit.constitution
Cause: spec-kit interacts with AI coding agents via slash commands. If your agent version is too old, it might not support slash commands. Solution: Upgrade your AI coding agent to the latest version, or check if the .claude/commands/ directory contains spec-kit related command files.
Continuity with Superpowers SDD: From Internal Mechanism to Universal Tool
Those who have read my previous article "Deep Dive into Superpowers v6.0 SDD Rewrite" should remember that the core design of Superpowers is Do Not Trust the Report — do not trust the subagent's self-reporting; results must be verified through diffs.
spec-kit essentially extracts the internal SDD methodology from Superpowers and turns it into a universal tool. The core logic is completely consistent:
| Superpowers (Internal Skill) | spec-kit (Universal Toolchain) |
|---|---|
| Subagent generates spec | /speckit.specify generates spec |
| Subagent verifies results (diff check) | /speckit.converge verifies code-spec consistency |
| Do Not Trust the Report principle | clarify step ensures spec is unambiguous |
| Only usable within Claude Code | Supports 30+ coding agents |
The core philosophy is Power Inversion — the spec is the boss, and code must obey the spec. In Superpowers, this was implemented through the subagent's internal architecture, invisible and unusable to ordinary people. In spec-kit, the same philosophy has become a slash command that anyone can execute.
The difference isn't in the methodology, but in accessibility. Superpowers is "SDD as engineering practice within a Skill," while spec-kit is "SDD opened up as a universal development workflow." The former requires you to install a specific Skill; the latter only needs a uv tool install.
3 Spec Persistence Models: How Different Teams Choose
This part is something many articles introducing spec-kit don't cover. I specifically looked through the official docs/concepts/spec-persistence.md and compiled the applicable scenarios for the three models.
| Model | Core Logic | Applicable Scenarios | Main Risk |
|---|---|---|---|
| Flow-back Spec | Artifacts can influence each other; changing code can update spec | Small teams (<5 people), rapid iteration | Silent drift, code changed but spec not updated |
| Flow-forward Spec | Completed artifacts are considered immutable; new requirements create new feature directories | Scenarios requiring auditing (finance, healthcare) | Many duplicate artifacts, high maintenance cost |
| Living Spec | spec.md is the sole contract; plan and tasks are disposable derivatives |
Stable product contracts, few requirement changes | Requires frequent spec updates when requirements change frequently |
To be honest, these three models weren't invented by spec-kit. Martin Fowler mentioned a similar classification when analyzing SDD tools: Spec-first (write spec first, then can discard), Spec-anchored (write spec, keep it, refer to it for subsequent changes), Spec-as-source (spec is the sole source, code is a derivative). spec-kit just turned these strategies into selectable configurations.
My personal recommendation: Teams under 10 people should directly use Flow-back for high flexibility; run /speckit.converge once a week to check consistency. Teams in finance must use Flow-forward to trace every requirement change during audits. Living Spec suits projects where the product is already stable and only needs maintenance and minor iterations — like your company's internal admin dashboard, where requirements might change only a few times a year.
Extensions and Presets System: Customize Your SDD Workflow
spec-kit supports extensions. You can add your own commands, hooks, or customize templates. Priority from high to low:
- Project-Local Overrides (
.specify/templates/overrides/) — Single project adjustments, doesn't change global settings - Presets — Customize core templates and terminology, e.g., change the default MIT license to your company's internal license
- Extensions — Add new commands, hooks, capabilities, e.g., automatically run code scanning after implement
- Core — spec-kit core default templates
Template resolution is runtime — spec-kit searches from top to bottom and uses the first match. This means you can almost completely customize the SDD workflow without modifying the core code.
For example, you can write a test extension that automatically runs unit tests after /speckit.implement completes. You can also customize a preset to change the default spec template format to your team's preferred style. The community has already contributed some extensions and presets, which can be found on the Community page of the spec-kit official documentation.
Pitfall Record: Don't Skip the Clarify Step
The first time I used it, I thought my requirements were clear enough and skipped the /speckit.clarify step. As a result, during the plan phase, the AI defaulted to soft delete for to-do deletion, while our requirement was hard delete. Fixing it later required changing three files: spec, plan, and tasks, taking nearly an hour.
Later, I ran clarify for every spec, even if the requirement was only three sentences long. The AI lists boundary conditions you might not have thought of: how to handle null values, how to resolve concurrency conflicts, what status code to return for exceptions. If these points aren't confirmed in advance, the AI just guesses during implementation, and if it guesses wrong, you have to rework.
Another pitfall: if the constitution only says "use Go" without specifying the framework, the AI might choose the standard library net/http instead of Gin. So, make the constitution as specific as possible: tech stack, framework versions, coding standards, prohibitions — don't miss a single one.
When to Use spec-kit, When Not To
Suitable scenarios:
- New projects from 0 to 1, requirements not fully thought out yet — writing the spec first helps clarify your thinking
- Adding new features to an existing system — the spec ensures new code is consistent with the existing architecture
- Team collaboration with frequent requirement changes — the spec is a shared source of truth, everyone sees the same thing
- Using AI coding agents to write code, often facing rework due to requirement misunderstanding — SDD can significantly reduce rework
Unsuitable scenarios:
- One-off scripts, temporary tools — writing the spec takes longer than writing the code
- Requirements are 100% clear and won't change — writing code directly is faster
- You don't use AI coding agents — the value of spec-kit lies in having AI generate code according to the spec; if you write everything manually, the spec is just extra burden
FAQ
Q: Will spec-kit make me write more documentation?
No. The constitution only needs to be written once. The subsequent spec, plan, and tasks are all AI-generated; you just need to confirm if they're correct. It actually saves time compared to repeatedly arguing with the AI about requirements.
Q: I use Copilot/Cursor, can I use spec-kit?
Yes. spec-kit supports 30+ coding agents. Just select the corresponding integration during initialization: specify init my-project --integration copilot or --integration cursor-agent.
Q: What if the generated code is not good?
Directly modify the spec and rerun /speckit.implement. No need to manually modify the code — manually changing code can easily lead to inconsistencies with the spec, and the converge check later will report conflicts.
Q: How to promote spec-kit within a team?
Start with a small requirement as a pilot, let everyone see that SDD indeed reduces rework. This is more effective than slogans. After a successful pilot, gradually promote it to larger projects.
Q: What happens to old code when the spec changes?
It depends on the persistence model you choose. In Flow-back mode, old code and old specs can coexist; new specs generate new code that gradually replaces the old. In Flow-forward mode, old code remains untouched, and new requirements are implemented independently in new feature directories. In Living Spec mode, just update the spec and regenerate directly.
My Judgment
The pitfalls I stepped into with vibe coding could fill three articles. Now, using spec-kit has reduced rework by at least 80%. This isn't because spec-kit is magical, but because the SDD methodology itself solves the biggest pain point of AI coding — ambiguous requirements leading to AI guessing. spec-kit just turned this methodology into an executable tool.
Honestly, SDD is not a new concept. The philosophy of Power Inversion (spec above code) has existed in backend architecture for a long time — interface contracts above implementation, API documentation above code. spec-kit just pushes this principle to a more extreme position: the spec doesn't just guide implementation; the spec directly generates implementation.
Later, I will update on how to write your own spec-kit extensions to integrate unit testing and code scanning into the SDD workflow. If interested, follow Code Brother Jumping, so you don't miss it. If you feel this article helped you avoid a few pitfalls, hit "Wow" to let me know, and feel free to forward it to friends still struggling with vibe coding failures.
References
- spec-kit official repository: https://github.com/github/spec-kit
- GitHub Official Blog: Spec-driven development with AI: https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit/
- GitHub Blog: Using Markdown as a programming language: https://github.blog/ai-and-ml/generative-ai/spec-driven-development-using-markdown-as-a-programming-language-when-building-with-ai/
- Code Brother Jumping: Deep Dive into Superpowers v6.0 SDD Rewrite
- Martin Fowler: Exploring SDD tools: https://martinfowler.com/articles/exploring-gen-ai/sdd-3-tools.html