我接触 OpenSpec 时,以为它就是几个命令加一些 Markdown。至少它早期给我留下的是这种印象。
然后我打开文档,看到了 profiles、schemas、artifacts、config 文件、archive 流程、OPSX,还有 delta specs。我花了比我想承认的更多的时间,在几个标签页之间来回切换,想把所有东西都装进脑子里。到底什么是 artifact?为什么 profiles 和 schemas 都存在?如果两者都影响工作流,为什么都需要存在?
这就是我当时希望看到的解释,而不是那些标签页。
OpenSpec 是什么?
OpenSpec 是一个 spec-driven 的开发框架。它和你的代码一起住在仓库里,能和大多数编程 agent 一起工作:Claude Code、Cursor、Codex、GitHub Copilot、OpenCode 等等。用 npm install -g @fission-ai/openspec@latest 安装,它就给你的 agent 加上了规划命令。
思路很简单。在写代码之前,先描述你想做的改动。OpenSpec 会生成一份提案、一份设计文档、一份任务拆解,以及一个 spec delta,显示需求将如何变化。你审阅这份计划,打磨它,然后再去实现。改动完成后,spec delta 会被应用到你的 canonical specs 上,这样仓库里的需求就保持最新了。
最后这一步是它和 agent 自带 plan 模式的区别。plan 模式在 chat session 结束时就没了。OpenSpec 的 specs 作为活文档留在仓库里,提交到 git,可以在 PR 里审阅。
项目开源在 openspec.dev。
简版
当我把 OpenSpec 归结为四个问题之后,它对我来说就变得容易多了:
| 概念 | 它回答的问题 |
|---|---|
| Profile | 我的 agent 可以用哪些工作流动作? |
| Schema | 存在哪些规划 artifact,以及什么依赖什么? |
| Config | 应该用哪些项目上下文和额外规则来塑造这些 artifact? |
| Skills | 我的 AI 工具如何执行每个工作流动作? |
Artifact 是这个系统产出的东西:提案、specs、设计、任务,或你的 schema 定义的其他任何东西。
为什么这套术语感觉是分层的
当你看 OpenSpec 是怎么演化过来的,一些困惑就比较好理解了。
早期的工作流有意做得很小:
propose -> apply -> archive提案这一步生成规划文档,agent 实现改动,archive 把结果折回项目的 specs 里。
之后 OPSX 让系统更灵活了。规划变成了一组离散的 artifact,通过依赖关系连接。你可以增量地创建它们,边做边修改,并自定义这个图,而不是接受一个写死的过程。
这种灵活性带来了更多动作:
new -> continue or ff -> apply -> verify -> archiveOpenSpec 1.2 然后引入了 profiles。重点不是再加一层规划抽象。Profile 控制安装哪些工作流 skills 和命令,让想要短路径的人不需要在 agent 的上下文里塞进每一个扩展命令。
当前的 core profile 给你快路径:
explore -> propose -> apply -> sync -> archive扩展工作流在你想要更细控制时,暴露 new、continue、ff 和 verify 这些动作。
这段历史很重要。Profiles 和 schemas 看着像同一个想法的两代产品。其实不是,这种困惑是我浪费最多时间的地方。
Profiles vs. Schemas
这是我卡得最久的地方。我原以为 profiles 和 schemas 是两种相互竞争的、定义工作流的方式。
它们是正交的。
Profile 控制你可用的动作。Schema 控制这些动作所作用的规划结构。
这句话我在文档里读了三遍才理解,所以我这里要多花点篇幅。
Profile 选择控制项
Profile 不定义 proposal.md、design.md 或 tasks.md。它决定 OpenSpec 给你的 AI 工具安装哪些工作流动作。
用 core profile 时,/opsx:propose 给你简单的体验:描述改动,一次性生成所有规划 artifact。
选择扩展后,你可以更有意识地操作:
/opsx:new创建改动的脚手架。/opsx:continue创建下一个可用的 artifact。/opsx:ff创建所有能生成的规划 artifact。/opsx:verify在 archive 之前把实现和 artifact 进行对比。
所以我最初的简略说法接近正确,但不够准确。Profile 不说"全部生成"或"只生成一个"。Profile 让这些动作可用;你选哪个命令决定接下来发生什么。
Schema 定义规划图
Schema 回答另一个问题:这个改动应该包含什么?
默认的 spec-driven schema 包含提案、specs、设计和任务这些 artifact。它也描述它们的依赖。简化视图长这样:
proposal
/ \
specs design
\ /
tasks这个图就是为什么 /opsx:continue 能判断哪个 artifact 已经就绪,哪个还被阻塞。OpenSpec 检查磁盘上有什么,并遵循 schema 的依赖规则。
自定义 schema 可以加一个研究或安全评审的 artifact:
research -> proposal -> specs -> security-review -> tasksProfile 不需要改。同一个 continue 或 ff 动作可以遍历不同的 schema。
就在这一刻,profiles 和 schemas 在我脑子里终于分开了:profile 给你控制项;schema 给这些控制项提供作用对象。
OpenSpec 说的"Artifact"是什么意思
"Artifact"这个词让系统听起来比实际更抽象。
Artifact 是 schema 定义的产出。大多数是 Markdown 文件,或一组 Markdown 文件:
proposal.md
design.md
tasks.md
specs/<capability>/spec.md没有在后台运行的特殊的 artifact 对象。OpenSpec 主要从文件系统推断状态:如果需要的产出存在,这个 artifact 就完成了,它的依赖项可能就可用。
这个词还是重要的,因为 schema 可以定义不止一种文件形态。比如 specs artifact 可以生成一个 delta specs 目录,而不是一个固定文件。但作为用户,有用的翻译是:
Artifact = 一次改动过程中产出的规划物。
用熟悉的话讲 Proposal、Specs、Design 和 Tasks
用普通的项目语言来理解这些,对我来说容易得多:
| OpenSpec artifact | 熟悉的对应物 | 主要问题 |
|---|---|---|
| Proposal | 商业案例 | 我们为什么做这个,范围是什么? |
| Specs | 需求 | 系统必须做什么? |
| Design | 技术方案 | 我们要怎么建? |
| Tasks | 实现清单 | 还有哪些工作要完成? |
当我不再把这些当作 OpenSpec 专属的发明,工作流就感觉熟悉了。它们就是任何一个体面团队本来就会产出的文档,只不过这里的工具知道这些文档。
Main Specs vs. Delta Specs
有一个区别我有一阵子没注意到:OpenSpec 处理两种规格。
openspec/specs/ 下的 specs 描述系统现在是怎么运作的。它们是按能力组织的、权威的事实源。
一个改动内部的 specs 只描述这个改动添加、修改或删除的内容。那些是 delta specs。
openspec/specs/ current system
openspec/changes/add-2fa/specs/ proposed difference这就是为什么改动可以不重写整个规格就能被审阅。审阅者看到的是差异,不是另一份完整副本。
当改动被 sync 或 archive 时,这些 delta 会被应用到 canonical specs 上。添加的需求被追加,修改的需求替换之前版本,删除的需求被删除。
这就是 OpenSpec 说"把规格作为活文档保存"的意思。
config.yaml 实际上做什么
我原本以为 openspec/config.yaml 用来定义工作流。它不是。
它配置的是工作流周围的项目:
schema: spec-driven
context: |
Stack: TypeScript, React, PostgreSQL
Public APIs must remain backwards compatible
rules:
proposal:
- Include a rollback plan
tasks:
- Include tests for every requirement这个文件有三个主要工作:
- 选择默认的 schema。
- 把项目上下文注入到每个 artifact 的指令里。
- 按 ID 把额外规则注入到特定的 artifact。
它不添加新的 artifact,也不改变它们的依赖。那属于 schema 的事。
这个区别给了一条有用的经验法则:
- 如果你想改变存在哪些文件,改 schema。
- 如果你想改变生成的文件应该考虑什么,改 config。
Schemas vs. Skills
我接下来错在这里。我以为 schema 也是所有 agent 行为应该放的地方。
Schema 可以包含生成其 artifact 的模板和指令,但它们不替代 skills。
Schema 描述规划模型:artifact ID、输出路径、模板和依赖。生成的 OpenSpec skills 教 AI 工具如何执行 propose、continue、apply、sync 和 archive 这些动作。
所以如果我在任务之前想要一个新的 security-review.md,那是 schema 的改动。
如果我想让我的编程 agent 在实现时遵循 TDD,那属于实现 skill 或项目指令。如果我只是想让每个生成的任务清单提到测试,config.yaml 里的一条 tasks 规则可能就够了。
这些是相关的事,但它们在不同层,把它们混在一起是我大多数困惑的来源。
Archive 能防止文档过期吗?
这是我最后一个放不下的问题。
Archive 做两件有用的事:把完成的改动移到历史里,并确保 delta specs 能被同步到 canonical specs 里。这避免了把多份相互竞争的需求版本散落在活跃的改动文件夹里。
Archive 不做的是证明代码和规格匹配。
扩展的 /opsx:verify 动作检查实现和规划 artifact 之间的完整性、正确性和一致性。即便如此,这个过程仍然依赖评审和工程纪律。没有任何 archive 命令能让一个不准确的 spec 变成真的。
所以 OpenSpec 减少了一种文档漂移:被遗弃或相互竞争的需求文档。它本身并不弥合书面意图和实际软件之间的差距。那部分仍然在你。
终于在我脑子里成形的心智模型
这是我现在记在脑子里的版本:
Profile -> chooses the available workflow actions
Schema -> defines the artifact dependency graph
Config -> injects project context and artifact-specific rules
Skills -> teach the agent how to perform those actions
Files -> record the state of the change或者一句话:
OpenSpec 安装一组 agent 动作,在一个 schema 定义的图上运行它们,用项目 config 塑造它们的输出,并把进度作为文件记录在你的仓库里。
当我这样看的时候,profile、schema 和 artifact 这些词就不再相互竞争了。每一个都有清晰的边界。
OpenSpec 最难的部分不是命令数量。而是那些熟悉的词在系统内部带有非常具体的含义,文档又不总是把这些边界讲清楚。如果你卡在术语上,你不是一个人,我花了一阵子,这篇文章大部分就是我走到这里所走的路。
