OpenSpec(SDD规范驱动开发)——给 AI Coding 的一份开发规约

📅 2026/7/18 4:40:29 👁️ 阅读次数 📝 编程学习
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@latest

pnpm 用户:

pnpmadd-g@fission-ai/openspec@latest

yarn 用户:

yarnglobaladd@fission-ai/openspec@latest

安装完之后跑一下openspec --version,能输出版本号就说明装好了。

项目初始化

进入你的项目目录,执行:

cdyour-project openspec init

它会问你用的是什么 AI 工具。选你正在用的那个就行。这一步做的事情是:

  1. 在项目根目录下创建openspec/目录
  2. 根据你选的 AI 工具,往对应的位置写入斜杠命令文件(比如 Claude Code 会写到.claude/commands/.claude/skills/,Cursor 会写到.cursor/commands/
  3. 创建openspec/config.yaml配置文件(可选)
  4. 创建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.mdtasks.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-mode

AI 就会创建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 CLIskill 风格调用

大多数工具用冒号(:)或横线(-)分隔。记不住也没关系,在 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,了解了他能做什么,好处是什么,还学习了他的文件结构、一些命令,最后用一个示例看到完整的开发流程。