OpenSpec 综合指南:使用动机与实践
什么是规范驱动开发(SDD)?
SDD(Specification-Driven Development):先写可验收的规格与设计,再按文档实现。先定「做什么」「怎么做」,实现只负责落地,验收有据、决策可查;和 AI 协作时按规范生成,少跑偏、少返工。
参考:
blog.dengqi.org/posts/%E8%A...
cloud.tencent.com/developer/a...
什么是 OpenSpec?
OpenSpec 是面向 AI 编码助手 (Cursor、Claude Code、Copilot 等)的规范驱动 开源框架,把 SDD 做成可执行闭环:共识规范 → AI 按规范执行 → 自动验证。人与 AI 先一起写出结构化规范(功能、边界、用例等),AI 据此生成代码或变更,框架再按规范中的验收条件做检查;配合审查与归档,变更可追溯、可审计。
特点:轻量(文件 + CLI,无 API 密钥)、适合既有项目增量改动、提案/规格/设计/任务全生命周期可追踪、通过 /opsx 等命令与 AI 协同。模糊需求易让 AI 跑偏;先落规范再让 AI 落地,歧义少、可维护性高。
开源工具对比:juejin.cn/post/759475...
OpenSpec 适合在已有项目内 添加规范驱动开发流程,适合需求有明确边界 、且不希望学习成本太高、开发流程改动太大的场景。
是否要使用规范驱动开发?
- 适合用:有边界的变更(一个需求、一次重构),需要和产品/测试对齐、留决策记录,或实现要拆多步、多人/多次做。
- 可以不用:问代码、小修小补(改文案、调样式)、探路试错、个人一次性修改,不打算留规格时,直接和 LLM 聊即可。
准备工作与快速开始
安装 CLI
bash
npm install -g @fission-ai/openspec@latest
在项目中初始化
bash
cd your-project-directory
openspec init
初始化完成后,项目根下会多出 openspec/ 目录,并可能包含与 AI 助手对接的 Skill 和 Command(具体因发行版和集成方式而异)。典型结构类似:
bash
openspec/
├── config.yaml # 项目配置,如 defaultSchema
├── changes/ # 进行中的变更(每个变更一个子目录)
└── specs/ # 主 spec(可选,sync 后存在)
.cursor/ # 若集成 Cursor,可能包含
├── commands/ # /opsx:new、/opsx:continue、/opsx:apply 等
│ └── opsx-*.md
└── skills/ # openspec-new-change、openspec-apply-change 等
└── openspec-*/
首次使用建议 :在 AI 助手里输入
/opsx:onboard走一遍完整流程,可以更好理解下文。
一、工件
一般来说,一个标准的 openspec 变更流程会包含以下四个工件,执行 opsx:continue 时,会按顺序逐渐完成这四个工件。
四个(类)工件对应四类问题,按依赖顺序形成一条线;缺哪一类都会在协作或验收时出问题。
| 工件 | 回答的问题 | 产出物 | 依赖 | 若没有会怎样 |
|---|---|---|---|---|
| Proposal | 为什么做、做哪些能力、影响谁 | proposal.md |
无 | 范围漂移、复盘不知当初为何做 |
| Specs | 做什么(可验收的行为) | specs/**/*.md |
Proposal | 验收标准模糊,测试无法系统化 |
| Design | 怎么做(技术决策) | design.md |
Specs | 实现时临时拍脑袋,事后难以解释、换人难接手 |
| Tasks | 拆成哪些步骤、做到哪了 | tasks.md |
Design | 实现难以跟踪进度,apply 无法扫「下一项是什么」 |
一条线:Proposal 定范围 → Specs 定行为(Requirement + WHEN/THEN)→ Design 定方案 → Tasks 拆步骤 → Apply 按 Tasks 做,Verify 用 Specs/Design 验。
二、设计理念
2.1 用「工件 + 依赖图」而不是「线性阶段」
设计选择 :变更由多个工件(artifact)组成,工件之间有依赖关系(如 Design 依赖 Specs);「下一步能做什么」由依赖是否满足决定,而不是强制你按固定阶段一步步走。
原因 :依赖满足了就能写下一件,不用等评审(例如 Specs 写完就能写 Design)。发现不对可以只改那一件、顺带更新下游,不用推倒重来。CLI 靠「文件在不在」和 schema 的 requires 就知道能创建啥,人也能一眼看出还缺啥。所以是 "Artifact graph, not a workflow engine":依赖决定能干啥,阶段不锁死。
2.2 先「做什么」再「怎么做」
设计选择 :在 schema 里 Specs 无前置依赖(或只依赖 Proposal),Design 依赖 Specs,Tasks 依赖 Design。即:先有「做什么」,再有「怎么做」,最后是「拆成哪些步骤」。
原因 :先写 Design 容易变成「能实现啥就写啥」;先写 Specs 把「要什么」定死,Design 再在约束下选方案。验收时先对 Specs(行为对不对),再对 Design(实现对不对)。产品/测试看 Specs,开发看 Design,各看各的,不掺在一起。这就是 spec-driven:规格驱动实现,而不是反过来。
2.3 文件即状态,无隐藏状态
设计选择 :完成没完成只看文件在不在、写没写好;没有数据库、没有「阶段」字段,变更目录就是状态。
原因 :状态全在仓库里,git 能追溯;不需要单独服务,有文件就能跑;打开 openspec/changes/<name>/ 就是完整快照。即 "Filesystem-as-database":完成度从文件推出来,不存别处。
2.4 支持多 schema,不绑死一种流程
设计选择 :通过 schema(如 no-proposal、spec-driven)定义「有哪些工件、谁依赖谁、apply 时依赖谁、跟踪哪个文件」。项目可以选默认 schema,也可以为某个变更指定 schema。
原因:有人要 Proposal 对齐范围,有人小改直接 Specs 起步(no-proposal)。新流程就新 schema,不动核心逻辑。同一仓库里大需求用完整 schema、小修用精简 schema,按变更选就行。
三、各工件示例
以下是全部按 openspec skill 生成之后的工件示例。
3.1 Proposal(提案)
| 区块 | 写法要点 | 说明 |
|---|---|---|
| Why | 背景与动机 | 范围争执时能回到共识。 |
| What Changes | 变更要点(简短列表) | 让人快速看懂轮廓。 |
| Capabilities | 新增/修改的能力(每能力可对应一个 spec) | 与 Specs 对应,边界清晰。 |
| Impact | 影响的模块/文件 | 评估改动面、排期、风险。 |
示例
markdown
## Why
读者借书后容易忘记归还或续借,导致逾期;在图书即将到期时给予站内提示,可降低逾期率、提升体验。
## What Changes
- 在个人中心页增加「即将到期」的提示展示(如:您有 2 本图书 3 天内到期)
- 用户点击可进入借阅明细页进行续借或查看
## Capabilities
### New Capabilities
- **借阅到期提醒展示**:在个人中心展示即将到期本数与跳转入口,支持跳转至借阅明细页
### Modified Capabilities
- 无
## Impact
- 个人中心页 / 借阅模块:增加顶部提示条与跳转
- 复用现有借阅列表接口与借阅状态
3.2 Specs(规格)
| 区块 / 约定 | 写法要点 | 说明 |
|---|---|---|
| ADDED / MODIFIED / REMOVED / RENAMED | 按增/改/删/重命名分块;RENAMED 用 FROM:/TO: | 只写「这次改了什么」。变更 spec 在 changes/<name>/specs/,主 spec 在 specs/<capability>/spec.md;sync 时把变更合并进主 spec。 |
| Requirement + Scenario | 每需求下多 Scenario,用 WHEN / THEN / AND | WHEN=触发条件,THEN=结果,AND=额外约束;可对应用例和测试,不写实现细节。 |
示例
markdown
## ADDED Requirements
### Requirement: 有图书即将到期时对读者进行提示
当读者有图书在 3 天内到期时,在合适入口给予提示,引导续借或归还。
#### Scenario: 有即将到期图书时展示
- **WHEN** 读者有至少一本图书在 3 天内到期,且进入个人中心页
- **THEN** 在个人中心顶部看到提示条(如「您有 2 本图书即将到期,点击查看」)及跳转按钮
- **AND** 点击可进入借阅明细页,或可暂时关闭本次提示
#### Scenario: 无即将到期图书时不展示
- **WHEN** 读者当前没有 3 天内到期的图书
- **THEN** 个人中心不展示到期提醒
多文件说明 :Schema 中 specs 的产出为 specs/**/*.md,可按能力/模块 拆成多个文件,例如 specs/due-reminder/spec.md(到期提醒)、specs/borrow-list/spec.md(借阅列表)。
3.3 Design(设计)
| 区块 | 写法要点 | 说明 |
|---|---|---|
| Context | 背景与现状 | 系统/模块现状 + 本变更在其中的位置,让人不翻代码也能懂约束。 |
| Goals / Non-Goals | 目标与明确不做的 | 做啥、不做啥,防 scope creep。 |
| Decisions | 关键决策 + 备选与理由 | 选了啥、为啥、放弃过啥,可追溯。 |
| Risks / Trade-offs | 风险与取舍 | 已知风险和取舍写清楚,避免上线踩坑。 |
示例
markdown
## Context
已有个人中心页与借阅明细页、借阅列表接口;需在个人中心增加「即将到期」的提示展示与跳转。
## Goals / Non-Goals
**Goals:**
- 当读者有图书在 3 天内到期时,在个人中心顶部露出提示条
- 点击可进入借阅明细页进行续借或查看
**Non-Goals:**
- 不做短信/邮件提醒;本需求仅站内展示
## Decisions
### 1. 数据来源
在已有借阅列表接口中扩展「即将到期本数」等汇总字段,不单独为提醒加一次接口。
**Alternatives considered:**
- 单独「到期提醒」接口:被拒,避免多一次请求,借阅列表本身会拉取。
### 2. 展示形态与入口
使用个人中心页顶部的提示条位,插入一条文案(如「您有 N 本图书即将到期」)+ 按钮「去查看」,点击跳转借阅明细页。
### 3. 展示逻辑
按「进入个人中心」时根据接口返回的汇总数据决定是否展示,不做「今日已展示过则不再展示」的本地记忆。
## Risks / Trade-offs
- 若后续在「借阅列表页」等也加提醒,需统一文案与跳转逻辑;本期优先只在个人中心落地。
3.4 Tasks(任务)
| 约定 | 写法要点 | 说明 |
|---|---|---|
| checkbox | - [ ] 未完成,- [x] 已完成;按模块分组,可带验收说明 |
apply 能解析「下一项是啥」;做完就打勾,断点续做。 |
示例
markdown
## Implementation Tasks
### 1. 数据与接口
- [ ] 1.1 确认借阅列表接口是否已有「即将到期本数」等字段,若无则与后端约定扩展
- [ ] 1.2 在借阅 store 或 data 层解析汇总数据与展示条件(如 dueWithinDays ≤ 3)
### 2. 展示组件
- [ ] 2.1 在个人中心页顶部增加到期提醒条(文案、「去查看」跳转链接)
- [ ] 2.2 根据接口返回与条件控制展示/隐藏(有即将到期则展示,否则不展示)
### 3. 联调与校验
- [ ] 3.1 有 0 本 / 1 本 / 多本即将到期等场景自测,文案与数量正确
- [ ] 3.2 点击跳转至借阅明细页并校验参数正确
四、 常用命令
/opsx:new 与 /opsx:ff 的区别
| 方式 | 节奏 | 适合场景 |
|---|---|---|
| /opsx:new | 先建变更,再一个工件一个工件地创建;每步都可和你对齐 | 需求还在细化、想逐步对齐、或希望每个工件都审一遍再继续 |
| /opsx:ff | 一次性生成 Specs → Design → Tasks,直到可 apply | 需求已经比较清晰,想尽快拿到全部工件并开始实现 |
/opsx:new:一个工件一个工件来
不必一次说完,给个变更名或一两句就行,例如 opsx:new 借阅到期提醒。建好变更后 AI 会给出当前要写的工件模板并等你。每个工件写的时候再补充(例如写 Specs 时贴场景,写 Design 时贴技术约束)。有 PRD 就在写对应工件那步粘贴:「用下面这段写当前这个」。
/opsx:ff:一次性生成到可 apply
第一次输入就把背景、要做什么、关键场景(和技术约束)说清楚,AI 一轮能生成更好的 Specs/Design/Tasks。只给变更名也能生成,但多半要事后多改几笔。推荐这样写:
diff
```
变更名:borrow-due-reminder
背景:读者借书后容易忘记归还或续借导致逾期,想在图书即将到期时用站内提示降低逾期率。
要做的:
- 当读者有图书在 3 天内到期时,在个人中心页顶部展示提示(如「您有 N 本图书即将到期」),点击可进入借阅明细页。
- 没有即将到期图书时不展示;多本即将到期时展示「共 N 本即将到期」。
- 仅站内展示,不做短信/邮件推送。
技术约束(可选):复用借阅列表接口,在接口里扩展「即将到期本数」等字段;用个人中心现有的顶部提示条位。
```
简要对照
| 你给的输入 | /opsx:new | /opsx:ff |
|---|---|---|
| 只给变更名 | ✅ 可以,后续每个工件再细说 | ⚠️ 可以但 LLM 会多推断,建议补几句背景和要做什么 |
| 给名字 + 一段描述 | ✅ 第一份工件会更有依据,后续可继续按工件补充 | ✅ 推荐:一段里包含背景、要做什么、关键约束 |
| 有 PRD/文档 | ✅ 在写到某个工件时粘贴并说「用这段写当前这个」 | ✅ 开头粘贴并说「按下面生成全部工件」 |
完整流程中的其他命令
从「建变更」到「收尾」会用到整条命令链,建议按阶段使用:
| 阶段 | 命令 | 作用 |
|---|---|---|
| 规划 | /opsx:explore |
先想清楚问题、看代码,不写实现;可随时用。 |
| 建变更 | /opsx:new、/opsx:ff |
新建变更;new 逐步写工件,ff 一次性生成。 |
| 写工件 | /opsx:continue |
new 之后,一个工件一个工件写下一个(Specs → Design → Tasks)。 |
| 实现 | /opsx:apply |
按 tasks.md 逐项实现并打勾。 |
| 验收前 | /opsx:verify |
校验实现是否满足变更里的 specs/design/tasks;不合并 spec。 |
| 合并 spec | /opsx:sync |
把变更里的 delta spec 合并进主 spec(openspec/specs/);可选,归档前若有 delta 常会提示先 sync。 |
| 收尾 | /opsx:archive |
归档单个变更;归档后位于 openspec/changes/archive/YYYY-MM-DD-<name>/。 |
| 收尾 | /opsx:bulk-archive |
批量归档多个变更。 |
典型顺序:new 或 ff →(若 new)continue 直到工件写完 → apply → verify → 需要时 sync → archive。
五、自定义 Schema
5.1 Schema 是什么
OpenSpec 的 schema 定义一条变更流程里「有哪些工件、谁依赖谁、从哪里开始能 apply、跟踪哪个文件」。同一仓库可以只有一种 schema,也可以放多种,新建变更时选一个用。
5.2 自定义 schema 的常见做法
要不同工件组合时:openspec schema fork <已有> <新名> 或 openspec schema init <新名>。
bash
openspec/schemas/my-schema/
├── schema.yaml # 该 schema 的定义(工件列表、依赖、apply 配置)
└── templates/ # 各工件模板
├── design.md
├── specs/
│ └── spec.md
└── tasks.md
接着编辑 schema.yaml 和 templates/ 里内容,用 openspec schema validate my-schema 校验;在 openspec/config.yaml 里设 defaultSchema: my-schema,或建变更时加 --schema my-schema。