🟡 进阶

OpenSpec 到底怎么用

它不是替你写代码的工具,而是你和 AI 开工前签字的那张图纸:先谈妥"要做什么",再让 AI 动手。

📅 更新于 2026-09-13

本文校对于 OpenSpec @ v1.13.0 · 官方源:github.com/Fission-AI/OpenSpec

1.13.0
本文校对版本(2026-09-09 发布)
6.8 万+
GitHub Stars
177 万
npm 上月下载量
30+
支持的 AI 助手

0030 秒速览:三条结论 + 按处境挑入口

读完这篇你能做到一件事:在自己的项目里跑通一次「想法 → 图纸 → 施工 → 归档」的完整闭环,并且知道什么时候不该用它。

📎 这篇和《OpenSpec 的一次变更到底怎么运转》怎么分工

这一篇是上手篇:两个半场(终端 vs 对话框)、三条主命令、四件工件是什么,以及跑通一次闭环的最短路径。如果你要问的是"磁盘上到底发生了什么、为什么会出现 blocked、那四类静默失效怎么防",看 《OpenSpec 的一次变更到底怎么运转》。两篇不重复:这篇讲怎么开始用,那篇讲它怎么运转。

先记住这三句

① 它是"先谈妥再动手":把"要做什么"写成仓库里的 Markdown 文件,AI 照着文件施工——而不是靠聊天记录里的口头约定。

② 它分两个半场:装东西的 openspec 命令敲在终端里,干活用的 /opsx:propose 这类命令敲在 AI 助手的聊天框里。搞混这两个地方是新手第一号卡点。

③ 它不是流程审批:没有任何"阶段门"锁住你,规格随时可以改;归档那一刻,改动才会被写进"系统现状说明书"。

你现在的处境,对应该看哪一节

你现在的状态直接看为什么
完全没听说过它,想知道值不值得学01 它是什么 → 02 它解决什么问题先判断"我的痛点是不是它治的那个"
已经决定要用,想今天就跑起来03 怎么装 → 04 最小例子两条终端命令加三句聊天指令就闭环
敲了 /opsx:propose 但没反应05 两个半场 → 16 排错九成是敲错了地方(终端 vs 聊天框)
图纸生成了,但不知道看哪儿14 审图清单审图只盯三处,十分钟够了
做到一半,产品改需求了11 改图还是重开两条路的判据官方给了明确边界
想让 AI 每次都知道我们的技术栈12 项目配置一份 config.yaml 顶十句重复提醒
老项目想接入,但不想先补全文档09 场景二它就是为存量项目设计的,按改动增量长出来
只想查一条命令一页纸速查表按"我要…"索引,不用重读全文

最小可用的一条路(照抄就能跑)

# 第一步:在你的终端里(iTerm / VS Code 终端 / PowerShell 都行)
npm install -g @fission-ai/openspec@latest   # 装 CLI,需要 Node.js 20.19.0 或更高
cd your-project
openspec init                              # 交互式选你的 AI 工具,生成对应的指令文件

# 第二步:切到你的 AI 助手聊天框里(Claude Code / Cursor / Codex …)
/opsx:propose add-dark-mode                # AI 起草图纸,你审
/opsx:apply                                # 照图施工,逐项打勾
/opsx:archive                              # 归档,delta 合进主规格

两条终端命令负责装,三句聊天指令负责干活——整篇就是把这三句背后的东西拆开讲清楚。

01OpenSpec 是什么:先破掉四个最像的错想

错想一:它会替你写代码?

不会,而且这是它刻意不做的部分。真正写代码的仍然是你的 AI 编程助手(Claude Code、Cursor、Codex、GitHub Copilot 这些)。OpenSpec 管的是写代码之前和之后的两件事:动手前把"要做什么、怎么做、分几步"落成文件;动手后验收、把改动合并进"系统现状说明书"、归档留痕。

官方仓库给自己的一句话定位是"一个 AI 原生的、面向规格驱动开发的系统"(an AI-native system for spec-driven development)。规格驱动开发(Spec-Driven Development,简称 SDD)里的"规格",指的就是这种用自然语言写死的"系统应该表现出什么行为"的说明文件——后面每次出现都按这个意思理解。

换句话说:你的 AI 助手是施工队,OpenSpec 是那张签了字的施工图,加一套把图纸归档的流程。变的是它现在照着图施工,而不是听你临场口述。

错想二:它是一套很重的规格文档体系,得先把规格写全?

不是。它官方明说自己的原则里有一条叫 "built for brownfield not just greenfield"——为存量项目(已经有代码、跑了一段时间的项目,行话叫 brownfield)而生,不只服务从零开始的新项目。落地方式很克制:你不必先把整个系统的规格补全,只为你这一次改动涉及的那部分写规格;主规格随着一次次归档慢慢长出来。

官方 FAQ 里有一句很直白的回答:存量代码库才是主场景("Existing codebases are the main event")。所以"接入前得先重构/先补文档"这个担心是反过来的。

错想三:它就是让 AI 写 PRD(产品需求文档)?

不是一类东西,差别有三处,而且每一处都直接影响你会不会用错:

差别聊天框里写 PRDOpenSpec 的做法
落在哪留在对话里,关掉窗口就散落在仓库的 Markdown 文件里,换模型、换工具、换人都还在
有没有结构想到哪写到哪四种工件各管一件事,依赖方向固定
能不能被"执行"不能,只能被人读tasks.md 的复选框会被 /opsx:apply 逐项执行和打勾

第三条最关键:tasks.md 里是带复选框的清单,AI 施工时会一项项勾掉——你第二天回来能看见"做到第几步了"。

错想四:它跟 TDD(测试驱动开发)是一回事?

不是,但它们不冲突。测试驱动是"先写测试、再写代码",关注的是代码层面的正确性。规格驱动是"先把要做什么写清楚、再写代码",关注的是你和 AI 对目标的理解是否一致。规格里可以包含验收场景(场景就是一段"给定…当…则…"的具体例子),测试只是验证手段之一。

它真正对立的做法是"氛围编程"(Vibe Coding):想到哪说到哪、让 AI 自由发挥。OpenSpec 的定位是给氛围编程补上图纸和归档,而不是给它加一套官僚流程。这一点从它的五条设计原则里能直接看出来(见本节末尾)。

那它到底是什么:一句话 + 一个类比

📖 正向定义

OpenSpec 是装在你项目里的一个小程序(一条命令就能装),它把"一次改动"打包成一个文件夹:为什么要改、改成什么行为、技术方案、施工清单,全在里面;改完之后一条命令归档,把"改成什么行为"那部分合并进一份长期维护的"系统现状说明书"。

用装修打个比方:openspec/specs/ 是这套房子现在的样子(哪面是承重墙、水电怎么走);openspec/changes/ 里的一个文件夹是这一次要动的那面墙的施工图袋;归档就是"改完了,把竣工图并回房子现状图"。

这个类比到哪儿就不准了:真实装修改完就结束了,而软件永远在变——归档之后那份"现状说明书"马上又会被下一次改动盯上。所以别把它当"一次性项目文档",它是持续被重写的活文档。另外,这里的图纸还要给 AI 看,所以它得写到 AI 能照着做的具体程度。

它的五条设计原则(官方 README 原话)

官方 README 把价值观写成五句短句,理解这五句就理解了它为什么长这样:

原文翻译过来是对你的实际影响
fluid not rigid流动的,不是僵硬的没有强制的阶段门,任何工件随时能改
iterative not waterfall迭代的,不是瀑布式的边做边修规格,不必一次定死
easy not complex简单,不复杂纯 Markdown,不用学 UML 那类重型建模
built for brownfield not just greenfield为存量项目而生,不只服务新项目老项目可以渐进接入,不必推倒重来
scalable from personal projects to enterprises从个人项目到企业都适用单人单仓库和跨仓库团队都有对应做法

02它到底解决什么问题:三个真实失效模式

直接用 AI 写代码,最大的痛点通常不是"代码写得烂"(那看得见、能改),而是决策过程丢了——需求只活在聊天记录里,过一会儿你就想不起当初为什么这么设计。

失效模式一:需求只活在聊天里,AI 会"失忆"

聊天窗口一关、上下文一清,AI 就不知道你们上次谈到哪了。下次改代码,你得把背景重新讲一遍——而且讲的可能和上次不完全一样。更糟的是你自己也会忘:三周后打开 git 历史,满屏 Add feature、Fix bug,没人知道当初为什么这样设计。

OpenSpec 的处理方式很朴素:把这些意图写进仓库里的文件。文件比聊天记录耐用得多——它进 git、能被评审、换模型换工具都不丢,而且 AI 每次都能从文件里读到完整上下文。

💡 一个具体的收益场景

官方 FAQ 里点得很准:当你的会话上下文用完了、或者需求中途变了,规格文件就是救命的东西。你可以清空上下文、开一个全新的 AI 会话,直接跑 /opsx:apply——它会读那些文件,从第一个没勾的任务接着做。这是聊天记录做不到的。

