0%

Claude-code-3-spec-kit

03-Spec Kit 规范驱动开发:从零到一完整项目实战

📝 前言

痛点:AI 总是“听不懂人话”?

你有没有遇到过这种情况:每次让 AI 写代码,它总是"自作聪明"地按它的理解来,结果和自己想的南辕北辙。

问题不在 AI,在于我们没把“图纸”画清楚。

在建筑行业,建筑图纸是建筑师的"语言",没人会不看图纸直接砌墙。同样,代码规范就是咱们和 AI 沟通的"语言"。Spec Kit 就是帮咱们快速生成这份"图纸"的工具——先设计,再施工,避免了"边盖边改"的尴尬。

本篇我们将从零开发一个完整的 Todo API,带你体验效率起飞的感觉。

一、 核心理念:为什么我们需要 SDD?

1.1 Spec Kit 简介

Spec Kit 是一个规范驱动开发(Specification-Driven Development, SDD)工具,由 GitHub 开源。它的核心理念特别简单:

先写规范,再写代码。规范就是最好的文档,也是最好的 AI 提示词。

在传统模式下,我们往往习惯直接让 AI 写代码,结果就是陷入“生成 -> 报错/不符预期 -> 修补 -> 再修补”的死循环。而 SDD 的核心逻辑是:代码是规范的实现,规范是代码的契约。

我们可以通过一张流程图来对比这两种模式:

graph TD
    subgraph 传统模式 ["🚫 传统模式 (容易返工)"]
        A1[脑暴需求] --> B1[直接让AI写代码]
        B1 --> C1{符合预期?}
        C1 -- No --> D1[反复修补代码]
        D1 --> B1
        C1 -- Yes --> E1["补文档(通常会忘)"]
    end
    
    subgraph SDD模式 ["✅ SDD模式 (一次成型)"]
        A2[明确需求] --> B2[编写 Spec 规范]
        B2 --> C2[Claude 读取规范]
        C2 --> D2[一次性生成高质量代码]
        D2 --> E2[规范即文档]
    end
    
    style 传统模式 fill:#fff0f0,stroke:#ffcccc
    style SDD模式 fill:#f0fff4,stroke:#ccffcc

SDD 的三大好处

  1. 效率提升:规范写好后,AI 可以一次性生成符合要求的代码,减少反复修改
  2. 质量保证:规范中包含测试策略,代码生成后可以自动验证
  3. 协作友好:规范就是文档,团队成员可以快速理解功能设计

1.2 Spec Kit + Claude Code 的化学反应

Claude Code 本身就很聪明,但如果有个清晰的"说明书",它能更精准地理解你的需求。Spec Kit 生成的规范文件(Markdown 格式)可以直接被 Claude Code 读取,作为上下文来生成代码。

工作流程是这样的

graph LR
    A[创建规范] --> B[编辑规范文件]
    B --> C[Claude Code读取规范]
    C --> D[生成符合规范的代码]
    D --> E[测试验证]

    style A fill:#e1f5ff
    style B fill:#fff4e1
    style C fill:#f0e1ff
    style D fill:#e1ffe1
    style E fill:#ffe1e1

实际使用示例

1
2
3
4
5
6
7
8
9
# 步骤1:创建规范
specify add rag-feature --type llm-feature

# 步骤2:编写规范(编辑 .specify/specs/rag-feature.md)
vim .specify/specs/rag-feature.md

# 步骤3:告诉 Claude Code 根据规范生成代码
claude-code # 启动 Claude Code
> "根据 .specify/specs/rag-feature.md 规范,帮我实现 RAG 功能"

就这么简单!✨ 真的是一试就知道有多香。

1.3 安装与初始化

Spec Kit 是一个基于 Node.js 的工具,安装非常简单:

1
2
3
4
5
# 全局安装 Spec Kit CLI
npm install -g @github/spec-kit

# 验证安装
specify --version

💡 踩坑经验

如果你在国内,npm 安装可能会很慢(我第一次装就等了半天),建议使用淘宝镜像:

1
npm config set registry https://registry.npmmirror.com

设置之后,速度起飞!🚀

1.4 初始化 Spec Kit 项目

在项目根目录执行初始化,

