我让 AI 加个暗黑模式,它一口气吐了 400 行。翻完才发现:引了新依赖、没接系统偏好、也没存本地。返工比写还累。问题不在模型,在于那句指令飘在聊天框里,写完就散了。OpenSpec 想治的就是这个:动代码之前,先把"到底要做什么"落成一页人能读、能改的文档。
它是 Fission-AI 开源的 spec-driven development(规范驱动开发)工具,MIT 协议。纯 Markdown 文件,跟着 git 走,不绑任何 IDE,Claude Code、Cursor、Copilot、Codex 这些都能接,官方说支持 30+ 种助手。
核心模型:两个文件夹
整个工具就两个目录,搞懂这两个就够了:
openspec/specs/(真相):记系统"现在"长什么样,用 requirement(系统 SHALL 怎样)加 scenario(WHEN/THEN 例子)描述,按业务域分目录,比如auth/、ui/、payments/。openspec/changes/(提案):要改什么,就在这下面建个文件夹,把这次相关的东西全放进去。
你不用重写整份 spec,只写"这次动了哪几条":新增写 ADDED、改了写 MODIFIED、删掉写 REMOVED。这恰恰是它能塞进 5 万行老项目的原因——你描述的是 diff,不是终点。
## ADDED Requirements ### Requirement: 主题切换 系统 SHALL 允许用户在浅色和深色主题之间切换,默认跟随系统偏好。 #### Scenario: 用户开启暗黑模式 - **WHEN** 用户点击主题切换按钮 - **THEN** 应用切换到暗黑模式并持久化该选择
上面这段就是 AI 起草、你来审的计划,代码一行没动。
日常循环:四个命令
默认配置下,每天就这四个斜杠命令,打在 AI 聊天框里:
/opsx:explore → (可选)还拿不准,先跟 AI 聊清楚方案
/opsx:propose add-dark-mode → AI 起草 proposal / specs / design / tasks
(你读一遍计划,不对就改)
/opsx:apply → AI 按 tasks.md 逐条实现
/opsx:archive → 规格更新,改动归档
explore 是个零风险的思考搭档:它读你的代码、摆选项、把含糊的想法收敛成具体方案,然后你再决定要不要进 propose。想清楚了就直接 propose,跳过它。
产物自下而上递进:proposal(为什么)→ specs(改什么)→ design(怎么做)→ tasks(步骤清单)→ implement。但顺序只是给 AI 喂上下文,没有强制关卡。实现时发觉设计不对?改 design.md 接着跑。范围要缩?改 proposal。什么都不锁死。
archive 只干一件事:把 change 里的 delta 并回主 specs,文件夹挪到 changes/archive/2026-09-08-xxx/。真相刷新,进入下一轮。
装好之后怎么跑
要求 Node.js 20.19.0 以上。全局装:
npm install -g @fission-ai/openspec@latest
进项目初始化:
cd your-project openspec init
init 会按你选的 AI 工具,打出对应的 /opsx 命令写法。前缀因工具而异:/opsx:propose(Claude Code)、/opsx-propose(Cursor、Copilot)、$openspec-propose(Codex)。
升级和刷新:
npm install -g @fission-ai/openspec@latest # 升 CLI openspec update # 进项目刷 AI 指令和命令 openspec config set telemetry.enabled false # 关遥测(可选)
把生成的 spec 改成中文
默认 OpenSpec 吐出来的 spec 全英文,但英文不是必须的。它内置多语言,简体中文是官方示例语言之一。默认英文只是因为 openspec init 没设语言、AI 又倾向写英文,不是硬规定。
新项目,初始化时直接指定:
openspec init --language "Chinese (Simplified)"
已初始化的项目(你的情况),别重跑 init——那会清掉已有的项目上下文。直接改项目里的 openspec/config.yaml,在 schema: spec-driven 下面加一段 context:
schema: spec-driven context: | 语言:中文(简体) 所有产出物必须用简体中文撰写。 技术性术语(API、REST、GraphQL 等)、代码与文件路径保持英文。 OpenSpec 结构性标题(Requirements / Requirement / Scenario / WHEN / THEN)与 SHALL/MUST 关键词保持英文,便于校验解析。
改完下次 /opsx:propose 生成的 proposal / specs / design / tasks 正文就全中文了。配置是生成时实时读取的,不用重跑 openspec init,也不用 openspec update。
唯一硬性约束:结构里那些关键词得留英文,包括 Requirements、Scenario、WHEN/THEN、SHALL/MUST,以及 delta 标记 ADDED/MODIFIED/REMOVED。校验工具靠这些词解析,翻成中文会让 openspec validate 和归档合并认不出。其余描述、理由、任务说明,随便用中文。
效果上没区别:中文 spec 一样能校验、归档、合并,AI 也照常按它实现。想确认配置吃没吃上:
openspec instructions proposal --change <随便一个change名>
输出里能看到 语言:中文(简体) 那段,就说明生效了。
一个完整例子
README 里的暗黑模式流程,完整跑一遍是这样的:
You: /opsx:explore
AI: What would you like to explore?
You: 我想加暗黑模式,但不确定怎么做得干净。
AI: 看了一下你的样式方案……最干净的路子:
CSS 变量 + 一个轻量主题 context,再做系统偏好检测,
不引入新依赖。要我按这个范围出计划吗?
You: 可以,就这么做。
You: /opsx:propose add-dark-mode
AI: Created openspec/changes/add-dark-mode/
✓ proposal.md — 为什么做、改什么
✓ specs/ — 需求与场景
✓ design.md — 技术方案
✓ tasks.md — 实现清单
Ready for implementation!
You: /opsx:apply
AI: Implementing tasks...
✓ 1.1 加主题 context provider
✓ 1.2 做切换组件
✓ 2.1 加 CSS 变量
✓ 2.2 接 localStorage
All tasks complete!
You: /opsx:archive
AI: Archived to openspec/changes/archive/2025-01-23-add-dark-mode/
Specs updated. Ready for the next feature.
跑完,仓库里多了一份"为什么这么做"的记录。半年后你或下一个 AI session 翻 spec,就能看懂这套主题系统当时的设计意图,不用去考古聊天记录。
什么时候该用,什么时候不值
OpenSpec 多一道工序:写代码前先写段计划。它实际解决的是这几件事:
- 在提案阶段改方向,代价几乎为零;写满 400 行之后再改,代价就高了。
- 计划和代码在同一仓库,需求文档不用漂到 wiki 上。
- 改动可审阅:一个 change 文件夹就是个整齐的包裹,读 proposal、扫 delta、查 tasks,一眼看全。
- 适配已有代码库:delta 机制让你能直接给老系统提改动,不用先把整个系统文档化。
也要诚实:一行 trivial 的小修复,走这套仪式不划算。它设计得轻,但终究不是零成本。原则就一句:在"对齐有价值"的地方用它;一旦你开始跟一个会自信地按模糊指令乱写的 AI 协作,大多数时候都该用。
和同类工具的区别
- vs Spec Kit(GitHub):更重、有刚性阶段门、文档多、要 Python。OpenSpec 更轻,能自由迭代。
- vs Kiro(AWS):能力强,但锁在自家 IDE、且只能用 Claude 模型。OpenSpec 用你已有的工具。
- vs 什么都不用:没有 spec 的 AI 编码 = 模糊提示 + 不可预测的结果。OpenSpec 把可预测性拿回来,又不添多少仪式感。
团队场景还有 Stores(beta):把规格单独放一个仓库,通过 git push 共享,跨多个代码仓保持一致的事实源:一个改动、一份计划,即便代码落在三个仓库里。个人项目暂时用不到,先不管也行。
一句话记住:先对齐规格、再写代码。explore 想清楚 → propose 出计划 → apply 去实现 → archive 归档。