开头
如果你最近在用 Cursor、Codex 这类 AI 编程工具,八成遇到过一种“无力感”:模型确实能写出像模像样的代码,但总在某些细节上跟你理解的不一样。你要的是“给用户提醒过期时间”,它给你封装了一个完整的定时器系统;你强调“不要动现有接口”,它还是会顺手把函数签名改掉。问题不在模型能力,而在于你给 AI 的“约束”太弱了——提示词里的要求是软性的,对话上下文也会被截断,真正的项目规约根本没传递到生成链路里。OpenSpec 这个规约框架,就是冲着这个问题来的。它是一个专门给 AI 代码生成场景设计的结构化规约管理工具,用一套文件级、可提交、可回滚、可验证的规格说明(Changeset)来约束 Agent 的行为边界,让“需求—设计—任务—实施”这条链路对模型完全可见、可循证。这篇内容我结合实际使用经验,把 OpenSpec 的设计思路、安装方式、和 Cursor/Codex 的配合方法,以及我踩过的坑,一次性讲透。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
1. 为什么需要 OpenSpec:AI 生成的代码缺的不是能力,是“边界”
1.1 AI 编码的真正瓶颈:上下文失控
很多人以为 AI 编程工具好不好用,取决于模型参数量大不大。真入行做了几个项目之后,你会发现更大的瓶颈是:Agent 对项目的理解是“一次性快照”式的。它基于你当前打开的若干文件、聊天记录里的对话历史、以及系统提示词来推断需求,而不是基于一份完整的、可追溯的项目规约。
拿我前段时间做的一个内部工具举例,需求很简单:在现有用户模块上增加一个“导出 CSV”的功能。我让 Cursor 自动实现,结果是模型自己“脑补”了权限控制、异步任务队列、日志上报,还顺手把原来的 API 返回结构改了。单看每一处改动都有道理,但合在一起就是一场灾难。这背后的本质是:自然语言提示词无法形成结构性约束。你说“尽量不改动现有逻辑”,模型理解成“保留函数名就行”,可它不知道哪些变量、字段、依赖关系是团队约定的红线。
1.2 从“提示词”到“可执行的规约”
OpenSpec 的思路是:把给 AI 的约束从“聊天里的几句话”变成“项目里的一组文件”。这组文件就是 Changeset(变更集),里面按固定规则写明:这次变更要解决什么问题、涉及哪些模块、必须保留哪些行为、验收标准是什么。Agent 在动手前先读这些文件,相当于拿着一张施工图去干活,而不是凭印象边猜边写。
这个思路并不新鲜——传统软件工程里的需求规格说明书、接口契约测试都是类似逻辑。但 OpenSpec 的厉害之处在于,它把这些规约做成了可以被 Agent 和命令行工具共同消费的格式:既能被 Cursor 这类 IDE 插件读取,也能被 Git Hook 和 CLI 在提交时校验。换句话说,规约不再是“写完就躺进 wiki 的文档”,而是参与了代码生成和审查流程的活体约束。
注意:OpenSpec 不是一个代码生成器,它不负责把需求翻译成代码。它负责的是“需求、设计与任务”结构化,让 AI 在生成代码时有一个明确且不可忽略的基准线。
1.3 适用场景与目标用户
如果你属于下面几类情况,OpenSpec 大概率适合你:
- 使用 AI 编码工具做多文件、跨模块功能开发,但经常被模型“跑偏”搞烦的开发者。
- 团队里 AI 生成代码的比例越来越高,需要一种机制来保证代码风格、接口设计和架构约束不被破坏。
- 做 AI Agent 相关项目,想给 Agent 设置一套可追踪、可回滚的“操作契约”。
反过来,如果你只是偶尔让 AI 补一段几十行的工具函数,OpenSpec 属于杀鸡用牛刀。它的价值在“多步骤、多文件、涉及既有代码改动”的场景里才真正体现。
2. OpenSpec 的核心设计:一切皆 Changeset
2.1 概念拆解:项目、变更集、规格、任务
OpenSpec 的操作对象可以拆成四个层级,理解了这四个词,整个框架就掌握了大半:
- 项目(Project):一个 Git 仓库就是一个项目,OpenSpec 在项目根目录下的
.openspec目录里存所有规约状态。 - 变更集(Changeset):一次功能开发或缺陷修复对应的结构化描述,它是一组文件的集合,放在
.openspec/changesets/<名称>/目录下。 - 规格(Specification):变更集里的
spec.md文件,用 Markdown 但带有固定的标题约定(比如 Requirements、Design、Tasks、Acceptance Criteria),规定了这次变更“做什么、为什么做、怎么做、做到什么算完”。 - 任务(Task):
tasks.md里拆解出来的具体实施步骤,可以对应到实现、测试、文档等操作。AI Agent 通常按这里列出来的顺序逐个执行。
这套结构和传统 Jira Ticket + 设计文档的模式很像,区别在于:OpenSpec 的规格文件是一种“机器可读的活动文件”,Agent 在每次编码前会主动读取它,而不是人在工具里手动弹个窗口提醒。
2.2 Changeset 的典型文件结构
我在一个实际项目里创建的 Changeset 长这样:
code复制.openspec/
└── changesets/
└── add-user-export/
├── spec.md
├── requirements.md
├── design.md
├── tasks.md
└── status.md
spec.md:变更集入口,写清目标和范围,相当于摘要。requirements.md:需求列表,每条需求带状态(Proposed / Accepted / Implemented / Verified),每条都要能追溯到验收。design.md:技术方案,比如涉及哪些文件、改了哪些接口、用了什么模式。tasks.md:Agent 要依次完成的具体任务,每个 Task 也带状态。status.md:当前整体状态,OpenSpec 的 CLI 工具会自动更新这个文件。
你甚至可以理解为:OpenSpec 是把“产品需求文档 + 技术设计文档 + 任务拆解清单”打包成一个 AI 可消费的目录结构。它最大的价值在于这些状态是主动更新的,不是写一次就封印在文件夹里吃灰。
2.3 两个核心功能:Board 视图与强制校验
OpenSpec 不只是文件格式,它提供了两种使用模式:
一是交互面板(Board)。在 Cursor 等编辑器里按 Ctrl+Shift+O(macOS 上是 Cmd+Shift+O),会打开一个 OpenSpec 控制面板,左侧显示当前的变更集列表,右侧显示规格内容、任务状态。你可以直接在里面新建变更集、勾选任务完成状态、查看哪些需求还没实现。这相当于给 AI 编码过程加了一个“项目管理仪表盘”。
二是CLI 强制校验。在命令行里执行 openspec plan 或 openspec apply,工具会校验 Changeset 里的规格状态与代码实际情况是否一致。我常在 CI 里加一个 openspec validate 步骤,任何不满足规约状态的提交都会被拦截。这样 AI 生成的代码就不是“游离于流程之外的补丁”,而是必须符合项目契约的正式变更。
提示:把 OpenSpec 的校验接入 Git Hook 或 CI,是保证 AI 生成代码质量最有效的一步。别指望模型自己自觉去更新状态,机制上强制才有意义。
3. 安装与基础使用:从零跑通一个 Changeset
3.1 安装方式对比
OpenSpec 提供了几种安装路径,操作系统兼容性做得不错:
bash复制# 方式一:Homebrew(macOS 推荐)
brew install openspec
# 方式二:通过 npm 全局安装
npm install -g @openspec/cli
# 方式三:直接安装官方脚本(Linux / CI 环境常用)
curl -fsSL https://openspec.dev/install.sh | bash
我用的是 Homebrew 安装,实测下来最省事,升级也方便。如果你在 Docker 化的 CI 环境里跑,推荐用官方脚本,避免依赖 Node 运行时。安装完成后执行 openspec --version 验证是否成功。
3.2 初始化项目
进入你的项目目录,执行初始化命令:
bash复制cd my-ai-project
openspec init
这条命令会在项目根目录生成 .openspec/ 结构,包括一个 project.md 文件(描述项目整体背景)。此时的目录结构大概是这样:
code复制.openspec/
├── project.md
├── changesets/
└── agent/
└── AGENTS.md
注意 agent/AGENTS.md 这个文件,它是 OpenSpec 给 AI Agent 看的操作手册。里面描述了 Agent 应该如何读取 Changeset、何时更新状态、代码生成的流程是什么。在 Cursor 里用规则文件(.cursor/rules 或项目级 instructions)的时候,我会把这个文件路径写进去,等于让模型自带一份“规约使用指南”。
3.3 创建你的第一个 Changeset
初始化完成后,用命令创建变更集:
bash复制openspec create-changeset add-user-export
这会自动生成 add-user-export/ 目录和几个标准文件。打开 spec.md,内容类似:
markdown复制# 变更集:add-user-export
## 目标
为用户模块增加 CSV 导出功能。
## 范围
- 修改 UserController 的导出相关 API
- 新增 UserExportService
- 不修改现有鉴权逻辑
## 验收标准
- [ ] 导出文件包含筛选后的用户列表
- [ ] 导出操作不改变用户现有行为
- [ ] 导出接口需要登录后才能调用
接下来,在 requirements.md 里补充具体需求,在 tasks.md 里把任务拆成“模型可以直接执行的一步步”。我通常会写得很细,比如“在 src/services/auth.ts 中新增函数 ensureAdminRole”,而不是“加强权限控制”。越具体的任务,Agent 执行越准确。
3.4 plan 和 apply:Agent 的两个关键动作
OpenSpec 的 CLI 里,有两个命令是配合 Agent 使用的核心:
openspec plan:读取当前 Changeset 的规格和任务,输出一个结构化的实施计划,包括涉及文件、改动点、依赖关系。这个命令我自己就常用——在让 Cursor 动手之前,先让它执行一下openspec plan,相当于把施工图晒给模型看一遍。openspec apply:把 Changeset 的状态落实,更新status.md和各需求、任务的状态标记。
实际工作流中,我一般是:
- 创建变更集并填好需求、设计和任务。
- 让 Agent 读取
.openspec/agent/AGENTS.md和当前变更集。 - Agent 按
tasks.md逐项实现。 - 每完成一项,调用
openspec apply更新状态。 - 全部完成后跑
openspec validate校验。
4. 与主流 AI 编程工具的集成:Cursor、Codex、OpenCode
4.1 在 Cursor 中集成 OpenSpec
Cursor 目前是我主力使用的 AI 编辑器,它对 OpenSpec 的支持比较成熟。安装 OpenSpec 插件后,在 Cursor 里按 Ctrl+Shift+O 可以直接打开 OpenSpec 控制面板。
要让 Cursor 的 Agent 自动使用 OpenSpec,核心配置是 .cursor/rules 里加一条规则文件。我建了一个 openspec.mdc 文件,内容大致是:
markdown复制---
description: OpenSpec workflow
globs: **/*
---
在开始编码前,必须先读取 .openspec/agent/AGENTS.md 和当前变更集目录下的所有文件。
严格按照 tasks.md 的顺序实现任务,每完成一个任务就更新任务状态。
不得修改 Changeset 范围之外的文件。
这条规则的意图很明确:让模型“先读规约再动手”,并且把变更范围锁死在任务清单里。实测下来,加上这个规则之后,Cursor 跑偏的概率明显降低,尤其是“顺手改动无关文件”这类问题,基本被拦住了。
4.2 和 Codex CLI 的配合
OpenAI 的 Codex CLI 是另一个我很常用的 AI 编码工具,特别是在终端里跑自动化重构时。Codex 本身支持 AGENTS.md 文件作为项目指导,所以我可以把 OpenSpec 的规则文件作为一种“入口”:
bash复制codex "读取 .openspec/changesets/add-user-export/spec.md,然后按照 tasks.md 依次实现所有任务"
如果你想精确控制 Codex 的行动范围,可以在提示词里加上“任何不在 tasks.md 中的改动都不允许做”。Codex 会在上下文窗口内把 tasks.md 当作约束清单来遵守。
4.3 与 OpenCode 的搭配使用
OpenCode 是一个相对轻量的开源 AI 编码终端工具,它同样支持 AGENTS.md 规则。OpenSpec 官方的文档里甚至给出了一个针对 OpenCode 的配置方式:在 .opencode 配置里把 OpenSpec 路径加到指令列表中。
我的习惯是把 OpenSpec 的 AGENTS.md 软链接到仓库根目录的 AGENTS.md,这样不管是 Cursor、Codex 还是 OpenCode,所有工具都能读到同一份规约。这个链接动作看起来不起眼,但对多工具协同很有帮助——你不会希望 Cursor 和 Codex 对规约的解读不一致。
4.4 Vs Codex / Cline 等工具的通用思路
如果你用的是 Vs Codex、Cline、Continue 这类支持自定义 rules 的工具,集成逻辑是通用的:让 Agent 在执行任务前主动读取 .openspec 目录下的文件即可。具体做法有两种:
- 在工具的 rules / instructions 配置里显式加上“读取 .openspec/agent/AGENTS.md”。
- 在项目根目录的
AGENTS.md中引用 OpenSpec 的路径。
后一种方式对多种工具更友好,因为不少 Agent 默认就会读取项目根目录下的 AGENTS.md。
实操心得:不要只配置一种工具。团队里可能有人用 Cursor,有人用 Codex,有人在 CI 里跑命令行 Agent。把 OpenSpec 的规约做成文件级的标准,让所有工具都消费同一套数据,才是框架真正发挥作用的前提。
5. 实战案例:用 OpenSpec 约束 AI 完成多文件功能开发
5.1 场景与初始化
我拿一个真实的演示项目来说明整个流程。项目是一个 web 管理后台,已有用户认证模块和商品列表模块。现在需要新增一个功能:允许管理员批量导出订单数据为 CSV 文件。
首先我建了一个 Changeset:
bash复制openspec create-changeset add-order-export
然后填充 spec.md:
markdown复制# 变更集:add-order-export
## 目标
为订单管理模块增加 CSV 批量导出功能。
## 范围
- 新增订单导出接口 GET /api/orders/export
- 新增 OrderExportService
- 修改前端订单页面的导出按钮交互
## 不在范围
- 不修改订单状态流转逻辑
- 不引入异步队列机制
接着在 requirements.md 里写需求:
markdown复制## Requirements
- [x] R1: 提供导出接口,返回 CSV 格式数据 (Accepted)
- [x] R2: 导出数据需按当前列表筛选条件过滤 (Accepted)
- [ ] R3: 导出操作需记录操作日志 (Proposed)
在 tasks.md 里做任务拆解:
markdown复制## Tasks
- [ ] T1: 在 `src/modules/order/order.controller.ts` 中新增 `exportCsv` 方法
- [ ] T2: 新增 `src/modules/order/order-export.service.ts`
- [ ] T3: 在 `src/modules/order/order.routes.ts` 中注册导出路由
- [ ] T4: 修改前端 `src/pages/order/index.tsx` 的导出按钮逻辑
5.2 让 Agent 按规约执行
在 Cursor 里打开这个项目,我在对话框里给 Agent 的指令是:
请阅读
.openspec/changesets/add-order-export/spec.md和tasks.md,严格按任务清单逐项实现。不要修改任何不在 tasks 范围内的文件。
Agent 读取变更集后,按 T1 开始实现。每个任务完成后,我让 Cursor 的 OpenSpec 插件把对应任务标记为 Done,再继续下一个。整体执行下来,改动集中在四个文件里,没有多余动作。
5.3 校验与回滚
全部任务完成后,执行校验:
bash复制openspec validate
如果某个需求还没实现完(比如日志功能被遗漏),validate 会报错并明确指出哪个需求没有对应对应实现状态。这种“机械式的提醒”在团队协作里太有用了——AI 不会像人一样主动说“我漏了一个功能”,只有校验工具才能兜住。
如果过程中发现改动不符合预期,OpenSpec 配合 Git 更方便了:由于 Changeset 本身就是一组独立文件,你可以在 git log 里清晰看到“规约变更”和“代码变更”之间的对应关系。要回滚某个 AI 操作,直接 git revert 对应提交即可,不会影响其他功能线。
5.4 这个流程帮我解决的问题
实际用下来,OpenSpec 至少帮我解决了三个之前频繁出现的问题:
第一,模型遗忘需求。以前用纯提示词让 AI 开发,聊了几轮后它经常把最初的需求忘了,或者把已经确认过的设计推翻。OpenSpec 把需求写进文件,Agent 每次读取都是最新状态,不容易丢。
第二,范围失控。现在有 tasks.md 的硬性清单,模型不能随便“自由发挥”了。它改文件之前会对照任务列表,实际上是把“代码生成”变成了“任务执行”。
第三,验收无据。以前做代码评审,AI 生成的改动有没有完成需求全靠人肉眼检查。现在每个需求都有状态标记,还有 openspec validate 做最后把关,评审效率高很多。
6. 常见问题与坑点:从安装到使用全记录
6.1 问题速查表
| 问题现象 | 原因分析 | 解决方案 |
|---|---|---|
openspec: command not found |
安装后 PATH 没刷新,或 npm 全局路径不在环境变量中 | 重开终端;检查 npm 全局目录,手动加入 PATH |
| Cursor 控制面板按快捷键没反应 | 插件没安装,或和现有快捷键冲突 | 在 Cursor 插件市场安装 OpenSpec 扩展,重载窗口 |
| Agent 不读取 Changeset,仍然乱改 | 没有配置 rules 文件,或 AGENTS.md 链接没建 | 在 .cursor/rules 中加入 openspec.mdc,并建立根目录 AGENTS.md 软链接 |
openspec validate 一直报错 |
tasks 或 requirements 的状态更新不完整 | 逐项检查任务状态标记,openspec apply 自动同步状态后再验证 |
| 多个人同时编辑 Changeset 冲突 | 不同分支同时改了同一变更集文件 | 尽量一个 Changeset 对应一个 Git 分支,提交前先 pull 最新代码 |
旧项目没有 .openspec 目录 |
尚未初始化 | 在项目根目录执行 openspec init,不要手动创建目录结构 |
6.2 经验分享:容易忽略的三个细节
第一个细节:Changeset 命名要短、语义明确。 我见过有人用 openspec create-changeset fix-issue-1234 这种命令,名字里全是 issue 编号,过两周自己都想不起来这是干什么的。建议使用动作前缀加上业务名,比如 add-order-export、refactor-auth-flow、fix-session-timeout,这样 Agent 在读取 AGENTS.md 时也能更快建立上下文。
第二个细节:AGENTS.md 和 .cursor/rules 不要写重复。 我一开始两边都写了完整的操作流程,导致 Agent 行为不一致,有时会读到旧的规则。现在我只维护根目录的 AGENTS.md,里面引用 .openspec/agent/AGENTS.md,Cursor 规则文件里只写一句“遵循根目录 AGENTS.md 的流程”。
第三个细节:把 openspec validate 接进 CI 而不是只靠本地执行。 AI Agent 在本地跑的时候可能会自己绕过校验(比如直接跳过命令),但在 CI 里它没有逃跑路径。我是在 GitHub Actions 里加了这一步:
yaml复制- name: Validate OpenSpec
run: npx @openspec/cli validate
只要这个步骤红掉,PR 就无法合并,这比任何提示词都管用。
6.3 从 OpenSpec 到 Agent 工作流的思考
用了这段时间 OpenSpec,我最大的体感是:它把“人和 AI 聊天写代码”的模式,往“人定规则,AI 执行规则”的方向推了一大步。过去我们依赖模型的“理解能力”,现在更多依赖“流程约束能力”。规约框架这种东西,短时间内不会替代模型,但它决定了一个项目能让 AI 在多大范围内自主干活。
我甚至觉得,OpenSpec 的底层思路可以扩展到 AI 测试生成、数据库迁移生成、文档自动维护等环节——只要是有明确输入输出边界、需要多步骤执行的工作,都可以用“规约文件 + 任务拆解 + 状态校验”来约束 Agent。这个思路比具体某个工具更重要。
最后分享一个小习惯:我会在每周五的代码评审前跑一次 openspec plan,把下一周要做的变更集全列出来,和同事对齐后再放 Agent 去实现。这一步看起来很简单,但提前把规约对齐到位,能让后续 AI 生成的代码少返工一半。这套流程你完全可以照搬过去试一试,先从一个小功能开始,用不了半小时就能跑通。
