OpenSpec 到底怎么用
它不是替你写代码的工具,而是你和 AI 开工前签字的那张图纸:先谈妥"要做什么",再让 AI 动手。
📅 更新于 2026-09-13
本文校对于 OpenSpec @ v1.13.0 · 官方源:github.com/Fission-AI/OpenSpec
0030 秒速览:三条结论 + 按处境挑入口
读完这篇你能做到一件事:在自己的项目里跑通一次「想法 → 图纸 → 施工 → 归档」的完整闭环,并且知道什么时候不该用它。
这一篇是上手篇:两个半场(终端 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(产品需求文档)?
不是一类东西,差别有三处,而且每一处都直接影响你会不会用错:
| 差别 | 聊天框里写 PRD | OpenSpec 的做法 |
|---|---|---|
| 落在哪 | 留在对话里,关掉窗口就散 | 落在仓库的 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.js | 20.19.0 或更高(硬性要求,低版本装不上) | 终端里跑 node --version |
| 一个 AI 编程助手 | Claude Code、Cursor、Codex、GitHub Copilot、Gemini CLI 等 30+ 工具 | 你平时用哪个就用哪个 |
| git 仓库 | 强烈建议:图纸评审走 PR,归档留下历史 | git status 能跑通就行 |
报错原文是 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 明确指定。
官方文档里有一份 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:archive | AI 助手的聊天框(就是你平时让它写代码的那个框) | 驱动 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-propose | Codex 这类工具根本不生成 opsx-* 命令文件,走 skill 调用 |
| Kimi Code | /skill:openspec-propose | 同样是 skill 式调用 |
共享的 .agents 目标 | /openspec-propose | 官方特意说明:这是通用形式,不保证每个助手都认——不认就查它自己的文档 |
好消息:openspec init 结束时会把你选中的那几个工具的正确写法打印出来。以它为准,比背上面这张表可靠。
安装相关的三条实务细节
- 命令找不到(
openspec: command not found):多半是全局 npm 的 bin 目录不在 PATH 上。跑npm prefix -g看全局包装在哪——macOS / Linux 上可执行文件在它下面的bin/,Windows 上就在该目录里。把它加进 PATH。(npm bin -g在 npm 9 已被删除,别再用它。) - 它不收集你的代码:官方说明遥测只上报命令名和版本号,不含参数、路径、内容和个人信息,CI 环境自动关闭。介意的话一条命令关掉(见 12 节)。
- 卸载没有专门命令:它就是一个全局包加项目里几个文件。跑
npm uninstall -g @fission-ai/openspec,然后按需删掉项目里的openspec/目录和生成出来的工具文件。
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(终端那一半)是引擎。它知道规矩:一个 change 文件夹该长什么样、哪个工件依赖哪个、怎么把一份 delta 合并进主规格。这部分跟你的 AI 工具无关,所以能保持一致。
- 斜杠命令(聊天框那一半)是方向盘。而每个 AI 工具的方向盘都长得不太一样:Claude Code 叫 commands,Cursor 有自己的格式,有些工具干脆叫 skills。你跑
openspec init时,OpenSpec 按你选中的工具生成对应格式的文件,于是同一个"提案"的意图在哪都能用。
好处是工作流只学一次、换工具不用重学;代价是同一条命令的拼写可能不同(见上一节那张表)。
两半的核对清单
| 做完这件事,说明哪一半没问题 | 命令 | 期望结果 |
|---|---|---|
| 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.md | Claude 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/(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 文档给的判据是一句话:"一个没看过代码的测试者,能不能判断它过没过?"答不能,就需要改。
### Requirement: Dark mode
The app SHOULD support dark mode somehow.
"somehow"把设计权整个扔给了 AI,"SHOULD"又留了模糊余地。它猜错了,你还得返工。
### 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 # 这次不改规格(纯工具/文档类改动)
归档会问确认问题。在 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(这才是它的主场)
存量项目是它官方定位的主场景。不用重写、不用先补全文档,路线是"先摸清现状,再圈小范围":
/opsx:explore 让 AI 去读相关代码,搞清楚根因和有哪几种修法。官方 explore 文档举的例子很典型:你说"结算偶尔会生成重复订单,我不知道为什么、也不知道怎么安全地修",它读完订单服务、支付回调、客户端提交逻辑之后告诉你——重复有两个来源,其中一个会重复扣款,三个修法按健壮性排序。这些结论在 propose 之前就拿到了,而且零成本。
修 bug 的 change 宁小勿大。"修登录超时"不要膨胀成"重写鉴权系统"——后者该是一个独立的 change。判断标准见 11 节。
官方 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
/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 | 带你走一遍完整流程的引导教程 | 第一次用,想被人手把手带 |
核心三件套长什么样(逐个拆)
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
tasks.md,找出没勾的项,一项项做:写代码、建文件、跑测试,然后把复选框打上勾。施工中途被打断也能接着做——进度就记在那些复选框里。施工中发现图纸错了,直接改工件继续,不必推倒重来。/opsx:apply # 只有一个进行中的 change 时自动推断
/opsx:apply add-dark-mode # 有多个并行 change 时必须点名
/opsx:archive
# 终端等价物(agent / CI 里要带 --yes):
openspec archive add-dark-mode --yes
/opsx:update:只改图纸、不碰代码
这条命令值得单独讲,因为它是"规格驱动"和"在聊天里改需求"最大的区别所在。它的行为很具体:
- 它读这个 change 的所有工件(内部用的是
openspec status --change <name> --json),然后应用你要求的修改;如果你什么都没指定,它会替你检查工件之间有没有互相矛盾。 - 它会双向调和已有工件:改 design 可能反向牵动 proposal,改需求可能牵动 tasks。
- 它每改一件都先跟你确认,一次一件。
- 结尾会建议下一步该
/opsx:continue(还缺工件)、/opsx:apply(把改过的图纸落进代码),还是/opsx:archive(都做完了)。 - 它不会创建缺失的工件——那是
/opsx:continue的事。
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 意图根本变了
- 意图没变,只是执行细节被修正
- 范围收窄了(比如砍到 MVP)
- 实现过程中发现设计有小偏差
- 理由:历史里的思考链有价值,保留它
- 意图变了(深色模式 → 整套主题系统)
- 范围膨胀到原 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> | 新建一个项目内 schema | openspec/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
官方 README 明确写着 "Stores are in beta",用户指南单独放在 docs/stores-beta/。个人学习和小团队先别碰它——把单仓库流程玩熟,等它转正再说。另外提醒一个容易混淆的命名:CLI 里的 context 命令(装配工作集)和 config.yaml 里的 context: 字段(注入给 AI 的项目背景)是两件事,官方专门点名了这个歧义。
14审图十分钟:到底盯哪几处
审图是这套流程里人最值钱的十分钟:AI 出图很快,但图错了,施工越快返工越多。难处在图纸有好几页,新手不知道该看哪。
三处必看
| # | 看哪儿 | 在找什么 | 发现了怎么办 |
|---|---|---|---|
| 1 | proposal.md 的"不改什么" | 范围有没有悄悄变大(你的"加个开关"变成了"重构主题系统") | 在聊天里说"范围太宽,去掉 X",或让它 /opsx:update |
| 2 | specs/ 里的 WHEN/THEN 场景 | 边界和错误情况有没有被覆盖(不只是"顺利路径") | 直接点名你关心的情况:"给一个已经手动选过主题的用户补个场景" |
| 3 | tasks.md 的每一项 | 每项是否都写明了"怎么算完成"(一个测试、一条命令、一个可观察的行为) | 让 AI 把模糊项拆细,或者你自己补上验收方式 |
官方给的快速检查清单
官方 writing-specs 文档末尾有一份勾选清单。它的六条问的是同一件事的六个面,值得抄下来当审图模板:
| 检查项 | 为什么它值得单独列一条 |
|---|---|
每条需求都是一个可观察的行为,且用了 SHALL/MUST | 含糊的 SHALL 是返工的源头 |
| 需求里没有混进实现细节 | 实现细节会随代码过时 |
| 每条需求至少有一个真正在验证它的场景 | 换个说法重复需求的场景等于没测(官方原话:tests nothing) |
| 重要的边界与错误情况有场景,不只是顺利路径 | 官方原话:bug 就住在这里 |
| delta 的 ADDED / MODIFIED / REMOVED 用对了 | 用错会造成主规格里两条打架的需求,或"没有东西可替换" |
| 整个 change 只有一句话能说清的意图 | 需要很多"而且还…"就是该拆的信号 |
两个可以拿去用的自问句
design.md 的 Decisions 段。官方模板要求每个决策都写清"为什么选 X 不选 Y"以及考虑过哪些替代方案。如果你发现有决策没给理由、或者理由不成立,就在这一步拦下来——这比在代码里发现代价小得多。怎么把图纸改到你满意
三种改法,按代价从小到大:
- 在聊天里指出问题:"范围太宽,去掉管理后台那部分。" 最便宜,通常也最对。
- 退回去 explore:如果问题出在"想法本身还没想清",退回
/opsx:explore聊透,再让一份更准的 proposal 出来。 - 重开一个 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;改完立即生效,不需要重启 |
另外三个"不是坑但很反直觉"的点
- 归档不会因为你没勾完任务而拦住你。它只警告。如果你确实想归档一个部分完成的工作,可以继续;否则先把任务做完。这个设计是有意的,但第一次遇到会以为它坏了。
/opsx:sync通常不需要手动跑。归档会问你要不要同步。只有"长跑型 change 想在归档前就合并"或"并行 change 需要基于最新规格"时才手动调它。官方 FAQ 的原话是"大多数用户永远不需要直接调用它"。- 生成的指令文件不要手改。skills 文件带版本戳、命令文件靠内容比对——你怎么改都会被判定为漂移并覆盖。你自己的规矩请写进
config.yaml。
16排错:六个真会遇到的问题
每一条都来自官方 troubleshooting 文档,顺序按"最快能检查"排。
1 · 敲了 /opsx:propose,什么都没发生
按代价从低到高排查,官方给的就是这个顺序:
- 你可能敲错地方了。斜杠命令在 AI 聊天框里,不在终端。如果在 shell 里敲的,这就是原因。
- 重新生成文件。在项目根目录跑
openspec update,它会重写你配置过的每个工具的 skill/命令文件。 - 重启你的助手。多数工具只在启动时扫描技能和命令,开个新窗口往往就好了。
- 确认文件真的存在。比如 Claude Code 下看
.claude/skills/里有没有openspec-*目录。 - 确认你初始化的是这个项目。技能是按项目写的;换了目录或 clone 了新仓库,就要在那个目录里跑一次
openspec init或openspec update。 - 确认你的工具支持命令文件。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 Issues | github.com/Fission-AI/OpenSpec/issues |
| 直接在终端提 | openspec feedback "你遇到的问题"——它会替你开一个 issue |
官方请求附带的信息:OpenSpec 版本(openspec --version)、Node 版本(node --version)、你用的 AI 工具、以及完整命令和完整输出。
97它和别的方案差在哪
市面上"管 AI 写代码"的东西大致分三类。官方 README 直接点名对比了两个同行,下面是加上了"什么都不用"这一栏的完整对照。
| 维度 | OpenSpec | Spec 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 …)
| 我要… | 敲… |
|---|---|
| 安装 CLI | npm install -g @fission-ai/openspec@latest |
| 在项目里初始化 | openspec init(非交互:openspec init --tools claude,cursor) |
| 升级后刷新 AI 指令文件 | openspec update(先升级包再跑它) |
| 看有哪些进行中的 change | openspec list |
| 看项目已覆盖哪些规格 | openspec list --specs |
| 看某个 change 的工件进度 | openspec status --change "<name>" |
| 读某个 change / 规格的详细内容 | openspec show <name> / openspec show <id> --type spec |
| 打开交互式看板 | openspec view |
| 校验一个 change | openspec validate <name> |
| CI 里校验全部(严格) | openspec validate --all --strict |
| 查已归档的 change 有没有漏勾的任务 | openspec validate --archived |
在终端归档(agent / CI 必须带 --yes) | openspec archive <name> --yes |
| 看有哪些 schema | openspec schemas |
| 切档位 / 投递方式 | openspec config profile 然后 openspec update |
| 关掉匿名遥测 | openspec config set telemetry.enabled false |
| 提反馈(会自动开 issue) | openspec feedback "…" |
聊天框命令(/opsx:…)
| 我要… | 敲… | 档位 |
|---|---|---|
| 想法还很模糊,先聊透(不写文件) | /opsx:explore | core(默认) |
| 立项并一次性生成全套图纸 | /opsx:propose <change-name> | core |
| 照图施工 | /opsx:apply [<change-name>] | core |
| 只改图纸、不动代码 | /opsx:update [<change-name>] + 说明你要改什么 | core |
| 提前把 delta 合进主规格(不归档) | /opsx:sync | core |
| 验收归档 | /opsx:archive | core |
| 先搭空架子,再逐个生成工件 | /opsx:new 然后 /opsx:continue | expanded |
| 一次把图纸全部生成 | /opsx:ff [<change-name>] | expanded |
| 验收"实现 vs 图纸" | /opsx:verify | expanded |
| 批量归档 | /opsx:bulk-archive | expanded |
| 被手把手带一遍 | /opsx:onboard | expanded |
配置文件要点
# 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参考来源与证据边界
一手来源(全部联网读取)
- npm 包与版本:
registry.npmjs.org/@fission-ai/openspec—— 本文校对时刻latest= 1.13.0(发布于 2026-09-09),engines.node=>=20.19.0;过去一月下载量 1,768,196(npm downloads API)。 - 官方仓库 README:github.com/Fission-AI/OpenSpec(本文读取的是随 1.13.0 包一起发布的 README 全文)—— 五条设计哲学、深色模式走查、安装与升级、Stores beta、模型与上下文卫生建议、与 Spec Kit / Kiro 的对比措辞。
- 官方文档(main 分支,逐个抓原文核对):
docs/cli.md(CLI 全量命令与参数)、docs/commands.md(斜杠命令参考)、docs/getting-started.md(目录结构、delta 格式、归档行为)、docs/how-commands-work.md(两个半场)、docs/overview.md与docs/concepts.md(五个核心概念)、docs/writing-specs.md(好需求与好场景的判据、RFC 2119 关键词、retire 规则)、docs/customization.md(config.yaml 全字段、schema、社区 schema)、docs/troubleshooting.md(排错条目)、docs/faq.md、docs/glossary.md、docs/examples.md、docs/workflows.md、docs/explore.md、docs/stores-beta/user-guide.md。 - 随包发布的 schema 定义与模板:
schemas/spec-driven/schema.yaml、templates/{proposal,spec,design,tasks}.md—— 本文里#### Scenario:必须四个井号、"每条需求至少一个场景"、## Purpose只给新能力写、MODIFIED 必须带全场景这些规则,都是从这份定义里读出来的。 - GitHub API:仓库 stars 68,077、forks 4,675、许可证 MIT、最近推送 2026-09-11(
api.github.com/repos/Fission-AI/OpenSpec)。
本文自己做的核对
- 版本锚点:旧文锚在 v1.12.0,本文锚在 v1.13.0——直接查 npm registry 的
dist-tags.latest与发布时间,不靠记忆。 - 把"命令现状"逐条对到官方原文:旧文里出现过的每条命令(install / init / update / propose / explore / apply / update / archive / verify / sync / new / continue / ff / bulk-archive / onboard / status / schemas / schema fork / schema validate / config set telemetry.enabled)都在 1.13.0 的
docs/cli.md或docs/commands.md里找到了对应物;对不上的两条见下文"改掉的旧版事实"。 - 数字口径:stars 和月下载量都标了"本文校对时刻",因为这类数字每天都在动。
证据边界与时效
- 版本口径:本文校对于 OpenSpec @ v1.13.0(2026-09-09 发布),读取的官方文档是仓库
main分支在校对时刻的内容。工具迭代很快,命令集、profile 组成、Stores 的状态都可能变——这也是它标evolving的原因。 - 我没有做的事:没有真的在一个项目里跑完
openspec init之后的完整闭环(本次核对以官方文档 + 包内 schema/模板 + registry 元数据为准);没有逐个验证 30+ 个 AI 助手各自的命令拼写(表里写的是官方文档明确给出的几个例子);没有评测/opsx:verify在真实代码库上的准确率;没有覆盖多语言、迁移指南、社区 schema 目录的全文。 - 一处口径提醒:官方 README 与官方 FAQ 都推荐"高推理模型"并点名了具体型号与版本号。本文只转述"推荐用强推理模型做规划和施工"这个方向,不把具体版本号当作长期有效的建议——模型版本更替比文档快得多,请以官方 README 当时的内容为准。同理,"官方支持 30+ 工具"这个数字也在持续增长。
- 术语对照提醒:
context在 CLI 里是一条命令(装配工作集),在config.yaml里是一个字段(注入给 AI 的项目背景),官方自己在 CLI 文档里点名了这个歧义。本文两处都按各自语境使用,读到时注意区分。