在项目根目录执行:

1
2
3
# 初始化 Spec Kit 配置

specify init

它会交互式地询问你项目类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> specify init

# 交互式问答:
# ? 项目名称: todo-api
# ? 项目描述: 智能 Todo API
# ? 输出目录: src
# ? 是否包含测试: Yes
# ? 测试框架: pytest

# 执行后会创建:
# .specify/
# ├── config.yaml # Spec Kit 配置
# ├── templates/ # 规范模板
# │ ├── llm-feature.md
# │ ├── api-endpoint.md
# │ └── data-pipeline.md
# └── specs/ # 存放功能规范
# └── README.md

初始化完成后,你的项目里会多出一个 .specify 文件夹,里面包含了配置和核心模板。

配置文件详解 config.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Spec Kit 项目配置
project:
name: "tutor-python-ai"
version: "1.0.0"
description: "Python AI/LLM 应用学习项目"

# 规范配置
spec:
dir: ".specify" # Spec Kit 根目录
specs_dir: ".specify/specs" # 规范文件目录
template_dir: ".specify/templates" # 模板目录
output_dir: "src" # 代码输出目录

# AI 配置(Claude Code 会读取这些配置)
ai:
provider: anthropic # 提供商:anthropic / openai
model: claude-3-5-sonnet-20241022 # 模型版本
temperature: 0.1 # 温度参数(越低越确定性)
max_tokens: 4000 # 最大 Token 数

# 生成配置
generation:
override: false # 是否覆盖已存在的文件
include_tests: true # 是否生成测试文件
include_docs: true # 是否生成文档
test_framework: pytest # 测试框架
docstring_style: google # 文档字符串风格

# 验证配置
validation:
strict: false # 严格模式(规范与代码不一致时是否报错)
check_consistency: true # 检查一致性
check_type_annotations: true # 检查类型注解

# Python 特定配置
python:
version: "3.10" # Python 版本
use_type_hints: true # 使用类型提示
use_async: true # 使用异步语法

💡 小贴士temperature 参数很重要!

  • 0.1-0.3:适合生成代码(稳定、确定性高)
  • 0.7-0.9:适合创意写作(多样性高)

1.3 核心概念:规范模板 (The Blueprint)

Spec Kit 的强大之处在于它预置了许多模板(位于 .specify/templates/),这比我们手写 Prompt 强太多了:

  • llm-feature.md: 专门用来定义 RAG、对话、分类等 AI 功能。
  • api-endpoint.md: 定义 REST API 接口(输入输出、错误码、数据模型)。
  • data-pipeline.md: 定义数据处理流(ETL)。

1.3.1 模板 1:llm-feature.md - LLM 功能规范

适用场景:需要调用 LLM API 的功能(如对话、摘要、翻译等)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
---
spec_version: "1.0"
type: llm-feature
priority: high
---

# [功能名称]

## 概述
[功能描述,说明这个 LLM 功能的用途]

## LLM 配置

### 模型选择
- **提供商**: OpenAI / Anthropic / 本地模型
- **模型名称**: gpt-4 / claude-3-opus-200k
- **温度**: 0.7
- **最大 Token**: 2000

### 提示词策略
- **提示词文件**: `prompts/[feature_name].txt`
- **变量**: [列出需要替换的变量]
- **版本**: v1.0

## 功能需求
- [需求1]
- [需求2]

## 数据流
<pre class="mermaid">graph LR
A[输入] --> B[预处理]
B --> C[LLM 调用]
C --> D[后处理]
D --> E[输出]</pre>

## API 端点(如果适用)
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/[feature] | [说明] |

## 错误处理
- API 调用失败:[处理策略]
- 超时处理:[超时时间,重试次数]
- 成本控制:[预算限制]

## 测试策略
- 单元测试:[测试内容]
- 集成测试:[测试内容]
- 提示词测试:[测试用例]

## 成本估算
- 预估 Token/请求:[数量]
- 预估成本/请求:[金额]
- 预估日请求量:[数量]

## 实现
### 文件结构
```
src/
├── prompts/
│ └── [feature_name].txt
├── chains/
│ └── [feature_name]_chain.py
└── api/
└── [feature_name]_routes.py
```

