💡这两年用 AI 编程助手写代码,大多数人都有过一个同样的体验:能力强,但不稳定。同一个重构需求,你在 Claude Code 里讲了三遍它才做对;换个会话、换个工具,又得从第一遍开始讲。
需求这件事最后长在了聊天记录里。上周你花四十分钟对齐的边界条件,这周上下文一压缩就没了;两个人各自开一个会话,改出来两套行为;等到 Review 的时候才发现,AI 理解的功能和你说的功能,从一开始就差了一格。
2026 年市面上出现了一批专门解决这件事的工具,口径都叫 Spec-Driven Development(规格驱动开发):先把「要做成什么样」写成仓库里能被机器校验的文件,人和 AI 在这份文件上达成一致,然后才允许动代码。GitHub 官方那份 Spec Kit 星数已经到 14.5 万,而我要写的这个 OpenSpec 走的是另一条路——它不要 Python 环境、不要阶段闸门,装上就是一个 npm 包。
所以这一篇就按我自己跑通的顺序来讲:这个叫 OpenSpec 的包到底往你仓库里写了些什么、一条变更从提案到归档怎么走完、规格文件必须写成什么样才不会被静默忽略,以及它和 Spec Kit、Kiro 相比适合哪种团队——用的是 1.16.0,命令输出全部本机实测。
1. 它补的是哪一段:不是让 AI 更聪明,是让需求有地方住
先把定位钉住,不然后面对比全是虚的。OpenSpec 是一个 TypeScript 写的命令行工具加一套文件约定,MIT 许可,npm 包名@fission-ai/openspec。它自己不接任何大模型,也不替你写代码——它做的事情只有一件:把"要做什么"从聊天记录搬进仓库,并且能校验这份描述写没写对。
没有规格层: 想法 --> 提示词 --> AI 直接改代码 --> 行为不符 --> 回滚/重讲 --> 再试 ↑ 需求只在这一格里,会话结束就蒸发 有规格层: 想法 --> proposal + specs + design + tasks --> 人审 --> 逐 task 实现 --> 归档并合并进主规格 ↑ 需求落在文件里,能 review、能校验、能留给下一个会话一句个人判断:这一层的价值不在于文档写得漂亮,而在于它把"确认"这个动作从代码阶段提前到了文本阶段。你在十行需求上叫停,比在三百行 diff 上叫停便宜得多。
Q1:这不就是让 AI 先写一份设计文档吗?
区别有两个,都很具体。第一,它不是自由散文,是有结构的断言:### Requirement:后面跟 SHALL/MUST,#### Scenario:后面跟 WHEN/THEN,openspec validate会去解析这些标记,写错了会报错(第 4 节有实测报错原文)。第二,它不是"当前系统长什么样"的全量文档,而是增量——每次变更只描述这次要 ADDED / MODIFIED / REMOVED / RENAMED 哪些需求,归档时再由 CLI 合并回主规格。
Q2:那它和 Cursor 规则文件、AGENTS.md 有什么区别?
那些是常驻上下文,描述的是这个项目长期的口味和约束(用哪个包管理器、目录怎么分层、禁止改哪些文件)。OpenSpec 管的是一次性变更:这个功能要新增什么行为、验收标准是什么、拆成哪几个 task。两者不冲突,init的时候甚至可以同时用——规则文件负责"怎么写代码",规格负责"这次写成什么样算对"。
Q3:为什么后端同学值得花这个时间?
我把它当成一个流程约束来看。做过的都清楚:需求歧义最早暴露的时机是评审,最贵的时机是线上。规格文件等于给评审提供了一个强制停靠点,而且这个停靠点是纯文本,可以直接进 PR、进 diff、进 git 历史,不需要额外系统。
2. 装起来:openspec init到底往仓库里写了什么
官方给的入口有五条:macOS/Linux 的一键脚本、Windows 的 PowerShell 一行、npm 全局装、Homebrew formula,以及 pnpm / yarn / bun / Nix。我走的是 npm 这条路。
npminstall-g@fission-ai/openspec@latestcdyour-project openspec init版本门槛这条必须单独提醒:1.16.0 的package.json里engines写的是node >= 22.12.0。也就是说 Node 20 那批环境这次会直接被拦(Node 20 已经在 2026-04-30 结束维护)。如果 CI 镜像里还锁着旧 Node,这一版升上去会先在安装步骤炸。
跑完之后我find了一遍目录,实际落盘的东西比宣传里说的少,也比我预期的多——少的是那些常驻说明文件,多的是每个工具一套的 skills 和 commands:
openspec/ ├── config.yaml # schema: spec-driven,外加 context / rules / operations 三段可选项 ├── specs/ # 主规格库,归档时由 CLI 写进来 └── changes/ └── archive/ # 已完成的变更,按日期前缀躺在这儿 .claude/ ├── commands/opsx/ # 6 个 md:explore propose apply update sync archive └── skills/openspec-*/ # 同名 6 个 SKILL.md .agents/skills/openspec-*/ # 通用落位,给没有专用适配器的工具用这里有个坑值得记:v1.0.0(官方叫 The OPSX Release,2026-01-26)之后,init不再生成CLAUDE.md、.cursorrules、AGENTS.md,也不再有openspec/project.md——那批文件在升级时被明确降级成 legacy。老仓库从 0.x 升上来必须重跑init或update,否则你以为 AI 在读项目说明,其实那份文件早就不是它读的形态了。
关于支持面,openspec init --tools会打印完整白名单。我本机 1.16.0 数出来是 50 个候选项,其中一个是agents(通用落位,不指定工具时的兜底),也就是 49 个具体工具。清单里除了 Claude Code、Cursor、Codex、Gemini CLI、GitHub Copilot、Windsurf(已改名 devin)、Cline、RooCode、Kiro 这些常客,qoder、trae、lingma、qwen、kimi、iflow、codebuddy、minimax-code这些国内在用的工具也都在列,可以--tools qoder,claude这样非交互一次配好。
同一个命令在不同工具里的拼写不一样,这一条很容易踩:
| 工具 | /opsx:propose的实际形态 | 落位文件 |
|---|---|---|
| Claude Code | /opsx:propose | .claude/commands/opsx/propose.md+ 同名 SKILL.md |
| Cursor / GitHub Copilot | /opsx-propose(连字符) | Copilot 是.github/prompts/opsx-<id>.prompt.md |
| Amazon Q | @opsx-propose | 按其 skills 目录 |
| Codex | $openspec-propose | 只有 skills,没有 command |
| 其他 / 通用 | /openspec-propose | .agents/skills/openspec-* |
Codex 那一行是我本机 init 时它自己打印出来的:Commands skipped for: codex (uses skills)。官方的口径已经在往 skills 一侧倾斜,commands 属于会逐步退役的形态——这点和前面那个"不再生成 CLAUDE.md"是同一个方向。
对中文团队最实用的一档:init --language zh。它不会把结构翻译一遍,而是往openspec/config.yaml里写一段 context:
context:|Language: zh All artifacts must be written in zh. Keep OpenSpec structural headings and SHALL/MUST keywords in English.也就是说 proposal、design、tasks 的正文会是中文,但### Requirement:、#### Scenario:、SHALL / WHEN / THEN 这些被解析器依赖的标记保持英文。我觉得这个取舍是对的:翻译标记会让校验和跨工具复用一起坏掉,翻译叙述则是纯收益。
3. 一轮完整闭环:从提案到归档,每步机器在做什么
这一节全部是我本机跑出来的真实输出,改动是那个add-dark-mode。默认档(core profile)实际给了六个命令,比 README 演示的四个多了update和sync:explore、propose、apply、update、sync、archive。
/opsx:explore --> /opsx:propose <name> --> /opsx:apply --> /opsx:archive 只读代码 写四个规划文件 逐 task 落地 delta 合并进主规格 不写任何东西 仍然不碰业务代码 只按 tasks 勾 变更目录进 archive先说explore这一档。它是唯一一个我建议在动手前都跑一遍的命令:不带任何写入,纯读代码 + 讨论方案。需求本身还没想清楚的时候,直接propose只会让 AI 生成一份看起来很完整、实际站不住的提案。
propose的边界值得单独念一句。我把它生成的.claude/commands/opsx/propose.md读了,里面有一段规划边界的硬约束:这条工作流只产出规划文件,不许编辑项目代码;即使你的原始请求里写着"顺便修一下",它也必须写完提案就停下,等你另起一次请求再进入 apply。这条设计我认为是整个工具里最关键的一处克制——它保证了"审规格"这个动作不可能被"顺手改完"绕过。
CLI 只搭骨架,内容全是 AI 写的。我直接跑了openspec new change add-dark-mode,它只创建目录和一个元数据文件:
openspec/changes/add-dark-mode/.openspec.yaml schema: spec-driven created: 2026-11-02四个规划文件(proposal.md、specs/、design.md、tasks.md)由 AI 按模板生成,模板就在包里的schemas/spec-driven/templates/下。openspec status会告诉你依赖关系走到哪一步:
Progress: 0/4 artifacts complete [ ] proposal [-] specs (blocked by: proposal) [-] design (blocked by: proposal) [x] tasks (blocked by: specs, design)四个文件各管一段,我把实测到的分工整理成一张表——最后一列是我实际用下来认为能不能省的判断:
| 文件 | 装什么 | 谁写 | 能不能省 |
|---|---|---|---|
proposal.md | Why / What Changes /Capabilities/ Impact | AI 起草,你审 | 不能,Capabilities 是它和 specs 阶段的契约 |
specs/<capability>/spec.md | 这次的行为增量:Requirement + Scenario | AI 起草,你审 | 不能(除非显式声明不改行为) |
design.md | Context / Goals 与 Non-Goals / Decisions / Risks | AI | 可以省,我实测只交三个文件也能归档 |
tasks.md | 分组复选框,实现进度全打在勾上 | AI 起草,apply 时逐项勾 | 不能,apply 的可验证性全靠它 |
tasks.md的形态就是一串复选框:
## 1. 主题基建 - [ ] 1.1 定义 CSS 变量 - [ ] 1.2 新增 ThemeContext 提供者archive是这套设计里唯一一个有真实写入动作的命令,也是最需要理解的一步。它会把这次 spec 目录里的 delta 合并进主规格库,然后把整个变更目录搬进changes/archive/,日期做前缀。我实测的输出:
Specs to update: theming: create Applying changes to openspec/specs/theming/spec.md: + 1 added Totals: + 1, ~ 0, - 0, → 0 Specs updated successfully. Change 'add-dark-mode' archived as '2026-11-02-add-dark-mode'.也就是说,openspec/specs/那个目录不是让你手写的,它是归档动作的产物——这一层认知很重要,很多第一次用的人会一上来就在 specs/ 里铺一堆文档,然后发现变更流程根本不认它。
4. 规格文件怎么写才不被静默忽略
这一节是踩坑密度最高的地方。OpenSpec 的解析器对格式很敏感,而它的报错信息不会主动告诉你"哪里像是对的但实际错了"。
最小合法形态长这样,我原样填进仓库跑通了校验:
## ADDED Requirements ### 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四个格式要求,每一条我都实测过反例:
#### Scenario:必须是四个#。写成三个井号、或者写成 bullet 列表,这条场景不会被识别——而且是静默不识别,校验只报"没找到 delta",不会说"你那个场景层级不对"。这是我见过最容易浪费时间的一个点。- 每个 Requirement 至少挂一个 Scenario。光有一句 SHALL 不算需求,只是断言。
- 规范动词只用 SHALL / MUST,别用 should / may,官方文档明确建议避开这两个词,因为它们在校验语义里是可选的。
- 新能力要写
## Purpose,已有能力不要写。Purpose 少于 50 字符时validate不报错,但归档会给你一句 warning,而validate --strict会直接判不合格——这个差异我在实测里两个都撞到了。
一个变更必须至少声明一个 capability(新增或修改),否则validate直接拦。我把骨架建好但还没写 spec 的时候,报错原文是:
✗ change/add-dark-mode ✗ [ERROR] file: Change must have at least one delta. No deltas found. Ensure your change has a specs/ directory with capability folders (e.g. specs/http-server/spec.md) containing .md files that use delta headers (## ADDED/MODIFIED/REMOVED/RENAMED Requirements) and that each requirement includes at least one "#### Scenario:" block. Totals: 0 passed, 1 failed (1 items)这条报错我读完的第一反应是:它把该写的目录名、该用的 delta 标记、该有几个场景全说了。写错格式的时候别跳过它,它比文档好用。
四种 delta 标记的约束不一样重,这一列值得贴在脑子里:
| 标记 | 用法要求 | 写错的后果 |
|---|---|---|
## ADDED Requirements | 全新行为 | 最常见的起手 |
## MODIFIED Requirements | 要把整块需求复制过来再改 | 只写差异,合并后会丢上下文 |
## REMOVED Requirements | 必须额外写 Reason 与 Migration | 光删一行,归档后没人知道为什么 |
## RENAMED Requirements | 成对写FROM:/TO: | 只改新名,旧引用不跟着动 |
Q1:纯重构、改 CI、补文档这类不动行为的变更怎么办?
它们确实不该产生 delta,但也不能绕过校验。两个官方出口:在这个变更的.openspec.yaml里写skip_specs: true,或者归档时加--skip-specs。前面那条报错原文里就顺手给了这个提示。
Q2:capability 的名字有什么讲究?
官方在 proposal 模板里反复强调命名要落在持久的系统行为上(例如user-auth),而不是这次的任务名(例如add-login-endpoint),并且要 kebab-case、避免大而全的兜底名字。它甚至明确写了动笔前先跑openspec list --specs查一遍已有能力清单,再openspec show "<spec-id>" --type spec --json --no-scenarios看相近的那几个,能复用路径就别新造一个近义名。这一条是我觉得它比同类工具成熟的地方:它默认了规格库会长期膨胀,并给出了抑制重复的手段。
5. 命令面板与档位:什么时候需要customprofile
CLI 子命令比我预期多。我把openspec --help里出现的全部分了类,日常用得上的其实只有前面几个:
| 分组 | 命令 | 我什么时候会真的敲 |
|---|---|---|
| 安装维护 | initupdateinstallversion | update每次换版本都要在各仓库跑一次,它刷的是各工具目录里的指令文件 |
| 看内容 | listshowview | list --specs查能力清单;view起一个交互式面板,规格一多比翻文件快 |
| 校验诊断 | validatestatusdoctorcontext | validate --all适合进 pre-commit;status --change <name>看四个文件走到哪 |
| 变更动作 | newarchiveinstructionstemplatesschemasschema | instructions/templates是给 AI 或自己查模板的,很少手敲 |
| 全局与实验 | configstoreworksetfeedbackcompletion | store和schema都还挂着 beta/experimental,别急着上生产 |
另外两个老命令change和spec已经废弃(--help里还挂着,但文档不再介绍),网上不少早期教程还写着openspec change show,照抄会踩空。
档位这块的逻辑:openspec config profile在 core(默认 6 个)和 custom 之间切。扩展的 6 个是new、continue、ff、verify、bulk-archive、onboard;切换是两步——先在全局配置里选档,再回到每个仓库执行openspec update才落到文件上。只改全局不跑 update,是这个流程里最容易漏的半步。
| 使用场景 | 建议档位 |
|---|---|
| 一个人写功能,只想要"提案 → 实现 → 归档" | core 就够 |
| 想把一次会话切成多步、中途反复补 artifact | 加new、continue |
| 需要"验收完再归档"的门禁,或者一次批量归档历史变更 | 加verify、bulk-archive |
| 存量项目第一次接,想让 AI 自己把现有行为反推成规格 | 加onboard |
Stores 是唯一一个我认为要谨慎对待的能力。它的定位是把规划放进一个独立仓库,让跨三个代码库的功能共享一份规格,团队里平台组持有、业务组只读引用。方向我很喜欢——后端做跨服务需求时最痛的就是规划散落。但官方自己在 README 里标了 beta,而且它把整个校验上下文从"当前仓库"挪到了"注册过的 store",--store <id>这个参数在十几条命令上都要保持传递,一旦忘记就回到本地根目录。我的做法是:先把单仓库那套跑顺,跨仓库真出现冲突需求时再上 store。
顺手记两个和合规相关的点:CLI 默认会上报匿名使用统计(只采集命令名和版本),三种关闭方式任选其一即可——openspec config set telemetry.enabled false,或者环境变量OPENSPEC_TELEMETRY=0/DO_NOT_TRACK=1,CI 环境里自动关闭;公司内网环境我建议直接默认关掉再开始用。
6. 和 Spec Kit、Kiro 摆在一起,差异到底在哪
这三个东西经常出现在同一个搜索结果里,但它们不是同一层的竞品。OpenSpec 官方 README 里就写了这两条对比,我把它加上实测后的判断重新组织一遍。
| 维度 | OpenSpec | Spec Kit(GitHub) | Kiro(AWS) |
|---|---|---|---|
| 形态 | npm 包 + 文件约定,挂在你现有的 CLI 工具里 | Python CLI + 一堆 prompt 模板 | 独立 IDE,另有 CLI / Web / Mobile |
| 流程刚性 | 无阶段闸门,artifact 随时可改 | 阶段闸门明确,走完一阶段才进下一段 | 规格与任务由 IDE 面板驱动 |
| 模型绑定 | 不绑,跟宿主工具走 | 不绑 | 不再只限 Claude 一家,也含 GPT 系列与 open-weight |
| 上手成本 | 一次init,Node 22+ | 要装 Python 环境和uv | 要迁移编辑器 |
| 代价与边界 | 规格质量取决于模型;格式敏感 | 模板 Markdown 体量大,改起来有仪式感 | 换 IDE 的成本与生态绑定 |
| 适合 | 已有习惯用的 CLI/IDE,想加一层规格 | 需要完整流程约束的团队 | 想整套换掉开发环境的团队 |
这里有一处官方口径已经过时,值得写出来:OpenSpec 的 README 里那句 “limited to Claude models” 描述的是早期 Kiro,而 2026-11-02 的 Kiro 已经是多模型形态并且有独立 CLI。这类对比句子放在营销文案里很常见,抄教程的时候最好回官网核一次。
至于热度这个维度:GitHub API 上 OpenSpec 是 73,669 star / 5,042 fork,Spec Kit 是 145,181 star(均为 2026-11-02 取值)。星数差一倍,我倾向于解读为发布时间差与背后主体差(Spec Kit 有 GitHub 官方渠道,OpenSpec 是 Fission 这个两人主力维护的小团队,npm 首版比对方晚),而不是能力优劣——这一点下面第 7 节还会回到边界上来讲。
Q:那和"我直接在 Claude Code 里用 plan 模式"比呢?
Plan 模式解决的是"这一轮先想清楚再动手",会话结束就蒸发,也不会被第二个工具读到。OpenSpec 多做的是把这轮的思考变成仓库里的版本化文件,还给了个校验器。如果你从来不打算留痕,也不需要跨会话、跨人接力,那 plan 模式确实更省事——这不是同一层的需求。
7. 什么项目我会用,什么项目我不会
说点我自己的取舍。写这篇之前我已经把它接进了两个 Java 后端仓库和一个个人项目,日常用 Claude Code 与 Qoder 两个入口,所以下面这段是使用者视角,不是评测视角。
笔者(后端 & 架构)的用法策略:
| 场景 | 我的做法 | 原因 |
|---|---|---|
| 存量系统加新模块 | 用,proposal + specs 一次走到底 | 存量最怕"AI 改了不该改的",规划边界帮我把这一步卡住 |
| 跨端改动(后端 + 前端 + 公共库) | 先 explore 定能力名,再拆多个 change | 一个 change 覆盖三端会把 tasks 写成一大坨,勾不动 |
| 一句话能改完的小修 | 不用 | 走一遍提案比代码本身还长 |
| 探索性原型、方向未定 | 只用 explore,或者干脆不用 | 需求还在变的阶段,写规格是给未来的自己埋返工 |
| 团队没有 PR review 习惯 | 先别上 | 这套的价值全在"审规格"那一步;没人审的话它只是多了四个 md |
| 有对外承诺的接口/权限行为 | 用,而且把 spec 文件当验收标准 | WHEN/THEN 天然可以对着测 |
我认为值得写下来的三条边界,都算实际踩到:
- 规格本身会腐化。
openspec/specs/里的内容不会因为代码改了而自动跟着变。归档是单向合并,不做一致性维护。它把需求记住了,但不保证记住的是对的东西——所以主规格库仍需定期人工审,别把它当真理源。 - 它确实"就是一些 Markdown 加 skills"。2026-09-16 那天 Hacker News 上的讨论(204 分 / 100 条评论)最集中的一条质疑就是:既然核心是文件约定,为什么要装一个 CLI。我的看法偏正面:CLI 提供的四件事——delta 解析、
--strict校验、归档合并、按 49 个工具分发指令文件——纯手写 md 都要自己补,尤其是同一份约定要在 Cursor、Claude Code、Copilot 里都长得一样,靠人工维持不现实。但如果你只用一个工具、并且团队都能遵守格式,那把 CLI 当"可选校验器"而不是"必需品",是个合理判断。 - 对模型的推理能力有要求。官方 Usage Notes 明确建议在规划与实现都用高推理模型,并且提醒换阶段前清一次上下文。这条不是客套——我实测过在长会话尾巴上让它写 MODIFIED 的整块需求,它会偷懒只写差异,校验通过但合并后语义残缺。这种失误只能靠换强模型或人工审 catch。
还有一个纯粹的小别扭:archive/不会自动清理,日积月累变更目录会一直堆在那;openspec view那个 dashboard 能缓解阅读压力,但本质上是把归档仓库当历史账本存。想让它长期可维护,自己定一条归档整理规则比较现实。
最后总结
- 如果你的痛点是"需求每次都要向 AI 重新讲一遍":OpenSpec 补的正是这一段——需求落到仓库里的结构化文件,能被校验、能跨会话、能进 PR。
- 如果你已经在用 Cursor / Claude Code / Qoder / Copilot 中的任何一个:一次
openspec init --tools <你的工具>就够了,不用换编辑器、不用换模型,也不用配 Python 环境。 - 如果是国内团队:记得加
--language zh,正文中文、结构标记英文;顺手把遥测关掉。 - 如果只是想试小改动或写原型:先只用
/opsx:explore,别急着把变更全流程走完。 - 对于后端 / 架构开发者,我个人最看重两点:
propose的规划边界(写完就停、不许碰代码),和archive那一步把行为增量合并回主规格的机制——前者把评审提前,后者让"系统现在应该是什么样"有一份可查的东西。
参考资料 & 致谢
- OpenSpec GitHub 仓库 Fission-AI / OpenSpec - README(Quick Start 安装方式、
/opsx:*工作流演示、与 Spec Kit 与 Kiro 的官方对比、Stores beta 说明、遥测与关闭方式,核实时间 2026-11-02) - OpenSpec npm 包
@fission-ai/openspec注册表元数据(latest 1.16.0 发布于 2026-10-30、MIT、engines.node >= 22.12.0、首次发布 2025-09-06、累计 56 个版本) - OpenSpec 1.16.0 npm 包解包后的 CLI 与模板(
--help全文、schemas/spec-driven/templates/四份模板、schema.yaml里 proposal 的写作指令,本机解压逐条读取) - OpenSpec 官方文档 - Quickstart / Set up your project / CLI / Profiles / Supported Tools / Skills 页(init 落盘内容、core 与 custom 档位、44 个工具口径、各工具命令拼写差异)
- OpenSpec 官方文档 - spec-driven schema 页(Requirement 与 Scenario 的关键词约束、delta 四种标记的写法要求、Purpose 50 字符下限)
- GitHub API - repos/Fission-AI/OpenSpec 与 repos/github/spec-kit(两仓 star 与 fork 数、最近 release 与 push 时间,取值时间 2026-11-02)
- OpenSpec Releases 页 - v1.0.0 The OPSX Release 与 v1.16.0 两条 notes(命令改名破坏性变更、不再生成 CLAUDE.md 与 project.md、Node 22 门槛)
- Hacker News 讨论帖 49734264(2026-09-16,204 分 / 100 条评论,"只是一堆 md 加 skills"这条质疑的出处)
- Kiro 官网 - 首页与产品页(当前形态为 IDE + CLI + Web + Mobile,模型不再只限 Claude 一家)