OpenSpec 1.5 更新详解:Stores Beta、Explore-first 工作流与团队级规格协作

发布于 2026年7月2日 作者 Remy

OpenSpec 近期最重要的变化不是某个单点命令,而是一次组织模型升级:它正在从“给单个仓库生成 spec workflow 的轻量 CLI”,向“可以被多个项目、多个团队、多个 AI agent 共享的规格协作层”演进。

如果只看一个关键词,就是 Stores。如果只看一条工作流,就是:

explore → propose → apply → archive

本文基于 Fission-AI/OpenSpecv1.5.0 源码、CHANGELOGdocs/cli.mddocs/commands.mddocs/explore.mddocs/existing-projects.md 以及相关命令实现,整理这次更新的含义、使用方式和工程上的注意点。

如果你还不熟悉 OpenSpec 的基础用法,可以先读这篇教程:OpenSpec 教程:CLI 安装、命令、AGENTS.md 与实战示例。本文不重复基础安装,而是聚焦 1.5 之后的新能力和实际落地方式。

一句话总结

OpenSpec 1.5 的主线是:用 Stores Beta 把 specs、changes 和 planning context 从单个 repo 里抽象出来;同时把 explore-first 变成更明确的推荐习惯,并补齐 brownfield 项目、AI command frontmatter、JSON 输出和多工具适配的稳定性。

这意味着 OpenSpec 不再只是“让 AI 按规范写代码”的文件模板,而是在尝试解决更难的问题:

  • 团队的规格和需求能否独立于代码仓库存在?
  • 一个项目能否引用另一个团队维护的规格上下文?
  • AI agent 能否在执行前知道“当前工作到底属于哪个 OpenSpec root”?
  • 模糊需求能否先被探索,再进入正式变更流程?

OpenSpec 1.5.0:Stores Beta 是核心变化

@fission-ai/openspec 当前发布版本为 1.5.0,npm 包描述是:

AI-native system for spec-driven development

CLI 入口仍是:

openspec

但 1.5.0 开始,OpenSpec 新增了 Stores very early beta。官方文档对 Store 的定义很直接:

A store is a standalone OpenSpec repo you’ve registered on this machine.

也就是说,Store 是一个可以被本机注册的独立 OpenSpec 仓库。它可以是:

  • 团队共用的 planning repo;
  • 产品/合约/架构规格仓库;
  • 跨项目复用的需求上下文;
  • 不想放进当前代码仓库的外部 spec root。

注册后,很多普通命令都可以通过 --store <id> 指向这个外部 root:

openspec list --store team-context
openspec show auth --type spec --store team-context
openspec new change add-billing-api --store team-context
openspec status --change add-billing-api --store team-context
openspec archive add-billing-api --store team-context

这就是它和旧模型的关键差异:过去 OpenSpec 更多假设你在当前 repo 的 openspec/ 目录下工作;现在它开始明确管理“多个 OpenSpec root”。

Stores 解决了什么问题?

在单人小项目中,把 openspec/specsopenspec/changes 放在当前 repo 里通常够用。但真实工程里经常会出现这些情况:

  • 一个产品能力跨越多个 repo;
  • 平台团队维护的规范要被多个业务团队引用;
  • 代码仓库很大,但需求规格希望独立演进;
  • AI agent 在不同 repo 中工作,但需要共享同一套业务约束;
  • 既有项目不想一开始就引入完整 openspec/ 目录。

Stores 的方向就是把规格从“某个代码仓库里的文件夹”提升为“可注册、可诊断、可引用、可选择的工程资产”。

这也是为什么我认为 Stores 不是一个小功能,而是 OpenSpec 的组织模型重构。

Store 命令速览

官方 CLI 文档中,Store 相关能力仍标为 Beta:命令名、flag、文件格式和 JSON 输出都可能继续变化。但当前核心命令已经很清楚。

创建并注册一个 Store

openspec store setup team-context --path ~/openspec/team-context

如果你希望跳过 Git 初始化:

openspec store setup team-context --path ~/openspec/team-context --no-init-git

面向 agent 或脚本时,建议使用 --json,并显式传入 id 和 path:

openspec store setup team-context \
  --path ~/openspec/team-context \
  --no-init-git \
  --json

注册已有 Store

openspec store register ~/openspec/team-context --id team-context