### 关键函数
- `process_[feature](input)`: [说明]
- `[feature]_chain()`: [说明]

1.3.2 模板 2:api-endpoint.md - API 端点规范

适用场景:REST API 端点设计(CRUD 操作等)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
---
spec_version: "1.0"
type: api-endpoint
priority: medium
---

# [API 端点名称]

## 概述
[API 端点的功能描述]

## API 定义

### 端点信息
| 项目 | 值 |
|------|-----|
| 方法 | POST / GET / PUT / DELETE |
| 路径 | `/api/[resource]` |
| 认证 | Bearer Token / API Key |

### 请求格式
```json
{
"field1": "value1",
"field2": "value2"
}
```

### 响应格式
```json
{
"success": true,
"data": {},
"message": "操作成功"
}
```

## 数据模型
```python
from pydantic import BaseModel

class RequestModel(BaseModel):
"""请求模型"""
field1: str
field2: int

class ResponseModel(BaseModel):
"""响应模型"""
success: bool
data: dict
message: str
```

## 业务逻辑
1. [步骤1]
2. [步骤2]
3. [步骤3]

## 错误处理
| 状态码 | 场景 | 处理方式 |
|--------|------|----------|
| 400 | 请求参数错误 | 返回错误信息 |
| 401 | 未认证 | 返回认证错误 |
| 500 | 服务器错误 | 记录日志并返回通用错误 |

## 测试用例
```python
def test_api_endpoint():
"""测试 API 端点"""
response = client.post("/api/[resource]", json={})
assert response.status_code == 200
```

## 实现
### 文件位置
```
src/api/
└── [resource]_routes.py
```

### 路由定义
```python
from fastapi import APIRouter

router = APIRouter(prefix="/api/[resource]", tags=["[Resource]"])

@router.post("/")
async def create_[resource](request: RequestModel):
"""创建 [资源]"""
pass

1.3.3 模板 3:data-pipeline.md - 数据管道规范

适用场景:数据处理流程(ETL、数据清洗、向量化等)

完整模板内容可以参考项目中的 .specify/templates/data-pipeline.mdspec-package Download Now

二、 实战演练:开发一个智能 Todo API

光说不练假把式。我们来从零开发一个 带有 AI 自动分类功能的 Todo API

技术栈:FastAPI + SQLite (SQLAlchemy Async) + 智谱 GLM-4.7

2.1 第一步:配置项目上下文 (CLAUDE.md)

首先,在项目根目录创建 CLAUDE.md,锁定技术栈。这一步至关重要,防止 Claude 放飞自我。

1
2
3
4
5
6
7
8
9
10
11
12
13
# Todo API 项目配置

**技术栈**:
- Python 3.10+
- FastAPI 0.104+
- SQLAlchemy (Async / aiosqlite)
- 智谱 GLM-4.7 (通过 Claude Code 调用)

**开发规范**:
- 代码必须符合 Pydantic V2 标准。
- 数据库操作**必须**使用异步 (async/await)。
- 提示词文件放在 `src/prompts/` 目录。
- 所有的 API 必须有 Swagger 文档注释。

然后,初始化 Memory,让 Claude 记住项目背景:

1
2
claude
>> /memory remember "这是一个 Todo List 项目,核心功能包含 CRUD 和基于 LLM 的任务智能分类"

2.2 第二步:编写 CRUD 规范

使用 Spec Kit 添加一个 API 规范:

1
specify add todo-crud --type api-endpoint

然后编辑生成的 .specify/specs/todo-crud.md这一步是质量的关键,写得越细,生成的代码越完美。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
---
spec_version: "1.0"
type: api-endpoint
---

# Todo CRUD 功能

## 数据模型
```python
class TodoCreate(BaseModel):
title: str = Field(..., min_length=1, max_length=200)
description: Optional[str] = Field(None)
# 允许为空,为空时触发自动分类
category: Optional[Literal["工作", "生活", "学习"]] = None
priority: Literal["高", "中", "低"] = "中"
```

## API 接口定义
1. **POST /api/todos** (创建任务):
- 验证请求参数。
- 如果 `category` 为空,**必须调用 LLM Service** 进行自动分类。
- 存入 SQLite 数据库。
- 返回 201 Created。
2. **GET /api/todos** (获取列表):
- 支持 `category` 查询参数过滤。
- 按 `created_at` 倒序排列。
3. **PUT /api/todos/{id}** (更新任务):
- 支持部分更新 (PATCH 逻辑)。

## 错误处理

| **状态码** | **场景** |
| ---------- | ----------------------------- |
| 404 | Todo ID 不存在 |
| 500 | 数据库连接失败或 LLM 服务超时 |

2.3 第三步:编写 LLM 智能分类规范

我们需要一个 AI 服务,根据任务标题自动分类。

1
specify add todo-llm --type llm-feature

编辑 .specify/specs/todo-llm.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 规范:智能分类服务

## 功能描述
输入任务标题和描述,输出 ["工作", "生活", "学习"] 三者之一。

## 提示词策略 (Prompt Engineering)
- **文件**: `src/prompts/classify_todo.txt`
- **模型**: glm-4-plus (智谱 GLM-4.7)
- **温度 (Temperature)**: 0.1 (我们需要稳定的输出,不要发散)

## 提示词模板
```text
你是一个任务分类助手。请根据以下任务标题,将其分类为 [工作, 生活, 学习] 之一。
只返回类别名称,不要返回任何其他字符。