失效模式二:AI 自由发挥,范围悄悄蔓延

你让它加个深色模式,它顺手把你的主题系统重构了。这不是它坏,而是它有主动性:只要有机会它认为"顺手",它就会做。问题在于这些顺手做的东西没经过你同意,也没被记下来。

对抗办法不是把话讲得更狠,而是把边界写进文件:proposal 里有明确的范围段(改什么、不改什么),AI 施工时以文件为准。你审图时最重要的动作之一就是盯住这个"不改什么"。

失效模式三:团队(包括 AI)没有共同语言

产品、后端、前端各说各话,而且现在多了一个成员:AI。一个 change 文件夹恰好是一份产品、工程师、AI 都能读的计划书——它跟代码走同一套协作流程(git 提交、PR 评审),而不是活在某个人的聊天窗口里。

反过来:什么时候别用它

官方 FAQ 的回答是"不,不必什么都用它"——一次改一个错别字,走完整套流程不划算。

你的场景要不要用理由
一次性脚本、做着玩的 demo、当天扔掉的试验不建议没有"要维护两周以上"的时间跨度,图纸的成本收不回来
改一个错别字、一行样式不建议官方原话:这种仪式的代价不值得
要维护超过两周的功能、要协作的代码建议正是它设计的甜蜜点
AI 容易"想多了"的中大型改动强烈建议范围边界写进文件,比口头叮嘱有效
多人协作、跨仓库的需求建议(可能要 Stores)change 文件夹 + PR 评审=共同语言,见 13 节

03怎么装、怎么升级,以及命令该敲在哪儿

装之前先确认这三件事

前置条件具体要求怎么确认
Node.js20.19.0 或更高(硬性要求,低版本装不上)终端里跑 node --version
一个 AI 编程助手Claude Code、Cursor、Codex、GitHub Copilot、Gemini CLI 等 30+ 工具你平时用哪个就用哪个
git 仓库强烈建议:图纸评审走 PR,归档留下历史git status 能跑通就行
⚠️ 如果你的 Node 版本低

报错原文是 Requires Node.js 20.19.0 or higher。先跑 node --version 确认版本,别在报错堆里找半小时。另外:即使用 bun 装它,它运行时仍然需要 Node,所以 PATH 里必须有 20.19.0+ 的 node。

第一步:装 CLI(终端)

npm install -g @fission-ai/openspec@latest
# 也支持 pnpm / yarn / bun / nix,分别是:
#   pnpm add -g @fission-ai/openspec@latest
#   yarn global add @fission-ai/openspec@latest
#   bun add -g @fission-ai/openspec@latest
# 装完确认:
openspec --version

第二步:在项目里初始化(终端)

cd your-project
openspec init

# 不想交互式回答问题?可以非交互地指定 AI 工具:
openspec init --tools claude,cursor
openspec init --tools all      # 给所有支持的工具都生成
openspec init --tools none     # 先不生成工具文件
openspec init ./my-project     # 初始化到指定目录

openspec init 会问你用哪个 AI 助手,再按选择生成对应的指令文件(比如 Claude Code 下是 .claude/skills/ 里的 openspec-* 目录)。它是交互式的;在 CI 或非交互环境里跑会因为没有终端可提问而停下——这时用 --tools 明确指定。

💡 懒人路线:让 AI 替你装

官方文档里有一份 setup prompt(安装用提示词),整段粘给 AI 助手,它会替你装 CLI、跑 openspec init、再验证结果,并报告创建了什么。位置:docs/installation.md#install-with-your-ai-assistant。第一次装建议走这条。它遇到 PATH 问题时只会把该改的路径告诉你,不会去改你的 shell 启动文件——这点是官方刻意设计的。

升级:两条命令,顺序不能反

升级要分两步,因为指令文件是由"已装好的那个 CLI"生成的:如果你先跑 openspec update 而没升级包,它会告诉你"一切都是最新的",实际上新版才有的命令根本没生成。

# 1) 先在终端升级包本身
npm install -g @fission-ai/openspec@latest

# 2) 再到每个项目里刷新 AI 指令文件(每个项目各跑一次)
cd your-project
openspec update

好消息是 openspec update 现在会主动问你:它会去 npm 问一句有没有更新的版本,如果发现你落后了,会打印类似这样的提示并提议帮你升级:

# openspec update 可能打印的内容(官方文档示例)
A newer OpenSpec CLI is available (v1.6.0 → v1.7.0).
  Running from: /usr/local/lib/node_modules/@fission-ai/openspec
? Upgrade to v1.7.0 now? (Y/n)

这里有个细节能解释"我明明升级了为什么没生效":它会去问"当前这个二进制是从哪个目录加载的",而不是信赖 npm 的退出码。PATH 上还有更靠前的旧安装时,它会告诉你,而不是假装成功——那行 Running from: 就是给你排查用的。

还有一处细节决定"它认为你已是最新"是否可信:skill 文件里记着"是哪个版本生成的",所以只要版本号一致,它就不动——哪怕你手改过。而命令文件没有版本戳,靠内容比对,你怎么改都会被判定为漂移并覆盖掉。想强制重写就加 --force。

命令敲在哪里:这是新手第一号卡点

OpenSpec 同时有两套命令,它们运行在两个完全不同的地方。搞混这一个事实,后面所有东西都会显得莫名其妙。

类型长什么样敲在哪干什么
CLI 命令openspec init、openspec list、openspec status终端(iTerm、VS Code 终端、PowerShell——你跑 git、npm 的那个地方)装、查、校验、归档;它是"引擎"
斜杠命令/opsx:propose、/opsx:apply、/opsx:archiveAI 助手的聊天框(就是你平时让它写代码的那个框)驱动 AI 走工作流;它是"方向盘"

两者的关系是单向的:你在终端跑一次 openspec init,它把斜杠命令"装进"你的 AI 工具;之后日常干活基本都在聊天框里。

🚫 最常见的误操作

在终端里输入 /opsx:propose,然后什么都没发生。终端不认识斜杠命令——斜杠命令是给 AI 助手看的,不是给 shell 看的。反过来,在聊天框里输入 openspec init 也没用(AI 可能好心替你去跑,但那是另一回事)。

命令的拼写因工具而异,以 init 的输出为准

标准写法是 /opsx:propose,但不同工具注册命令的方式不同,拼写会变。这跟对错无关,纯粹是各工具加载文件的方式不同。官方给的口径是:一排命令文件叫 opsx-propose.md 的,你敲 /opsx-propose;放在 commands/opsx/ 目录下的,你敲 /opsx:propose。

工具该敲什么补充说明
Claude Code 等多数工具/opsx:propose官方文档里的标准写法
Cursor、GitHub Copilot/opsx-propose用连字符
Amazon Q@opsx-propose它把命令装进提示词库,不是斜杠菜单
Codex$openspec-proposeCodex 这类工具根本不生成 opsx-* 命令文件,走 skill 调用
Kimi Code/skill:openspec-propose同样是 skill 式调用
共享的 .agents 目标/openspec-propose官方特意说明:这是通用形式,不保证每个助手都认——不认就查它自己的文档

好消息:openspec init 结束时会把你选中的那几个工具的正确写法打印出来。以它为准,比背上面这张表可靠。

安装相关的三条实务细节

04最小例子:一句"我想要深色模式"到代码落地

这是官方 README 里的经典走查,也是你能亲手跑完的最短闭环。全程四步,人只在两个地方把关:审图、验证结果。中间写代码的脏活是 AI 的。

第 1 步:想法模糊?先聊透(不写任何文件)

You: /opsx:explore
AI:  What would you like to explore?
You: I want dark mode but I'm not sure how to do it cleanly.
AI:  Let me look at your styling setup...
     Cleanest path here: CSS variables + a small theme context,
     with system-preference detection. No new dependencies. Scope it?
You: Yes, let's do it.

注意这一步不创建任何文件、不写一行代码:它只是把"我模糊地想要深色模式"变成"用 CSS 变量加一个小的主题上下文、探测系统偏好、不加新依赖"这样具体到能开工的方案。你可以探索三条死路、从每条里学到东西,然后只立项活下来的那条。

第 2 步:一句话生成全套图纸

You: /opsx:propose add-dark-mode
AI:  Created openspec/changes/add-dark-mode/
     ✓ proposal.md — why we're doing this, what's changing
     ✓ specs/       — requirements and scenarios
     ✓ design.md    — technical approach
     ✓ tasks.md     — implementation checklist
     Ready for implementation!

到这里,你已经有了一个装好四件东西的文件夹。你应该停下来读它。这是 OpenSpec 存在的意义所在:在它还只是一段话的时候发现理解偏了,而不是在写了 400 行代码之后。

第 3 步:照图施工

