OpenSpec(SDD规范驱动开发)——给 AI Coding 的一份开发规约
OpenSpec 是什么
我们在使用AI写代码的时候,可能时长遇到过这种情况:让 AI 帮你写个功能,它噼里啪啦写了一堆代码,你一看方向就错了。你想要的暗色模式是跟随系统偏好自动切换,它给你做了个手动按钮还绑了一堆 localStorage 逻辑。改吧,改了半天又跑偏了。
这个问题的根源很简单:我们和 AI 之间没有一个明确的规约。脑子里想的和它理解的不是一回事,我们没有白纸黑字写清楚。
那OpenSpec 就是来解决这个事的。
它是一个轻量级的"规范驱动开发"框架。名字听着有点唬人,做的事情其实很朴素:在你让 AI 写代码之前,先跟它对齐要做什么、怎么做、做到什么程度算完。对齐的结果写在 Markdown 文件里,存在你的项目仓库中,跟着代码一起版本控制。
具体来说,OpenSpec 做了这么几件事:
- 每次变更都有一个独立的文件夹,里面放着提案(为什么做)、规范(做什么)、设计(怎么做)和任务清单(分几步做)
- AI 在动手写代码之前,先把方案拉出来给你看
- 你确认了再让它动手,不满意就改方案
- 做完之后,规范自动合并到项目的"知识库"里,下次谁来看都知道这段代码为什么长这样
跟随便"vibe coding"(就是那种"让 AI 随便写写看"的方式)相比,OpenSpec 多加了一层规划。但这层规划不重,不需要你写几十页的需求文档。大多数时候,几分钟就够了。
跟其他工具的关系?
其实还有类似的工具,比如 GitHub 的 Spec Kit、AWS 的 Kiro 之类。它们解决的是同一类问题,但思路不同。Spec Kit 比较重,有严格的阶段门禁,Python 环境配置一堆。Kiro 锁定在它自己的 IDE 里,只能用 Claude 模型。OpenSpec 走的是轻路线:不挑 AI 工具(目前支持 25 种以上,包括 Claude Code、Cursor、Codex、Windsurf、GitHub Copilot、Gemini CLI 等),不需要 MCP,不需要 API Key,就是普通的 Markdown 文件和命令行。
它还跟 AGENTS.md 配合得很好。AGENTS.md 是告诉 AI "这个项目怎么干活"的,OpenSpec 是告诉 AI "这次变更具体要做什么"的。两者各管一层,不冲突。
OpenSpec 安装
安装
前提:Node.js,没有的话先安装。
npm 用户:
npminstall-g@fission-ai/openspec@latestpnpm 用户:
pnpmadd-g@fission-ai/openspec@latestyarn 用户:
yarnglobaladd@fission-ai/openspec@latest安装完之后跑一下openspec --version,能输出版本号就说明装好了。
项目初始化
进入你的项目目录,执行:
cdyour-project openspec init它会问你用的是什么 AI 工具。选你正在用的那个就行。这一步做的事情是:
- 在项目根目录下创建
openspec/目录 - 根据你选的 AI 工具,往对应的位置写入斜杠命令文件(比如 Claude Code 会写到
.claude/commands/和.claude/skills/,Cursor 会写到.cursor/commands/) - 创建
openspec/config.yaml配置文件(可选) - 创建
openspec/project.md项目知识库(空的,等你填)
初始化完成之后,你就可以在 AI 助手的聊天窗口里输入斜杠命令了。
更新
OpenSpec 升级分两步。先升级全局包:
npminstall-g@fission-ai/openspec@latest然后在每个项目里刷新一下生成的文件:
openspec update这一步会重新生成斜杠命令文件,确保命令跟最新版本匹配。
卸载
没有专门的卸载命令。删全局包,再删项目里的openspec/目录就行了:
npmuninstall-g@fission-ai/openspec不过我建议留着openspec/specs/和openspec/changes/archive/,那里面存着你项目的功能规范和变更历史,删了就没了。
OpenSpec 的文件结构
文件结构及作用
执行完openspec init之后,你的项目里会多出这些东西:
openspec/ ├── specs/ # 规范库(你系统的行为真相) │ └── <domain>/ │ └── spec.md ├── changes/ # 变更提案(每个变更一个文件夹) │ └── <change-name>/ │ ├── proposal.md │ ├── design.md │ ├── tasks.md │ └── specs/ # 规范差异(这次变更会改什么) │ └── <domain>/ │ └── spec.md ├── project.md # 项目知识库 └── config.yaml # 项目配置(可选)另外根据你选的 AI 工具不同,还会在工具特定的目录下生成一些文件。比如 Claude Code 的话:
.claude/ ├── skills/ │ └── openspec-*/ │ └── SKILL.md ├── commands/ │ └── opsx/ │ ├── propose.md │ ├── apply.md │ └── archive.md └── CLAUDE.md # 里面会注入一段 OpenSpec 的标记Cursor 的话是写到.cursor/commands/下面,文件名格式也略有不同。但这些都是 OpenSpec 自动处理的,你不用操心具体写到哪。
各个目录和文件是干嘛的?
(1)openspec/specs/是规范库,也就是你系统当前行为的"唯一真相来源"。里面的文件按领域组织。比如specs/auth/spec.md描述认证模块的行为,specs/checkout-payment/spec.md描述支付模块的行为。一开始这个目录是空的,随着你不断做变更,规范会逐渐积累起来。
(2)openspec/changes/是变更提案区。每次你想做一个新功能或重大改动,这里会多出一个文件夹。文件夹名就是变更的 ID,比如add-dark-mode。里面放着四个东西:
proposal.md是提案,写为什么要做、做什么、大方向怎么做specs/是差异规范,用 ADDED/MODIFIED/REMOVED 标记这次变更会影响哪些需求design.md是技术设计,写具体的技术方案和架构决策tasks.md是任务清单,把实现拆成一个个带 checkbox 的小任务
这四个文件的关系是层层递进的:
proposal → specs → design → tasks → 写代码但你随时可以回头改前面的文件。比如实现到一半发现设计有问题,回去改design.md和tasks.md就行,没有什么阶段门禁。
(3)openspec/project.md是项目知识库。放项目背景、业务术语、技术栈说明之类的东西。AI 在做提案的时候可能会读这个文件来理解上下文。
(4)openspec/config.yaml是项目级配置。大多数情况下不用动它,除非你想自定义一些行为。
差异规范(Delta Specs)的格式
这是 OpenSpec 里一个比较有意思的设计。变更提案里的规范不是写"完整的规范是什么样",而是写"跟现有规范相比,变了什么"。格式长这样:
# Delta for Auth ## ADDED Requirements ### Requirement: 两步验证 系统必须在用户登录时要求输入第二因子。 #### Scenario: 需要 OTP - GIVEN 用户开启了两步验证 - WHEN 用户输入正确的账号密码 - THEN 展示 OTP 输入界面 ## MODIFIED Requirements ### Requirement: 会话超时 系统将在 30 分钟无活动后会话过期。 (原来是 60 分钟) #### Scenario: 空闲超时 - GIVEN 已认证的会话 - WHEN 30 分钟无活动 - THEN 会话失效 ## REMOVED Requirements ### Requirement: 记住我 (已被两步验证替代,废弃)当你归档一个变更的时候,ADDED 的内容会追加到主规范里,MODIFIED 的内容会替换掉主规范里的旧版本,REMOVED 的内容会从主规范里删掉。这个合并过程是自动的。
归档之后
变更做完、归档之后,文件夹会被挪到openspec/changes/archive/下面,文件名会加个日期前缀:
openspec/changes/archive/2025-01-24-add-dark-mode/同时差异规范已经合并进了openspec/specs/,变成了你系统行为的正式记录。下次有人看代码想知道"暗色模式到底怎么设计的",直接翻 spec 就行。
OpenSpec 命令
OpenSpec 有两套命令,跑在不同的地方,这个区分很重要,新手最容易搞混。
终端命令(CLI)
这些命令在你的终端里执行,就是普通的命令行工具:
openspec init — 在项目里初始化 OpenSpec,创建目录结构,安装斜杠命令。前面讲过了。
openspec update — 刷新项目里生成的斜杠命令文件。升级 OpenSpec 版本之后要在每个项目里跑一次。
openspec list — 列出当前所有活跃的变更提案。就是看changes/目录下有哪些还没归档的。
openspec list --specs — 列出所有已有的规范。看specs/目录下有哪些领域的 spec。
openspec show — 查看某个变更的详细信息。比如openspec show add-dark-mode。
openspec validate — 校验某个变更的规范格式是否正确。实现之前跑一下,省得格式有问题导致归档失败。
openspec view — 打开一个交互式的终端仪表盘,可以浏览你的规范和变更。纯查看用的,不能在里面操作。
斜杠命令(与 AI 的聊天窗口用)
这些命令不在终端里跑,而是在你的 AI 助手的聊天输入框里输入。就像你跟 AI 说"帮我写个登录页"一样,只不过用斜杠命令更结构化。
默认的 core 配置包含这些,我们会使用主要的4个命令就行:
/opsx:explore— 在你还不确定要做什么的时候用。它是一个"思考伙伴",会读你的代码库、分析现有架构、跟你讨论方案,但不会创建任何文件或写任何代码。聊完觉得方向对了,再用 propose。
这个命令特别适合两种场景:一是你有个模糊的想法但不知道怎么落地,比如"我想加个暗色模式但不确定该用 CSS 变量还是 Tailwind 的主题方案";二是你接手了一个不熟悉的项目,想先搞清楚某个功能现在是怎么实现的。
/opsx:sync— 把变更里的规范差异合并到主规范库。通常在归档时自动执行,但如果你想提前合并(比如先让别的变更参考新的规范),可以手动调。
/opsx:propose— 创建一个新的变更提案。AI 会读你现有的规范和代码,然后一口气生成 proposal.md、specs/、design.md、tasks.md 四个文件。生成完之后你去看一遍,不满意的地方直接让 AI 改。
举例:
/opsx:propose add-dark-modeAI 就会创建openspec/changes/add-dark-mode/并填充所有文件。
/opsx:apply— 让 AI 按照 tasks.md 里的清单开始实现。它会一个个任务做过去,做完一个打个勾。如果实现过程中发现设计有问题,你可以暂停,让它回去改 design.md 和 tasks.md,再继续。
/opsx:archive— 归档一个已完成的变更。它会做三件事:把差异规范合并进openspec/specs/,把变更文件夹挪到openspec/changes/archive/,然后在前面加个日期。
下面扩展配置额外包含的命令,了解即可,很少使用:
/opsx:new — 只创建变更文件夹和空的 proposal.md,不自动生成其他文件。适合你想一步步手动填充的情况。
/opsx:continue — 增量生成下一个 artifact。比如你先用 /opsx:new 创建了提案,再 /opsx:continue 让它生成 specs,再 /opsx:continue 生成 design,一步步来。跟 /opsx:propose 一口气全生成的区别是,每一步你都有机会审查和修正。
/opsx:ff — fast-forward,跟 /opsx:continue 类似但会一次性生成剩余所有 artifact。适合你用 /opsx:new 创建了空变更,手动写了 proposal,然后想让 AI 把剩下的都补上。
/opsx:verify — 让 AI 检查实现是否符合规范。它会对比 tasks.md 和实际代码,看有没有漏掉的任务或者偏离规范的地方。
/opsx:bulk-archive — 批量归档。你有好几个做完的变更想一次性归档时用。
/opsx:onboard — 新手教程命令。它会在你的真实项目上走一遍完整的 OpenSpec 流程,边做边解释每一步在干什么。第一次用 OpenSpec 的话推荐跑一次。
不同 AI 工具的斜杠命令写法
不同的 AI 工具,斜杠命令的分隔符可能不一样:
| 工具 | 写法 |
|---|---|
| Claude Code | /opsx:propose |
| Cursor | /opsx-propose |
| Windsurf | /opsx-propose |
| GitHub Copilot | /opsx-propose |
| Trae | /opsx-propose |
| Codex | /opsx:propose |
| Gemini CLI | skill 风格调用 |
大多数工具用冒号(:)或横线(-)分隔。记不住也没关系,在 AI 助手的聊天框里输入一个/,看自动补全的提示就行了。
使用示例
用一个实际的例子走一遍完整流程。假设你有一个 Web 应用,想给它加个暗色模式。
第一步:想想清楚(可选但推荐)
你:/opsx:explore 我想加暗色模式,但不知道怎么处理主题切换最干净 AI:让我看看你的样式方案…… 你现在用的是 CSS Modules,没有设计系统。最干净的路子是 CSS 变量 + 一个轻量的 ThemeContext,再加上系统偏好检测。 不需要引入新依赖。要不要做个提案? 你:好,开始吧。第二步:创建提案
你:/opsx:propose add-dark-mode AI:已创建 openspec/changes/add-dark-mode/ ✓ proposal.md ✓ specs/ ✓ design.md ✓ tasks.md这时候你去翻这几个文件看看。proposal.md 里大概是这样的内容:
# Proposal: Add Dark Mode ## Intent 用户要求暗色模式以减少夜间使用的眼睛疲劳。 ## Scope - 在设置页添加主题切换 - 支持系统偏好检测 - 用 localStorage 持久化偏好 ## Approach 使用 CSS 自定义属性做主题,React Context 管理状态。tasks.md 可能是这样的:
# Tasks ## 1. 主题基础设施 - [ ] 1.1 创建 ThemeContext,管理 light/dark 状态 - [ ] 1.2 添加 CSS 自定义属性 - [ ] 1.3 实现 localStorage 持久化 ## 2. UI 组件 - [ ] 2.1 创建 ThemeToggle 组件 - [ ] 2.2 在设置页添加切换入口 - [ ] 2.3 在 Header 里加快捷切换 ## 3. 样式适配 - [ ] 3.1 定义暗色主题色板 - [ ] 3.2 把所有组件改成使用 CSS 变量觉得方案没问题,就继续。觉得不对,直接告诉 AI 哪里要改,它改完你再确认。
第三步:让 AI 动手
你:/opsx:apply AI:开始实现…… ✓ 1.1 创建了 ThemeContext ✓ 1.2 添加了 CSS 自定义属性 ✓ 1.3 实现了 localStorage 持久化 ✓ 2.1 创建了 ThemeToggle 组件 …… 所有任务完成!第四步:归档
你:/opsx:archive AI:归档 add-dark-mode…… ✓ 规范已合并到 openspec/specs/ui/spec.md ✓ 变更已移至 openspec/changes/archive/2025-01-24-add-dark-mode/ 完成!到这一步,openspec/specs/ui/spec.md里就多了一条关于主题切换的规范。下次有人(或 AI)要改 UI 相关的东西,读这个 spec 就知道暗色模式的设计意图和行为约定。
一个完整的终端操作序列
把上面所有步骤压缩一下:
# 终端里做的(只需要做一次)npminstall-g@fission-ai/openspec@latestcdyour-project openspec init# 以下全在 AI 聊天窗口里做/opsx:explore# 先聊聊想做什么/opsx:propose add-dark-mode# 创建提案/opsx:apply# 实现/opsx:archive# 归档# 想在终端里检查状态openspec list# 看活跃变更openspec show add-dark-mode# 看某个变更详情openspec validate add-dark-mode# 校验规范格式openspec view# 打开仪表盘什么场景需要OpenSpec
不是所有改动都要走 OpenSpec 流程。改个拼写错误、修个 CSS 间距这种,直接让 AI 改就行,用 OpenSpec 反而是多此一举。
适合走提案的场景:新功能、API 变更、数据库 schema 变更、架构调整、重大重构。这些事情的共同特点是:如果方向错了,返工成本很高。
不需要提案的场景:bug 修复(恢复原有行为)、文案修改、注释修改、非破坏性的依赖升级。这些事情做错了,git revert 一下就行。
**总结:**本章学习了OpenSpec,了解了他能做什么,好处是什么,还学习了他的文件结构、一些命令,最后用一个示例看到完整的开发流程。