任务标题: {title}
任务描述: {description}
```

## 容错机制

- 设置 5 秒超时。
- 增加 2 次重试机制 (Exponential Backoff)。
- 如果 LLM 彻底失败,默认返回 `None` (由前端处理)。

我在规范里特别强调了容错处理

  • 如果 LLM 超时,默认归类为“未分类”,不要报错崩掉。
  • Prompt 模板直接写在规范里,方便后续调优。
sequenceDiagram
    participant User
    participant API
    participant LLM_Service
    participant Model as GLM-4.7

    User->>API: 创建 Todo (无分类)
    API->>LLM_Service: 调用分类服务
    LLM_Service->>Model: 发送 Prompt (标题+描述)
    Model-->>LLM_Service: 返回 "工作/生活/学习"
    LLM_Service-->>API: 补全分类字段
    API-->>User: 返回完整 Todo

2.4 第四步:见证奇迹的时刻 (AI Coding)

现在“图纸”画好了,让 Claude Code 开工!

在 Claude CLI 中输入:

“根据 .specify/specs/todo-crud.md 和 todo-llm.md 的规范,帮我实现整个后端代码。包括 Models、API 路由、LLM 服务层和 main.py。”

Claude 的执行逻辑:

  1. 读取 todo-crud.md -> 生成 Pydantic 模型和 SQLAlchemy Table。
  2. 读取 todo-llm.md -> 生成 classify_todo 函数,包含重试逻辑和 Prompt 加载逻辑。
  3. 组合代码 -> 生成 main.py 和路由。

你会发现,生成的代码完全对应你的规范,连重试次数和超时时间都一模一样。

2.5 第五步:测试与验证

让 AI 生成测试代码:

“根据规范中的测试用例章节,为 src/api/todo_routes.py 生成 pytest 测试,使用 TestClient。”

运行测试:

1
pytest -v

三、 总结

规范驱动开发 (SDD) 加上 AI 编程助手,简直是绝配。

  • 以前:你脑子里有个想法 -> AI 瞎猜 -> 你改 Bug。
  • 现在:你写好 Spec 文档 -> AI 照着写 -> 一次跑通。

这不仅提升了代码质量,更重要的是——文档和代码永远是同步的。Spec Kit + Claude Code 的组合,本质上是把写代码变成了写文档

  • 如果你不仅想做一个 Coder,更想做一个 Designer,这套工作流绝对适合你。
  • 规范越详细,AI 的“幻觉”就越少。
  • 磨刀不误砍柴工,古人诚不欺我。

下一步:如果你对如何让 Claude Code 变得更智能(比如自己查资料、操作 Git)感兴趣,请移步阅读下一篇《Agent 系统与 MCP 高级玩法》。

下一篇,我们将进入真正的高级玩家领域:Agent 系统与 MCP 协议。我们要让 Claude 连上网、连上数据库,自己去干活!

📖 参考来源

-------------This blog is over! Thanks for your reading-------------