You: /opsx:apply
AI:  Implementing tasks...
     ✓ 1.1 Add theme context provider
     ✓ 1.2 Create toggle component
     ✓ 2.1 Add CSS variables
     ✓ 2.2 Wire up localStorage
     All tasks complete!

施工中如果发现图纸不对(比如设计里说存 localStorage,你其实想用 cookie),直接改图纸再继续即可,不必推倒重来——展开见 11 节。

第 4 步:验收归档,主规格同步更新

You: /opsx:archive
AI:  Archived to openspec/changes/archive/2025-01-23-add-dark-mode/
     Specs updated. Ready for the next feature.

归档做了三件事:把这次改动的规格(delta)合并进主规格、把 change 文件夹搬到归档目录并加上日期前缀、之后它就不再出现在"进行中的改动"列表里。

生成出来的目录长什么样

openspec/
├── specs/                        # 主规格(source of truth):系统"现在"是什么样
│   └── ui/
│       └── spec.md               # 按能力/领域一个目录一份,比如 ui、auth、payments
├── changes/
│   ├── add-dark-mode/            # 本次改动的"图纸袋"
│   │   ├── proposal.md           # 为什么做、改什么、不改什么
│   │   ├── specs/                # 本次新增/修改的需求(delta)
│   │   │   └── ui/
│   │   │       └── spec.md
│   │   ├── design.md             # 技术方案(简单改动可以不要)
│   │   └── tasks.md              # 带复选框的施工清单
│   └── archive/
│       └── 2025-01-23-add-dark-mode/   # 归档:日期前缀 + 原文件夹名
└── config.yaml                   # 项目配置(可选,init 时会问你要不要建)
💡 节奏记一下

explore(聊透)→ propose(出图)→ 人工审图 → apply(施工)→ archive(归档)。人把关的只有审图和验收两处;每一步之间都没有"必须做"的强制关系,只是这样做最顺。

05两个半场:终端和聊天框各管什么

这个区分值得单独讲,因为理解它之后,"为什么能支持 30+ 个工具"这个问题就自动有答案了。

为什么一个项目要长成两半

因为"规则"和"入口"是两种不同的东西:

好处是工作流只学一次、换工具不用重学;代价是同一条命令的拼写可能不同(见上一节那张表)。

两半的核对清单

做完这件事,说明哪一半没问题命令期望结果
CLI 装好了openspec --version打印版本号(本文校对版本 1.13.0)
项目初始化了openspec init出现 openspec/ 目录,并打印你该敲的斜杠命令写法
斜杠命令装进 AI 了在聊天框输入 /opsx 看自动补全能看到 propose / apply / archive 等候选
两半能对上话/opsx:propose 一个小需求AI 创建 openspec/changes/<name>/

没有"可进入的交互模式"

FAQ 特意回答这个问题,因为问的人太多:OpenSpec 没有"启动交互模式"这一步。你就像平时一样打开 AI 助手、在聊天框敲一个斜杠命令——那个命令就是你"进入 OpenSpec"的方式,AI 认出它、加载对应的 skill、开始按流程走。

唯一真正"交互式"的东西在终端里:openspec view,一个浏览规格和改动的看板。但那是看板,不是干活的地方。

skill 与 command file:它到底往你项目里写了什么

这两个东西都是"为了让 AI 认识工作流"而生成的文件,你不用选——openspec init 按工具决定。

是什么文件长什么样谁在用
skill(较新的跨工具标准).../skills/openspec-*/SKILL.mdClaude Code、Codex、Kimi Code 等
command file(较老的按工具斜杠文件).../commands/opsx-*Cursor、Copilot、Amazon Q 等

有一个容易踩的点:生成的文件归 OpenSpec 所有,别在里面写你自己的指令——下次 openspec update 可能把它们覆盖掉。你自己的项目规矩应该写在 openspec/config.yaml 的 context 里(见 12 节)。

06四种工件:图纸袋里装了什么

每个 change 文件夹里有四种工件(artifact,指一套流程里产出的单份文档)。记住它们的顺序和依赖方向,你就理解了这套流程的骨架。

proposal.md
为什么做
→
specs/
做什么
→
design.md
怎么做
→
tasks.md
分几步做

四件工件各管一件事

工件回答什么问题关键内容谁会被它约束
proposal.md为什么做这次改动?值不值得做?动机、改什么、不改什么(范围边界)、影响面你(审图时第一个看的就是它)
specs/(delta)改成什么行为?用 SHALL 写的需求 + WHEN/THEN 场景AI(这是它的施工合同)
design.md用什么方式做?技术选型、架构决策、取舍与风险、迁移/回滚写代码的 AI 会话
tasks.md分几步、先做哪步?带复选框的清单,每项写明怎么算完成/opsx:apply(唯一会被"执行"的工件)

依赖方向是"菱形",不是一条直线

初学者容易以为这是流水线:写完 proposal 写 specs,写完 specs 写 design。看官方 status 的输出就知道不是——proposal 一写完,specs 和 design 同时变成"可写"状态,两者都完成后 tasks 才解锁。

# openspec status --change add-dark-mode 的输出(官方文档示例)
Change: add-dark-mode
Schema: spec-driven
Progress: 2/4 artifacts complete

[x] proposal
[x] specs
[ ] design
[-] tasks (blocked by: design)

所以真实形状是这样的:

proposal ──┬──► specs ──┐
           │            ├──► tasks ──► implement
           └──► design ─┘
   ▲             ▲            ▲              │
   └─────────────┴────────────┴──────────────┘
            边做边学,随时回头改
📖 "使能,不是闸门"

官方用一句话解释这个依赖关系:它是 enablers, not gates——只说明"下一步什么变得可能",不说明"你必须下一步做这个"。施工到一半发现设计错了?改 design.md 继续。范围该缩?改 proposal。依赖存在的唯一理由是"AI 需要上下文"——没有 specs 就写不出靠谱的 tasks。

design.md 是可以不要的

这一点新手常常不知道,于是每个小改动都被要求写一份技术方案文档。官方的口径是:只有符合下列任一条时才需要 design.md——跨服务/跨模块的改动或引入新架构模式;新增外部依赖或数据模型有重大变化;涉及安全、性能、迁移的复杂度;有需要先定下来的技术分歧。一个改按钮颜色的需求不需要 design.md。

07delta spec:为什么只写"改了什么",而不是重写整份规格

这是整套设计里最关键的一个机制,也是"为什么它改老系统特别好用"的答案。

主规格与 delta 的分工

主规格 openspec/specs/delta changes/<name>/specs/
描述的是系统现在的真实行为这次要改什么(相对现状的差异)
覆盖面整个系统的相关能力只覆盖这次动到的需求
什么时候写归档时被自动合并、逐步长出来立项时由 AI 起草、你审
谁来读想了解"这系统到底怎么跑"的人(和新会话里的 AI)审图的人、施工的 AI
写长的后果越全越有用越全越坏——评审者要通读整个系统,而不是看差异

官方的定位是一句很准的话:你描述的是"差异"(diff),不是"终点"(destination)。这就是它能优雅地改老系统的原因。

delta 用四个标题说明改动的种类

标记含义归档时发生什么最容易犯的错
## ADDED Requirements全新的行为,以前没有追加进主规格把老行为的变化写成 ADDED,结果主规格里出现两条打架的需求
## MODIFIED Requirements已有行为发生变化整块替换主规格里的旧版本只写改动部分——替换是整块替换,漏掉的场景就丢了(见本节末尾)
## REMOVED Requirements行为被删掉从主规格里删除只写"删了",没写为什么删、怎么迁移
## RENAMED Requirements只是改名,行为没变主规格里对应改名把改名写成 REMOVED + ADDED,历史变得难读

一份真实的 delta 长什么样