只忘记本地注册,不删除文件

openspec store unregister team-context

这适合 Store 被移动、重新克隆,或你只是想让本机 OpenSpec 不再显示它。

删除本地 Store 文件夹

openspec store remove team-context --yes

文档中特别强调:remove 会删除本地文件夹,交互模式会显示将要删除的路径;脚本和 JSON 调用必须传 --yes。源码里也能看到它会校验 metadata,避免误删不匹配的目录。

列出本机 Store

openspec store list
openspec store ls --json

诊断 Store 健康状态

openspec store doctor
openspec store doctor team-context --json

doctor 只诊断,不会 clone、pull、push 或修复。它会报告 root、metadata、Git、references 等状态。对于 AI agent 来说,--json 输出里的 status 数组是更可靠的机器可读信号。

源码视角:Store Registry 如何工作

从源码看,Stores 的核心实现集中在:

src/core/store/foundation.ts
src/core/store/registry.ts
src/core/store/operations.ts
src/core/root-selection.ts
src/commands/store.ts

其中 foundation.ts 定义了本机 registry 的文件名:

export const STORE_REGISTRY_FILE_NAME = 'registry.yaml';

Registry 的结构可以概括为:

version: 1
stores:
  team-context:
    id: team-context
    root: /Users/you/openspec/team-context
    # backend / metadata / remote 等信息

源码里有几类关键操作:

  • readStoreRegistryState():读取本机 registry;
  • writeStoreRegistryState():写入 registry;
  • updateStoreRegistryState():带 lock 更新 registry,避免并发写冲突;
  • listStoreRegistryEntries():列出 stores;
  • registerStore():注册 Store;
  • unregisterStoreRegistration():移除本机注册;
  • 冲突检查:防止同一个 id 指向不一致的 root 或 backend;
  • metadata 校验:防止 registry id 与 Store 自身 metadata id 不一致。

这说明 OpenSpec 并不是简单地“记一个路径”。它开始把 Store 当成有身份、有健康状态、有本机注册表、有 Git/remote 元数据的上下文单元。

Root selection:为什么 --store 很重要

OpenSpec 1.5 之后,很多命令都需要先回答一个问题:当前命令应该作用在哪个 OpenSpec root 上?

文档中提到,listshowvalidatestatusinstructionsnew changearchivedoctorcontext 等命令都会解析一个 root。

一般优先级可以理解为:

  1. 显式 --store <id>
  2. 当前 repo 的本地 OpenSpec root;
  3. openspec/config.yaml 中声明的默认 store:
  4. 失败时输出诊断。

这对 AI agent 很关键。过去 agent 很容易在错误的目录下执行命令,或者把当前 repo 的 openspec/ 和外部 workspace 状态混在一起。现在 JSON 输出和错误诊断会携带 root/store 信息,让 agent 更容易判断“我到底在改哪里”。

References:只读引用,不改变写入位置

Store 还有一个很实用的用法:在项目的 openspec/config.yaml 里声明引用。

schema: spec-driven
references:
  - team-context

或者带上远端来源:

references:
  - { id: team-context, remote: "[email protected]:acme/team-context.git" }

之后,openspec instructions 会把引用 Store 的 spec 索引带进输出,包括:

  • spec id;
  • 从 Purpose 段落提取的一行 summary;
  • 可用于拉取完整内容的命令,例如:
openspec show <spec-id> --type spec --store team-context

需要注意:references 是只读上下文。它不会改变命令实际写入的位置。当前 repo 的工作仍写在当前 root;如果要写入 Store,必须显式使用 --store <id>

这个设计很重要:它避免了“引用上下文”和“生命周期归属”混在一起。一个 change 仍属于一个 root,reference 只是帮助 agent 理解背景。

默认外部 Store:把规划完全外置

如果某个 repo 不想本地保留 openspec/specsopenspec/changes,可以在 openspec/config.yaml 中声明默认 Store:

store: team-context

这样普通命令会自动解析到这个 Store:

openspec list
openspec new change add-login
openspec status --change add-login

显式 --store 仍然优先;如果当前目录已经有真实 planning folders,本地 root 也不会被这个 pointer 强行覆盖。

Context 与 Worksets:给 agent 的“工作集合”

OpenSpec 还引入了 doctorcontext 两个相关但不同的问题:

openspec doctor [--store <id>] [--json]
openspec context [--store <id>] [--json]

可以这样理解:

  • doctor 回答:这个 root 和它引用的 stores 健康吗?
  • context 回答:这个工作到底由哪些 root/store 组成?

context 的 JSON 输出适合 agent 消费;它也可以通过 --code-workspace 生成 VS Code workspace,把当前 root 和可用引用 Store 组合成一个可打开的工作区。

Worksets 则更偏个人本地视图:把你经常一起工作的文件夹命名保存,方便重新打开。它是本地的、不提交、不共享,也不会从 declarations 自动推导。

Explore-first:OpenSpec 的工作流重心前移

除了 Stores,6 月文档更新中另一个信号非常明显:OpenSpec 把 /opsx:explore 放到了更靠前的位置。

官方命令文档写得很直接:

Start here when you’re unsure.

/opsx:explore 的定位不是创建 change,而是作为“无风险的思考伙伴”:它可以先读代码、比较方案、澄清模糊想法,在 artifact 或 code 产生前把问题收敛成计划。

推荐习惯变成:

/opsx:explore   # 不确定做什么时先探索
/opsx:propose   # 形成正式 change 和规划 artifacts
/opsx:apply     # 根据 tasks 实施
/opsx:archive   # 完成后归档并更新主规格

这和很多 AI coding 工具的默认体验很不同。大多数工具鼓励你直接说“实现 X”;OpenSpec 现在更强调:当需求还不清楚时,不要急着生成 proposal,更不要急着改代码。

终端命令和 AI Slash Commands 的分工

OpenSpec 文档反复强调一个容易混淆的点:

  • openspec init/update/list/validate/status/... 是终端 CLI;
  • /opsx:explore/opsx:propose/opsx:apply/opsx:archive 是在 AI assistant 聊天里输入的命令。

一个典型流程是:

# terminal
npx -y @fission-ai/openspec@latest init .
npx -y @fission-ai/openspec@latest update

然后在 AI 工具中:

/opsx:explore redesign billing flow
/opsx:propose add-usage-based-billing
/opsx:apply
/opsx:archive

这也是 OpenSpec 的特殊之处:CLI 负责文件、schema、root、状态、验证;AI slash command 负责让 agent 按同一套 artifact contract 行动。

Brownfield 项目:不要一口气文档化全系统

docs/existing-projects.md 的增强说明 OpenSpec 已经不只面向新项目模板。对既有项目,它更推荐 delta-first 的方式:

  • 不要试图一开始把整个系统都写成 specs;
  • 从一个真实 change 开始;
  • 只为受影响区域补充必要规格;
  • 让 proposal、design、tasks、spec delta 约束这一次变更;
  • 归档后再逐渐积累主规格。

这对真实团队很关键。很多规范驱动工具失败,不是因为理念错,而是因为要求团队先完成一大坨前置文档。OpenSpec 的 brownfield 路径更轻:先解决眼前变更,再让知识沉淀下来。

YAML frontmatter 修复:小 bug,大影响

1.5.0 还有一个看似细节但很重要的修复:命令描述的 YAML frontmatter 现在会正确 escape 回车和换行。

源码中新增了共享 helper:

src/core/command-generation/yaml.ts

核心函数是:

export function escapeYamlValue(value: string): string {
  const needsQuoting = /[:\n\r#{}[\],&*!|>'"%@`]|^\s|\s$/.test(value);
  if (needsQuoting) {
    const escaped = value
      .replace(/\\/g, '\\\\')
      .replace(/"/g, '\\"')
      .replace(/\n/g, '\\n')
      .replace(/\r/g, '\\r');
    return `"${escaped}"`;
  }
  return value;
}

它被多个 command adapters 复用,包括:

  • Claude;
  • Cursor;
  • Windsurf;
  • Pi;
  • Bob。

这类 bug 对普通用户可能不显眼,但对 AI 工具适配很重要:如果 frontmatter 被 YAML line folding 或 CRLF 污染,命令描述可能看似能生成,实际被工具读取时语义已经变了。集中 helper 之后,同类问题可以在一个地方修。

Config JSON container 解析修复

1.5.0 还修复了配置值被包在 JSON container 中时的解析问题。这通常会影响编辑器、AI 工具或自动化脚本生成配置的场景。

从产品角度看,它和 YAML 修复属于同一类:OpenSpec 正在变成多个工具之间的“协议层”,所以配置和命令文件必须足够稳。越多 AI 工具接入,越不能依赖“人眼看起来没问题”。

v1.4 系列:工具适配继续扩展

6 月初的 v1.4.0v1.4.1 也值得放在一起看。

v1.4.0 增加了:

  • Kimi CLI support;
  • Mistral Vibe support;
  • 新安装 core profile 默认生成 /opsx:sync
  • requirement headers 大小写不敏感;
  • zsh / oh-my-zsh completion 修复;
  • validate 对 SHALL / MUST 放错位置时给出更清楚提示。

v1.4.1 修复了:

  • 当项目本身有 workspace.yaml 时,openspec update 被误导的问题;
  • beta workspace view state 被移到 .openspec-workspace/view.yaml
  • 顶层 openspec update 不再错误路由到 workspace update。

这些更新说明 OpenSpec 的生态适配还在扩张,但同时也在修 workspace-era 模型带来的边界问题。Stores 的出现,某种程度上就是对这些边界问题的系统性回应。

实战建议:什么时候该用 Store?

你可以用这个判断标准。

继续用 repo-local openspec/,如果:

  • 只有一个代码仓库;
  • spec 和 code 生命周期高度一致;
  • 团队不需要跨 repo 共享需求;
  • 你只是想让 AI 变更更可控。

考虑 Store,如果:

  • 一个产品能力横跨多个 repo;
  • 有团队级共享规范;
  • 有平台/协议/设计系统之类的独立规格资产;
  • 你希望代码 repo 保持轻量,只引用外部 planning root;
  • 多个 AI agent 需要共享同一个上下文来源。

暂时谨慎使用 Store,如果:

  • 你不能接受 beta 的命令/格式变化;
  • 团队还没有形成 spec 维护习惯;
  • 只是一次性原型或短期 demo;
  • 当前问题还没复杂到需要多 root。

一个推荐的团队落地流程

假设你有一个团队级 Store:

openspec store setup team-context \
  --path ~/openspec/team-context \
  --remote [email protected]:acme/team-context.git

在业务项目中引用它:

# openspec/config.yaml
schema: spec-driven
references:
  - { id: team-context, remote: "[email protected]:acme/team-context.git" }

日常开发时:

openspec doctor --json
openspec context --json
openspec instructions --change add-billing-api --json

AI 聊天中:

/opsx:explore usage-based billing edge cases
/opsx:propose add-usage-based-billing
/opsx:apply
/opsx:archive

如果某个变更本身应该进入团队 Store,而不是当前 repo:

openspec new change update-billing-contract --store team-context

然后让 AI agent 基于这个 change 继续生成 artifacts。

对 OpenSpec 产品方向的判断

这轮更新透露出三个方向。

第一,OpenSpec 正在从 command generator 走向 workflow runtime。早期价值是给不同 AI coding tools 生成 commands/skills;现在它在加强 root selection、artifact state、validation、archive、JSON contract。

第二,它正在从单项目工具走向多项目协作层。Stores、references、context、worksets 的组合,都是为了让规格能在 repo 之外独立存在,并被 agent 装配进工作上下文。

第三,它越来越强调“约束 AI 实施”,而不是“写文档”。explore → propose → apply → archive 的意义不是生成更多 Markdown,而是让意图、验收标准、任务和最终 spec delta 形成闭环。

结论

OpenSpec 1.5 最值得关注的不是某个命令,而是它对“规格在哪里、归谁管、被谁引用、由哪个 agent 执行”的重新建模。

如果你是个人开发者,短期内最值得养成的习惯是:不确定时先 /opsx:explore,不要直接让 AI 改代码。

如果你是团队或多 repo 项目,最值得试验的是:把共享规格抽成 Store,用 references 给项目提供只读上下文,用 --store 明确写入归属。

Stores 仍然是 early beta,但方向很清楚:OpenSpec 正在从“AI coding 的 spec 文件模板”升级为“AI coding 的规格协作层”。

Ad Blocker Detected

We noticed that you are using an ad blocker. This site relies on advertisements to provide free content and stay operational.

How to whitelist our site:

To continue accessing our content, please disable your ad blocker or whitelist our site. Once you've disabled it, please refresh the page.

Thank you for your understanding and support! 🙏