规格就是普通 Markdown,没有新语法要学。核心约定只有两条:需求用 SHALL/MUST 写,场景用 GIVEN / WHEN / THEN 写。下面这份是新建能力时的完整形态(注意它开头有 ## Purpose):

## Purpose

Lets users take their data out of the product in a portable format.

## ADDED Requirements

### Requirement: User can export data
The system SHALL allow users to export their data in CSV format.

#### Scenario: Successful export
- **WHEN** user clicks "Export" button
- **THEN** system downloads a CSV file with all user data
🚫 三个静默失效点(官方文档明确点名)

① 场景标题必须恰好四个井号(#### Scenario: …)。用三个井号、或写成普通的列表项,会静默失败——不报错,但场景不被识别。

② 每条需求至少要有一个场景,否则校验会拦。

③ 新建能力时要写 ## Purpose(一两句话说明这个能力是干什么的)。不写的话,主规格里会留下一个 TBD 占位符要你手动补。反过来说,给已存在的能力写 delta 时不要加 ## Purpose——那个能力的主规格里已经有了,delta 里的会被忽略;要改已有的 Purpose,直接去编辑 openspec/specs/<能力路径>/spec.md。

MODIFIED 是整块替换:这是最容易吃亏的地方

官方排错文档专门给这个错误留了一段。它的表现形式是这样的:

# openspec validate 会报的错(官方示例)
MODIFIED "<requirement>" omits scenario(s) the current spec still has: "<scenario>"

意思是:你写 MODIFIED 时,必须把"原本就有、且这次仍然保留"的所有场景一并带上,不能只写你改的那一个。因为归档时它整块替换旧版本,你漏掉的场景会一起消失。官方给的修法是:回 openspec/specs/<能力路径>/spec.md 把那些场景原样拷进 delta。

还有一个常见误用:如果只是"新增一块关注点"而没有改动原有行为,要用 ADDED,不要用 MODIFIED。官方管这个叫 common pitfall。

需求该写多细:一条可执行的判据

官方 writing-specs 文档给的判据是一句话:"一个没看过代码的测试者,能不能判断它过没过?"答不能,就需要改。

❌ 含糊的 spec(AI 只能猜)
### Requirement: Dark mode
The app SHOULD support dark mode somehow.

"somehow"把设计权整个扔给了 AI,"SHOULD"又留了模糊余地。它猜错了,你还得返工。

✅ 精确的 spec(AI 照做)
### Requirement: Theme selection
The app SHALL let users switch between
light and dark themes, defaulting to
the system preference.

#### Scenario: User toggles dark mode
- **WHEN** the user clicks the theme toggle
- **THEN** the app switches to dark mode
  and persists the choice

SHALL + 具体场景 = 一份可验收的合同。

SHALL / MUST / SHOULD / MAY 的分量不一样

这四个词来自一份互联网标准文档(RFC 2119),OpenSpec 沿用了它们的分量约定。新手默认应该用 SHALL/MUST;只有当你真的想说"除非有正当理由,否则不建议"时才用 SHOULD。

关键词分量什么时候用
MUST / SHALL硬性要求,没有商量余地默认选择
SHOULD强烈建议,允许有正当理由的例外你确实想留口子的时候
MAY真的可选可选功能

为什么 spec 里不该出现技术选型

官方给了一条很好用的自查:"如果实现的换法变了、但对外的行为没变,那这件事就不属于 spec。"队列、库、表结构属于 design.md 或代码;混进需求里,需求就既不可验收、又会随代码过时。

08磁盘上到底留下什么:怎么查、怎么验

这一节讲怎么用终端命令亲眼确认它。命令都可以直接复制去跑。

四个常用查看命令

# 1) 看当前有哪些进行中的 change
openspec list

# 2) 看主规格清单(注意:不加 --specs 列的是 change,不是规格)
openspec list --specs

# 3) 看某个 change 的工件进度(哪件做完了、哪件被卡住)
openspec status --change add-dark-mode

# 4) 看某个条目的详细内容;名字有歧义时用 --type 指明是 change 还是 spec
openspec show add-dark-mode
openspec show auth --type spec

# 附带一个交互式看板(终端里的浏览器):
openspec view
⚠️ 一个官方专门提醒的坑

openspec list 列出的是进行中的 change,不是项目已有的规格。想看"这个项目现在覆盖了哪些能力",要加 --specs。搞混会得出"我的规格是空的"这种错误结论。

校验:在归档之前发现问题

openspec validate 检查结构和一致性,包括"MODIFIED 需求有没有漏掉现存场景"这种跨文件的一致性。它可以进 CI:

openspec validate add-dark-mode        # 校验单个 change
openspec validate --changes            # 校验所有 change
openspec validate --specs              # 校验所有规格
openspec validate --all --strict       # 严格模式 + 全部,适合 CI
openspec validate --all --json         # 给脚本 / agent 用的结构化输出
openspec validate --archived           # 检查已归档的 change 是否还有没勾完的任务

--archived 值得单独说:它不校验规格(归档时已应用过),专门检查 changes/archive/ 下每个 change 的 tasks.md 是否全部勾完,有没勾的就以非零退出码结束——适合放进提交前的钩子,拦住"带着半成品被归档"。

归档在磁盘上做的三步

步骤做什么失败会怎样
1校验这个 change(除非你显式跳过)不通过就不动任何文件
2把 delta 合并进 openspec/specs/:ADDED 追加、MODIFIED 替换、REMOVED 删除中途失败会回滚规格,change 留在原地
3把 change 文件夹搬到 openspec/changes/archive/YYYY-MM-DD-<name>/搬不动时保留已提交的规格状态以便恢复

归档也可以直接在终端跑,不必走聊天框:

openspec archive                          # 交互式:问你要归档哪个、再确认
openspec archive add-dark-mode            # 指定 change
openspec archive add-dark-mode --yes      # 不问,直接归档(agent / CI 用)
openspec archive update-ci-config --skip-specs   # 这次不改规格(纯工具/文档类改动)
🚫 在 CI 或 agent 里跑归档,必须带 --yes

归档会问确认问题。在 AI agent 调用、CI 任务、或任何 stdin 被关掉的环境里没人能回答,于是它会在动手之前停下、以退出码 1 结束,并告诉你该重跑哪条命令。正确做法是提前把 change 名字和 --yes 一起传进去。注意保留你原本要传的其他 flag——--skip-specs 和 --no-validate 会改变归档的行为,只补一个 --yes 不是同一条命令。

两个容易忽略的元数据开关

change 文件夹里还有一个 .openspec.yaml,平时不用碰,但有两个开关只在这里生效:

开关写在哪解决什么问题
skip_specs: true该 change 的 .openspec.yaml纯重构、纯工具、纯文档改动没有行为变化,于是没有 delta。默认校验会因为"零 delta"拒绝它;加这个标记后校验放行,status 里 specs 一项显示为"已跳过"且不计入进度分母
retire_capabilities: true同上,和 schema: 写在一起当一个能力最后一条需求被删掉时,允许归档把它的主规格文件一并删掉。没有这个标记,归档会中止并告诉你去加它

为什么要额外加标记?因为这是归档流程里唯一会删除文件的步骤,必须被明确要求。规则还不止一条:只要那个主规格里除了标题、## Purpose 和需求块之外还有别的东西(比如一段 ## Notes、一条需求下面的注释),归档也会拒绝并指出那几行——你得先把它们挪进 Purpose 或某条需求,或者自己手动删文件。

09三种场景,三条不同路线

同一个工具,在三种处境下该走的路不一样。这一节把差异讲清楚,你可以对号入座。

场景一:需求清楚的新功能

比如"给博客加 RSS 订阅"。需求明确,走最短路径即可:

You: /opsx:propose add-rss-feed
# AI 生成四件套。你重点审两处:
# 1. proposal 里的"不改什么"(别让它顺手重构全站)
# 2. specs 里的 WHEN/THEN 场景(条目排序、转义、分页覆盖了没有)
You: 看起来可以,开工。把分页放到 v2,这次只做全量输出。
# AI 先用 /opsx:update 把范围收窄,再 /opsx:apply 施工,最后 /opsx:archive 归档

官方的 examples 文档给这条路的说法是"三个命令搞定":propose 起草、apply 构建、archive 归档。审图那一步是它专门强调的:"这是 OpenSpec 为之而生的时刻——在错误的理解还只是一段话的时候抓住它,而不是在 400 行代码之后。"

场景二:老项目修 bug(这才是它的主场)

存量项目是它官方定位的主场景。不用重写、不用先补全文档,路线是"先摸清现状,再圈小范围":

1
先 explore 摸清现状,不写任何文件

/opsx:explore 让 AI 去读相关代码,搞清楚根因和有哪几种修法。官方 explore 文档举的例子很典型:你说"结算偶尔会生成重复订单,我不知道为什么、也不知道怎么安全地修",它读完订单服务、支付回调、客户端提交逻辑之后告诉你——重复有两个来源,其中一个会重复扣款,三个修法按健壮性排序。这些结论在 propose 之前就拿到了,而且零成本。

2
propose 只圈小范围

修 bug 的 change 宁小勿大。"修登录超时"不要膨胀成"重写鉴权系统"——后者该是一个独立的 change。判断标准见 11 节。

3
把"正确"写进规格,而不是写"修了个 bug"

官方 examples 给的关键建议:bug 修复和加功能流程完全一样,差别只在 proposal 的写法——描述正确的行为,而不是"修了这个 bug"。这样一个修复会以 MODIFIED 需求的形式落进规格,下一个人(或下一个 AI 会话)看到的不只是"修过",而是"正确是什么意思"。官方还说:一条好的回归场景,就是一段散文形式的回归测试。

场景三:多个改动并行

这得益于"一个 change 一个独立文件夹":做 A 的时候插进来紧急修复 B,两者互不干扰——各有各的文件夹、tasks.md 和归档时机。

You: 我 add-dark-mode 做到一半,现在得先修一个登录 bug。
You: /opsx:propose fix-login-redirect
You: /opsx:apply
You: /opsx:archive
You: 回到深色模式。
You: /opsx:apply add-dark-mode    # 显式点名,因为现在有两个 change
💡 只有一个 change 时可以省掉名字

/opsx:apply 不带参数时,会从上下文推断你要做哪个 change;有多个并行 change 时必须显式点名,否则它不知道该做哪个(报错文本是 Change not found,排错见 16 节)。

三条路线的对照

场景开头用哪条命令图纸重点容易搞砸的地方
需求清楚的新功能/opsx:propose范围边界 + 场景覆盖度proposal 范围写太宽,AI 顺手改别的
老项目修 bug/opsx:explore 先摸清把"正确行为"写成 MODIFIED 需求跳过 explore 直接猜根因,修偏
多改动并行/opsx:propose(新开一个)一个 change 只干一件事把紧急修复塞进正在进行的那一个 change

10全部指令:你在哪一步敲哪一条

先说结论:日常 90% 的时间你只用到三条——propose(出图)、apply(施工)、archive(归档)。其余的都是在这三条周围打辅助。

默认就有的一组(core 档位)

新装默认是 core 档位,装着这六条斜杠命令。它们全部敲在 AI 聊天框里。

命令作用什么时候用会不会动代码
/opsx:explore没有压力的思考伙伴:读代码、比方案、把模糊想法变具体想法模糊,先聊透再立项不会(不创建任何工件,也不写代码)
/opsx:propose创建 change,并一次性生成整套规划工件默认的立项入口(核心三件套之一)不会(只写图纸)
/opsx:apply按 tasks.md 逐项实施并打勾图纸审完、批准开工(核心三件套之一)会
/opsx:update只改规划工件、并保持它们互相自洽需求变了,先改图再让 AI 补施工不会(官方明确:它从不改代码)
/opsx:sync把 delta 合并进主规格,但不归档长跑型 change 想提前合并;多个并行 change 需要基于最新规格不会(只动规格文件)
/opsx:archive校验、合并 delta、把 change 移进归档目录验收通过、收尾(核心三件套之一)不会(改规格、搬文件夹)

需要手动开启的一组(expanded / 自定义档位)

下面这六条默认不装。想要精细控制出图节奏的人才需要它们,开启方式见本节的最后一段。

命令作用什么时候用
/opsx:new只搭一个空的 change 架子(创建文件夹 + .openspec.yaml)想一个工件一个工件地控制
/opsx:continue按依赖顺序创建下一个工件,并显示哪些已就绪、哪些被卡住想每写完一件就审一次
/opsx:ff快进:一次把所有规划工件按依赖顺序全生成情况清楚、想省时间
/opsx:verify从完整性 / 正确性 / 一致性三个维度验收"实现 vs 图纸"归档前想结构化地查一遍
/opsx:bulk-archive一次归档多个 change攒了一堆做完的 change
/opsx:onboard带你走一遍完整流程的引导教程第一次用,想被人手把手带

核心三件套长什么样(逐个拆)

/opsx:propose
立项出图:默认的快捷入口
你主动敲的
一句话创建 change,并生成实施前需要的全部规划工件。对默认的 spec-driven 流程来说就是 proposal、specs、design、tasks 四件。它会停在"可以开工"那一刻,然后告诉你跑 /opsx:apply。
怎么用
/opsx:propose add-dark-mode      # 名字写清楚;也可以直接写一句自然语言的描述
/opsx:explore                    # 想法还模糊时先聊透,再 propose
它实际创建了什么
openspec/changes/add-dark-mode/
├── proposal.md
├── specs/ui/spec.md    # 具体路径取决于这个 change 涉及哪个能力
├── design.md
└── tasks.md
/opsx:apply
照图施工:流式执行任务
你主动敲的
读 tasks.md,找出没勾的项,一项项做:写代码、建文件、跑测试,然后把复选框打上勾。施工中途被打断也能接着做——进度就记在那些复选框里。施工中发现图纸错了,直接改工件继续,不必推倒重来。
怎么用
/opsx:apply                    # 只有一个进行中的 change 时自动推断
/opsx:apply add-dark-mode      # 有多个并行 change 时必须点名
/opsx:archive
验收归档:把改动并把进主规格
你主动敲的
校验 → 合并 delta 进主规格 → 把 change 文件夹搬到带日期的归档目录。它不会因为你还有没勾完的任务就拦住你,只会警告你——因为归档通常意味着活干完了。它还会在需要时提议帮你先 sync(把 delta 合并进主规格)。
怎么用
/opsx:archive
# 终端等价物(agent / CI 里要带 --yes):
openspec archive add-dark-mode --yes

/opsx:update:只改图纸、不碰代码

这条命令值得单独讲,因为它是"规格驱动"和"在聊天里改需求"最大的区别所在。它的行为很具体:

You: /opsx:update add-dark-mode - we're storing the theme in a cookie now, not localStorage
AI:  Reading add-dark-mode artifacts...
     The design references localStorage in two places; tasks 1.3 covers
     localStorage persistence; the proposal doesn't mention storage.

     Proposed revisions:
     1. design.md - swap localStorage decision for cookie storage
     2. tasks.md - reword task 1.3 to cookie persistence

     Apply revision 1? (design.md)

/opsx:verify:三个验收维度

它检查三个方面,报告分成 CRITICAL / WARNING / SUGGESTION 三档,并且不会拦住归档——它只把问题摆出来。官方口径是"归档前跑一遍能早点发现不一致"。

维度它查什么典型发现
完整性(Completeness)任务是否全勾完、每条需求是否都有对应实现、场景是否都被覆盖"系统偏好探测"这个场景没有测试覆盖
正确性(Correctness)实现是否符合规格意图、边界情况是否处理错误分支和规格描述不一致
一致性(Coherence)设计决策是否反映在代码里、命名和模式是否统一design 说用 CSS 变量,实现里却用了 Tailwind 类

官方文档的输出示例,能看出它具体到什么程度:

# /opsx:verify 的典型输出(官方文档示例,有删节)
COMPLETENESS
✓ All 8 tasks in tasks.md are checked
✓ All requirements in specs have corresponding code
⚠ Scenario "System preference detection" has no test coverage

COHERENCE
⚠ Design mentions "CSS variables" but implementation uses Tailwind classes

SUMMARY
Critical issues: 0
Warnings: 2
Ready to archive: Yes (with warnings)

开关这两档:profile 与 delivery

"装哪些命令"由两个设置决定,都在全局配置里,改完之后要在项目里跑一次 openspec update 才会落到项目文件上。

设置管什么可选值怎么改
profile(档位)装哪一组工作流core(默认,六条)/ 自定义(勾选 expanded 那六条)openspec config profile(交互式)或 openspec config profile core(快速切回)
delivery(投递方式)写 skill 文件、命令文件,还是两者都写skills / commands / both同一个 openspec config profile 向导里选"只改投递方式"
# 查看 / 修改全局配置,再把它应用到当前项目
openspec config profile          # 交互式向导:先给你现状摘要,再让你选改什么
openspec config profile core     # 快速预设:工作流切回 core(保留投递方式)
openspec config list             # 看当前所有设置
openspec update                 # 把选择落到本项目的生成文件上

向导里有个设计细节值得知道:如果你选"保持当前设置"退出,它不会写任何东西、也不会弹升级提示;但如果设置没变、而项目里的文件与全局设置不一致,它会警告并建议你跑 openspec update。另外,勾选清单里的 [x] 只表示"这个工作流在全局配置里被选中了",要真正落到项目文件上还是得跑 update。

11需求变了:改这张图,还是重开一个 change

这是用起来之后最容易做错的判断,代价很具体:要么让一个 change 变成大杂烩(图纸没人愿意看),要么让本来一件事的历史被拆成三段互不相干的故事。

官方的判据:同一件工作被细化 vs 意图根本变了

🔄 用 /opsx:update:同一件事,细化了
  • 意图没变,只是执行细节被修正
  • 范围收窄了(比如砍到 MVP)
  • 实现过程中发现设计有小偏差
  • 理由:历史里的思考链有价值,保留它
🆕 开新 change:本质上已经是另一件事
  • 意图变了(深色模式 → 整套主题系统)
  • 范围膨胀到原 proposal 面目全非
  • 原来那个 change 本来就可以结项了
  • 理由:硬往上补只会让故事线混乱

官方文档里对应的原话是两句:FAQ 里说"当它是同一件工作、被细化时用 update;当意图根本改变、或范围炸成了不同的工作时,重新开始";/opsx:update 的说明里说"如果你的修改改变了这个 change 的意图,就改用一个新 change 重来"。

三问自测(把上面的判据落到可操作)

#问自己答"是"意味着
1还是同一个问题吗?("让用户能切换深浅色"vs"让整套视觉可配置")意图没变 → 倾向 update
2范围还大体重叠吗?(原来要做的事,大部分还是原来那些吗)重叠 → 倾向 update
3不改图纸的话,原来那个 change 能算"做完了"吗?答"能"→ 说明新需求是另一件事 → 开新 change

前两问答"是"、第三问答"不能"→ 用 /opsx:update 改图。否则开新 change。

改图的具体动作

不管走哪条路,"怎么改图纸"这件事本身没有门槛:工件就是普通的 Markdown 文件,改它有两种等价方式——直接在编辑器里改文件,或者在聊天里告诉 AI"把设计改成用后台任务,不要同步调用"。官方特意说明:没有专门的"改提案"命令,因为你不需要;文件就是唯一真相,改文件就是改图纸。而且 AI 永远从文件的当前内容出发工作,所以改完接着跑 /opsx:apply 就行。

📖 手改了代码怎么办

这事天天发生,而且没关系。原则是:归档那一刻,规格就变成"有记录的真相",所以归档前要让规格对代码诚实。两个方向选一个:代码才是对的 → 把 delta 规格改成描述你实际发出去的行为;规格才是对的 → 继续把代码改到符合规格。/opsx:verify 会告诉你哪里分了叉,把它当待办清单用。

12项目配置:让 AI 每次都知道你们家的规矩

如果你每次都要重复提醒"我们用 TypeScript、接口是 REST 风格、测试用 Vitest",那这份配置就是为你准备的。把项目背景写一次,之后每次生成工件时它都会自动带上。

文件在哪、装的时候怎么建

位置是 openspec/config.yaml。openspec init 会问你要不要建它,官方推荐建。注意扩展名必须是 .yaml,不能写成 .yml——这是官方排错文档里列出的第一个"配置没生效"的原因。

一份能照抄的完整配置

# openspec/config.yaml
schema: spec-driven

context: |
  Tech stack: TypeScript, React, Node.js, PostgreSQL
  API style: RESTful, documented in docs/api.md
  Testing: Jest + React Testing Library
  We value backwards compatibility for all public APIs

rules:
  proposal:
    - Include rollback plan
    - Identify affected teams
  specs:
    - Use Given/When/Then format
    - Reference existing patterns before inventing new ones

operations:
  apply:
    guidance:
      - Run focused tests before the full suite
  archive:
    guidance:
      - Keep the completion summary concise

# openspec init 问你(或替你决定)的 GitHub Copilot 云 coding agent 开关
githubCopilot:
  cloudAgent: false

四个字段分别管什么

字段管什么作用范围别当什么用
schema这个项目默认用哪套工件流程全局默认值,命令上仍可用 --schema 覆盖别当"锁"——它只是免去你每次都传参数的麻烦
context项目背景:技术栈、约定、约束注入到每一个工件的提示词里别当文档仓库——它上限 50KB,塞太多既报错又拖慢、效果还更差;长内容用链接引出去
rules按工件分别加的规矩只注入到对应工件(proposal / specs / design / tasks)写错工件 ID 会报 Unknown artifact ID in rules: X;合法 ID 用 openspec schemas --json 查
operations给"执行类操作"的建议(比如 apply / archive 时该注意什么)在 openspec instructions apply/archive --json 时随 context 一起返回它不是 rules:约束不了工件内容,只是给 agent 的建议;两者不会被互相改名顶替

官方把注入机制写得很直白:生成工件时,context 和 rules 被塞进 AI 的提示词,形如 <context>…</context> + <rules>…</rules> + <template>…</template> 三段。context 进所有工件,rules 只进匹配的那一个。operations 下的建议则是每次执行时现取快照——改了立刻生效,不用重启。

关掉遥测 + 几个常用开关

# 彻底关掉匿名遥测(也可以设环境变量 OPENSPEC_TELEMETRY=0 或 DO_NOT_TRACK=1)
openspec config set telemetry.enabled false

# 看配置存在哪里、现在都有什么
openspec config path
openspec config list
openspec config get telemetry.enabled

# 用显式字符串写入(避免被当成数字 / 布尔)
openspec config set user.name "My Name" --string
openspec config unset user.name

# 用编辑器打开配置文件
openspec config edit

# 重置全部配置(会先确认)
openspec config reset --all --yes

遥测的默认状态是"未设置即开启"(opt-out 模型)。环境变量的优先级高于配置文件,而且 CI 被设成真值时(true/1/yes)无视配置直接关闭。

初始化时的三个实用参数

参数做什么什么时候用
--language <语言>在新项目的 config.yaml 里写入一条语言指令想让 AI 用中文写规格(已有项目改 context 字段,不要靠 init 覆盖)
--force非交互地自动清理旧版本残留文件在 CI 里跑 init,遇到 Legacy files detected in non-interactive mode 时
--no-animation开场动画换成静态欢迎屏终端录制、无障碍需求(也可设 OPENSPEC_NO_ANIMATION,或设 NO_COLOR、开启系统的"减少动态效果")

13进阶:自定义工作流(schema)与跨仓库规格(Stores)

如果你现在是一个人一个仓库,这一节可以跳过,需要时再回来。

schema:定义"有哪些工件、谁依赖谁"

默认那套 spec-driven(proposal → specs → design → tasks)本身就是一个 schema。你可以 fork 一份改成自己的流程——官方举的典型例子是"研究前置型":research → proposal → tasks。

openspec schema fork spec-driven my-workflow   # 拷一份出来改
openspec schema validate my-workflow          # 改完校验结构和模板
openspec schemas                              # 看有哪些可用
openspec schema which spec-driven              # 看某个名字到底从哪儿解析来的(排查用)

# 不想 fork 的话,也能直接新建一个
openspec schema init rapid \
  --description "Rapid iteration workflow" \
  --artifacts "proposal,tasks" \
  --default
命令做什么产物 / 输出
schema init <name>新建一个项目内 schemaopenspec/schemas/<name>/schema.yaml + templates/
schema fork <source> [name]把已有 schema 拷进项目再改同上(不改源 schema)
schema validate [name]校验结构与模板不写名字就校验全部
schema which [name]显示这个 schema 从哪儿解析来的排查"我改的 schema 怎么没生效"

解析优先级是三层,从近到远:项目里 openspec/schemas/<name>/ → 用户级 ~/.local/share/openspec/schemas/<name>/ → 包里内置的 schema。所以同名时项目里的会赢——这也解释了为什么"我改了但没生效"通常是因为改到了另一层。

社区还有现成的 schema 包(极简版、事件驱动版等),官方 customization 文档里有目录。但默认那套够用很久,别一上来就改流程。

Stores:一个需求横跨三个仓库时怎么办

单人单仓库时,openspec/ 跟代码放在一起就行。但一个需求同时涉及 API 服务、Web 应用、共享库三个仓库时,规格该放哪?官方给的答案是 Stores:把 openspec/ 单独放一个仓库,用 git push 共享。

它解决的问题怎么解代价
跨仓库的功能(代码落在三个仓库里)一次 change、一份计划,放在 store 仓库里多个仓库要引用同一个 store
需求的归属(平台团队拥有规格,产品团队只读引用)产品团队把 store 注册进来、只读引用,AI 也能读到同一份真相多一层权限 / 流程约定
代码还不存在,但计划要先定先把计划写进 store,代码仓库后补计划与实现之间会出现时间差
# 建一个本地 store 并注册(standalone 的 OpenSpec 仓库)
openspec store setup team-plans
openspec store register /path/to/store
openspec store list
openspec store doctor                 # 检查本地 store 配置有没有问题

# 报告"解析出的根"的关系健康度 / 打印当前装配出的工作集(根 + 被引用的 store)
openspec doctor
openspec context
⚠️ Stores 还在 beta

官方 README 明确写着 "Stores are in beta",用户指南单独放在 docs/stores-beta/。个人学习和小团队先别碰它——把单仓库流程玩熟,等它转正再说。另外提醒一个容易混淆的命名:CLI 里的 context 命令(装配工作集)和 config.yaml 里的 context: 字段(注入给 AI 的项目背景)是两件事,官方专门点名了这个歧义。

14审图十分钟:到底盯哪几处

审图是这套流程里人最值钱的十分钟:AI 出图很快,但图错了,施工越快返工越多。难处在图纸有好几页,新手不知道该看哪。

三处必看

#看哪儿在找什么发现了怎么办
1proposal.md 的"不改什么"范围有没有悄悄变大(你的"加个开关"变成了"重构主题系统")在聊天里说"范围太宽,去掉 X",或让它 /opsx:update
2specs/ 里的 WHEN/THEN 场景边界和错误情况有没有被覆盖(不只是"顺利路径")直接点名你关心的情况:"给一个已经手动选过主题的用户补个场景"
3tasks.md 的每一项每项是否都写明了"怎么算完成"(一个测试、一条命令、一个可观察的行为)让 AI 把模糊项拆细,或者你自己补上验收方式

官方给的快速检查清单

官方 writing-specs 文档末尾有一份勾选清单。它的六条问的是同一件事的六个面,值得抄下来当审图模板:

检查项为什么它值得单独列一条
每条需求都是一个可观察的行为,且用了 SHALL/MUST含糊的 SHALL 是返工的源头
需求里没有混进实现细节实现细节会随代码过时
每条需求至少有一个真正在验证它的场景换个说法重复需求的场景等于没测(官方原话:tests nothing)
重要的边界与错误情况有场景,不只是顺利路径官方原话:bug 就住在这里
delta 的 ADDED / MODIFIED / REMOVED 用对了用错会造成主规格里两条打架的需求,或"没有东西可替换"
整个 change 只有一句话能说清的意图需要很多"而且还…"就是该拆的信号

两个可以拿去用的自问句

"有哪个场景一旦坏了,我会特别难受?"
官方推荐的审图习惯:在批准之前问自己这一句,然后确认有一个场景点名了它。如果翻遍 specs 都没有,就是漏了——补上再开工。这一句比"场景写全了吗"这种抽象问题有用得多。
"方案里哪些取舍是 AI 替我做的?"
看 design.md 的 Decisions 段。官方模板要求每个决策都写清"为什么选 X 不选 Y"以及考虑过哪些替代方案。如果你发现有决策没给理由、或者理由不成立,就在这一步拦下来——这比在代码里发现代价小得多。

怎么把图纸改到你满意

三种改法,按代价从小到大:

  1. 在聊天里指出问题:"范围太宽,去掉管理后台那部分。" 最便宜,通常也最对。
  2. 退回去 explore:如果问题出在"想法本身还没想清",退回 /opsx:explore 聊透,再让一份更准的 proposal 出来。
  3. 重开一个 change:如果意图已经根本变了(见 11 节的三问自测)。

在开始实现之前就指出问题,比以后纠正要便宜得多——这也是"先出图纸"的整个理由。

15七个常见坑

每一条都能在官方文档里找到出处。

坑你看到的现象怎么避开
🚫 跳过审图直接 apply图纸错了,施工越快返工越多审图十分钟能省施工两小时;三处必看见 14 节
🐘 一个 change 塞太多事"顺手"把重构、升依赖、新功能塞进同一个 change,结果没人愿意审、任务互相打架官方判据:一个好 change 的意图能一句话说清;需要很多"而且还…"就该拆
🧹 手改代码不同步图纸你顺手改了两行没更新规格,图纸和实现分叉归档前用 /opsx:verify 找分叉(11 节)
📦 忘了 archive,change 越堆越多changes/ 下躺着好几个做完了却没归档的文件夹,/opsx:apply 不知道该做哪个做完就归;攒多了用 /opsx:bulk-archive(需要开启 expanded)
❌ 场景标题用了三个井号规格看着没问题,但场景没被识别——官方原话是静默失败(fail silently)必须恰好四个:#### Scenario: …
📝 MODIFIED 只写了改动的那部分归档后主规格里丢了一批场景;validate 报 "omits scenario(s)…"把本来就有、且仍然保留的场景全部带上
🔧 把配置文件写成 .yml配置完全不生效,你以为它在起作用必须是 openspec/config.yaml;改完立即生效,不需要重启

另外三个"不是坑但很反直觉"的点

16排错:六个真会遇到的问题

每一条都来自官方 troubleshooting 文档,顺序按"最快能检查"排。

1 · 敲了 /opsx:propose,什么都没发生

按代价从低到高排查,官方给的就是这个顺序:

  1. 你可能敲错地方了。斜杠命令在 AI 聊天框里,不在终端。如果在 shell 里敲的,这就是原因。
  2. 重新生成文件。在项目根目录跑 openspec update,它会重写你配置过的每个工具的 skill/命令文件。
  3. 重启你的助手。多数工具只在启动时扫描技能和命令,开个新窗口往往就好了。
  4. 确认文件真的存在。比如 Claude Code 下看 .claude/skills/ 里有没有 openspec-* 目录。
  5. 确认你初始化的是这个项目。技能是按项目写的;换了目录或 clone 了新仓库,就要在那个目录里跑一次 openspec init 或 openspec update。
  6. 确认你的工具支持命令文件。Codex、CodeArts、ForgeCode、Hermes、Kimi Code、Mistral Vibe、Zed Agent 和共享的 .agents 目标不生成 opsx-* 命令文件,所以 /opsx 永远不会自动补全——它们走 skill 调用形式(见 03 节那张拼写表)。

2 · Change not found

它无法确定你指哪个 change。两个动作:明确写出名字,或者先看看有哪些。

openspec list                     # 终端:看当前有哪些进行中的 change
/opsx:apply add-dark-mode        # 聊天:把名字写出来

顺便确认你在正确的项目目录里——技能是按项目写的。

3 · No artifacts ready

意思是:每个工件要么已经生成了,要么在等它依赖的东西。看谁在挡路:

openspec status --change <name>

记一下顺序:proposal 解锁 specs 和 design;specs 和 design 两个都完成才解锁 tasks。看到 [-] tasks (blocked by: design) 就说明设计还没写。

4 · openspec validate 报错 / 警告

读它给的消息——它会点名文件、说明问题。常见原因是缺必需小节(比如一份规格没有任何场景),或者 delta 标题格式写错了。按前面说的修,再重跑。第 15 节里那个"MODIFIED 漏场景"的报错是唯一值得单独记的。

openspec validate <name>              # 校验一个
openspec validate --all               # 校验全部
openspec validate --all --strict      # 更严,适合 CI
openspec validate --archived          # 已归档的 change 里有没有没勾完的任务

5 · AI 生成的工件不完整或者偏了

官方把这个归因成一件事:AI 拿到的上下文不够。四个可用的手段:

手段怎么做什么时候用它
补项目背景在 config.yaml 的 context: 里写技术栈和约定它每次都猜错你们的框架 / 风格时
加按工件的规矩在 rules: 下给 specs 之类加条目只有某一类工件反复出同样的问题时
把需求描述写细propose 的时候把意图和边界都说清楚图一开始就跑偏,且不是风格问题
改用一件一件生成用 /opsx:new + /opsx:continue 代替 /opsx:ff复杂改动,你想每写完一件就审一次

官方给的"把 AI 引向好草稿"的具体话术也值得抄:把意图和边界一起说——"加一个深色模式开关,首次加载跟随系统设置——不要动现有主题 API"(后半句和前半句一样重要);点名你在意的情况——"确保有一个场景覆盖已经手动选过主题的用户"。

6 · 用 bun 装的,为什么还要 Node?

因为它是用 Node 运行的。bun / npx 只负责把它下载下来,运行时的引擎仍然是 Node,所以 PATH 里必须有 20.19.0 或更高版本的 node。openspec --version 能跑通就说明这件事没问题。

7 · 想报告问题或问人

渠道怎么用
Discord官方社区,discord.gg/YctCnvvshC
GitHub Issuesgithub.com/Fission-AI/OpenSpec/issues
直接在终端提openspec feedback "你遇到的问题"——它会替你开一个 issue

官方请求附带的信息:OpenSpec 版本(openspec --version)、Node 版本(node --version)、你用的 AI 工具、以及完整命令和完整输出。

97它和别的方案差在哪

市面上"管 AI 写代码"的东西大致分三类。官方 README 直接点名对比了两个同行,下面是加上了"什么都不用"这一栏的完整对照。

维度OpenSpecSpec Kit(GitHub 出品)Kiro(AWS)纯氛围编程
流程形态流动的、可随时改图,没有阶段门严格的阶段门,偏重IDE 内置、开箱即用没有流程,想到哪说到哪
上手成本低:一条 npm 命令 + Markdown官方口径:需要 Python 环境和大量文档低,但你要换到它的 IDE零
工具绑定基本无绑定:支持 30+ 助手绑定 GitHub 生态锁定它的 IDE 和部分模型无
可定制schema 可 fork、可自建有社区扩展包较弱——
官方自己的定位"更轻,允许你自由迭代""彻底,但重""强大,但你被锁进他们的 IDE""没有规格就是含糊的提示词和不可预测的结果"

最后一列的措辞不是我编的,是官方 README 里 "How we compare" 那一节的原意。要公平地说一句:对手的"重"不是缺点,是取舍——如果你的组织需要审批留痕、每个阶段都要检查点,那"更轻"对你就不是优点。

💡 怎么选

一次性 demo 和脚本:直接氛围编程最快;要维护、要协作、AI 容易跑偏:OpenSpec;企业级强合规:再考虑 Spec Kit;全家桶都在 AWS:可以试 Kiro。对绝大多数刚开始用 AI 写代码的人来说,从 OpenSpec 起步是成本最低的一档。

它和"就写个 PRD 放仓库里"的最后一个区别

有人会问:"我自己写个 PRD.md 提交到仓库,不也一样落盘了吗?"三处不同:一是结构——四种工件各管一件事、依赖方向固定,而不是一份什么都能塞的文档;二是可执行——tasks.md 的复选框会被逐项执行和打勾,形成闭环;三是会自动合并——归档那一刻,规格里"改动的那部分"被自动并回系统现状说明书,而不是留在某个角落慢慢过期。

98术语对照表

术语定义为什么重要 / 何时用 · 别当什么用
SDD(规格驱动开发,Spec-Driven Development)先把"要做什么"写成规格文件、再让 AI 照它写代码的做法这是 OpenSpec 的核心主张;别当教条——改一个错别字的改动直接写更快
CLI(命令行工具)装在终端里的程序,名字就叫 openspec只管装、查、校验、归档;别把它当成干活的入口——干活在聊天框里
OPSX当前这套以 /opsx: 为前缀的工作流(动作式,不是阶段式)新上手直接用这套;别把它当成某个可选插件——它就是默认工作流本身
斜杠命令(slash command)敲在 AI 助手聊天框里的命令,如 /opsx:propose日常干活的入口;别在终端里敲它——这是新手第一号坑
change(一次改动)openspec/changes/<name>/ 下一个文件夹,装一次改动的全部工件一个需求开一个 change、做完就归档;别把它当"任务清单"——它装的是一整套规划
工件(artifact)change 里的一份规划文档:proposal / specs / design / tasks它们是"图纸"不是"代码",价值在于让人审、让 AI 照着做;别让它们膨胀成没人读的八股文
proposal(提案)"为什么做、改什么、不改什么、影响谁"审图第一个看的就是它,重点看范围边界;别当需求文档用——具体行为归 specs
spec(规格)描述系统行为的需求 + 场景;有"现状规格"和"delta 规格"两种形态它是"系统现在应该表现成什么样"的唯一说法;别把技术选型写进去——那属于 design
需求(requirement)一条用 SHALL/MUST 写的可观察行为它是 AI 施工的合同条款;别一条里塞三个"而且还"——那是三条需求
场景(scenario)一条需求的具体例子,用 #### Scenario: + WHEN/THEN 写它是需求的"证据",也能直接变成测试;必须恰好四个井号,否则静默失效
delta 规格(增量规格)change 里的规格,只写"这次改了什么",用 ADDED / MODIFIED / REMOVED / RENAMED 标记它让评审聚焦差异、让老系统能渐进接入;别在 delta 里重述系统现状——那是主规格的职责
source of truth(主规格 / 现状真相)openspec/specs/ 整个目录,永远描述系统当前的行为归档后它会被 delta 合并、代表"现在的真相";别让它和代码脱节——每次归档后它都该是最新的
domain / capability(领域 / 能力)规格的分组方式,比如 auth/、payments/、ui/决定了路径长什么样(specs/ui/spec.md);别在已有项目里另造一套命名——跟着现有组织方式走
design(设计文档)"怎么做":技术方案、取舍、风险、迁移与回滚简单改动可以不要它;别把它写成代码复制粘贴——它要回答的是"为什么选这个方案"
tasks(任务清单)带复选框的实施步骤,每项写明怎么算完成唯一会被"执行"的工件(/opsx:apply 逐项打勾);别把它当愿望清单——每项都要可验收
archive(归档)合并 delta 进主规格 + 把 change 移进 changes/archive/YYYY-MM-DD-<name>/它让规格跟上现实、让历史可追溯;别攒着不归——堆多了 AI 都不知道哪个在进行中
sync(同步)只把 delta 合并进主规格、不归档这个 change长跑型 change 或并行 change 需要提前合并时用;通常不用手动跑——归档会问你要不要
profile(档位)决定装哪一组斜杠命令:core(六条)或自定义(加 expanded 六条)新手用 core 就够;改完记得跑 openspec update,否则只在全局配置里改了、项目里没变
delivery(投递方式)生成 skill 文件、命令文件,还是两者都生成由工具决定,你不用选;别去手改生成的文件——更新时会被覆盖
skill(技能文件).../skills/openspec-*/SKILL.md,AI 助手自动识别的指令文件较新的跨工具标准,Codex / Kimi 这类工具只认它;别把它当你的项目文档——它归 OpenSpec 所有
schema(流程定义)定义有哪些工件、谁依赖谁;默认是 spec-driven团队统一一套 schema 能让产物可预期;别为一次性小需求配复杂 schema
template(模板)schema 里决定 AI 生成物形态的 Markdown 骨架改模板立刻改变 AI 输出,不用重建;别在项目里随手改内置模板——fork 一份再改
Store(规格仓库,beta)把 openspec/ 单独放一个仓库,供多个代码仓库共享多仓库团队想复用同一套规格时引入;单仓库项目别碰——它还在 beta
RFC 2119 关键词MUST/SHALL(硬性)、SHOULD(建议)、MAY(可选)它们决定了 AI 能不能给自己留余地;默认全部用 SHALL,别用 SHOULD 含糊过去
brownfield / greenfield存量项目(已有代码)/全新项目(从零开始)OpenSpec 的主场景是前者——不用先补全文档;别误以为接入前必须先重构
氛围编程(Vibe Coding)没有规格、靠对话即时驱动 AI 写代码一次性脚本和 demo 用它最快,是 OpenSpec 的合法反面对;别用它来写要维护、要协作的功能
上下文卫生(context hygiene)官方建议:开工前清一次对话上下文,过程中保持干净带着几百轮聊天记录去 apply,AI 只会越做越糊涂;别以为规格文件能完全代替它——两者互补

99一页纸速查表

读第二遍时只看这一节。左边是"我要…",右边是敲什么。

终端命令(openspec …)

我要…敲…
安装 CLInpm install -g @fission-ai/openspec@latest
在项目里初始化openspec init(非交互:openspec init --tools claude,cursor)
升级后刷新 AI 指令文件openspec update(先升级包再跑它)
看有哪些进行中的 changeopenspec list
看项目已覆盖哪些规格openspec list --specs
看某个 change 的工件进度openspec status --change "<name>"
读某个 change / 规格的详细内容openspec show <name> / openspec show <id> --type spec
打开交互式看板openspec view
校验一个 changeopenspec validate <name>
CI 里校验全部(严格)openspec validate --all --strict
查已归档的 change 有没有漏勾的任务openspec validate --archived
在终端归档(agent / CI 必须带 --yes)openspec archive <name> --yes
看有哪些 schemaopenspec schemas
切档位 / 投递方式openspec config profile 然后 openspec update
关掉匿名遥测openspec config set telemetry.enabled false
提反馈(会自动开 issue)openspec feedback "…"

聊天框命令(/opsx:…)

我要…敲…档位
想法还很模糊,先聊透(不写文件)/opsx:explorecore(默认)
立项并一次性生成全套图纸/opsx:propose <change-name>core
照图施工/opsx:apply [<change-name>]core
只改图纸、不动代码/opsx:update [<change-name>] + 说明你要改什么core
提前把 delta 合进主规格(不归档)/opsx:synccore
验收归档/opsx:archivecore
先搭空架子,再逐个生成工件/opsx:new 然后 /opsx:continueexpanded
一次把图纸全部生成/opsx:ff [<change-name>]expanded
验收"实现 vs 图纸"/opsx:verifyexpanded
批量归档/opsx:bulk-archiveexpanded
被手把手带一遍/opsx:onboardexpanded

配置文件要点

# openspec/config.yaml —— 文件名的扩展名必须是 .yaml
schema: spec-driven          # 默认流程,可用 --schema 覆盖
context: |                   # 注入每一个工件(上限 50KB)
  Tech stack: TypeScript, React, Node.js, PostgreSQL
rules:                       # 只注入到对应工件
  proposal:
    - Include rollback plan
  specs:
    - Use Given/When/Then format
operations:                  # 给 apply / archive 的建议(不是 rules,约束不了内容)
  apply:
    guidance:
      - Run focused tests before the full suite

上手路线(三天,每天一个目标)

第 1 天:跑通最小闭环

找个玩具项目或新建空仓库:openspec init → 用 /opsx:onboard 跟着带练走一遍 propose → apply → archive。目标:亲手摸到四种工件长什么样,特别是 tasks.md 的复选框怎么被勾掉。

第 2 天:在真实小需求上用一次

挑一个一小时能做完的真实需求(加个 404 页面、修个小 bug),完整走一遍 explore → propose → 审图 → apply → archive。重点练审图:试着驳回一次 AI 的图纸,体会什么叫好的 WHEN/THEN 场景。

第 3 天:把配置写成团队资产

写一份 openspec/config.yaml(技术栈 + 测试约定 + spec 格式),试一次 /opsx:update 改图,再试一次 verify 验收。做完你就可以在正式项目里接需求了。

100一句话总结

🎯 核心要点

OpenSpec 就是"先出图纸再施工":在终端跑两条命令把它装好,然后在 AI 聊天框里用 /opsx:propose → /opsx:apply → /opsx:archive 这套动作,把需求锁进仓库里的 Markdown 图纸,让 AI 照图施工、人只负责审图和验收——从今天起,别让重要的需求只活在聊天记录里。

101参考来源与证据边界

一手来源(全部联网读取)

本文自己做的核对

证据边界与时效

⌂