Skip to content

Stores (beta) ​

规划跨仓库的变更:一个 store,多个仓库。

OpenSpec 通常位于单个仓库内:一个 openspec/ 文件夹,紧挨着它所规划的代码。Store 会将该文件夹移入一个独立的仓库,多个代码仓库便可以共享它。

在每台机器上完成一次性设置后,status、new change、archive 等命令就可以在任意目录下对 store 使用。

         team-plans  (一个 store:OpenSpec 位于自己的仓库中)
         ├── .openspec-store/store.yaml   store 的名称
         └── openspec/
             ├── specs/
             └── changes/
                   ▲
                   │ 在每台机器上设置一次,
                   │ 像任何仓库一样通过 push 和 clone 共享
     ┌─────────────┼─────────────┐
     │             │             │
 web-app       api-server     mobile-app
(代码仓库) (代码仓库)   (代码仓库)

你使用 git 共享 store,就像共享代码一样:自行完成 commit、push、pull 和 review。Spec 和变更会像代码一样,获得各自的分支和 pull request。

什么时候需要 store ​

使用 store 的两个常见原因:

  • 前端和后端分属不同仓库:一个功能会同时涉及两者,计划需要安放在同一个地方,而不是被拆成两半。

          shop-plans  (store)
          └── openspec/changes/add-discounts/    该功能的一份计划
                    ▲
          ┌─────────┴─────────┐
          │                   │
      storefront             api
     (前端仓库)        (后端仓库)
  • 一个产品,多个客户端仓库:Android、iOS 和 web 各自从自己的仓库发布,却共享同一份预期行为。spec 描述的是行为,而不是实现,因此一份 spec 就能同时服务于三者。

            product-specs  (store)
            └── openspec/specs/checkout/spec.md    预期的行为
                      ▲
        ┌─────────────┼─────────────┐
        │             │             │
    android-app    ios-app       web-app

(代码仓库) (代码仓库) (代码仓库)


你可以拥有多个 store,不过我们建议将其数量保持在较低水平。

## 设置存储库

由一个人创建存储库,然后其他人加入。

1. **创建存储库**(一个人操作,每个团队一次)。运行 `openspec store setup` 并回答提示:

 ```bash
 # 可在任意位置运行;它会询问要创建什么以及创建在哪里
 openspec store setup

它会询问三个问题:

  • 存储库名称:team-plans
  • 此存储库应位于何处?:预填为 ~/openspec/<name>,按 Enter 接受,或输入另一个路径
  • 创建此存储库吗?:显示即将创建的内容,回答 Yes

然后它会报告所创建的内容:

yaml
Store ready: team-plans
Location: ~/openspec/team-plans
OpenSpec root: ready
Registry: registered

Next: run normal OpenSpec commands against this store, for example:
  openspec new change <change-id> --store team-plans
Share this store by committing and pushing it like any Git repo.
  1. 将其推送到你的 Git 托管平台。 首先在你的托管平台上创建一个空的 team-plans 仓库。设置过程不会添加 Git 远程仓库,因此请将存储库连接到该仓库,然后推送:

    bash
    # 将存储库连接到 Git 托管平台上的空仓库
    cd ~/openspec/team-plans
    git remote add origin git@github.com:acme/team-plans.git
    
    # 发布它
    git push -u origin main
  2. 加入存储库(每位队友,每台机器一次):

    bash
    # 将存储库获取到你的机器上
    git clone git@github.com:acme/team-plans.git ~/openspec/team-plans
    
    # 告诉 OpenSpec 它位于何处
    openspec store register ~/openspec/team-plans
    yaml
    Store registered: team-plans
    Location: /Users/you/openspec/team-plans
    OpenSpec root: ready
    Registry: registered

    注册会告诉你的机器这个存储库位于何处。存储库的名称已经提交在其内部,位于 .openspec-store/store.yaml。设置过程已注册创建者的副本,因此只有克隆得到的副本需要执行此步骤。

  3. 确认它正常工作,从任意目录:

    bash
    # 任何 OpenSpec 命令都能按名称访问该存储库
    openspec status --store team-plans
    yaml
    Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
    No active changes. Create one with: openspec new change <name> --store team-plans

设置类型 ​

OpenSpec 有三种设置。本页其余部分使用以下名称:

  • repo-local:OpenSpec 位于你的仓库内,不使用存储库。这是默认设置。
  • store-only:你的仓库不保留自己的 specs 或 changes。所有内容都位于存储库中。
  • store-optional:你的项目有自己的 openspec/ 文件夹,并且在需要时也可以访问存储库。

默认:OpenSpec 位于你的仓库内(repo-local) ​

openspec init 会在你的代码旁放置一个 openspec/ 文件夹,该仓库的 specs 和 changes 就存放在那里。不涉及存储库。这是 设置你的项目 所介绍的设置,大多数项目永远不需要其他设置。

web-app  (代码仓库)
└── openspec/
    ├── specs/
    └── changes/

OpenSpec 位于仓库之外,在存储库中(store-only) ​

该仓库不保留自己的 specs 或 changes。它规划的所有内容都位于存储库中,仓库配置中的一行将两者连接起来。

当由一个团队构建所有仓库并在一处进行规划时,这很常见。上面的示例都属于这种形态。

team-plans  (存储库)
└── openspec/
    ├── specs/       该仓库的 specs 位于此处
    └── changes/     其 changes 也位于此处
          ▲
          │ store: team-plans   (连接行)
web-app  (代码仓库)
└── openspec/
    └── config.yaml    没有其他内容

OpenSpec 既在你的仓库中,也在存储库中(store-optional) ​

该仓库在其自身工作中仍保持 repo-local,而存储库保存共享的 specs 和 changes。在仓库内部,OpenSpec 使用你项目的 openspec/ 文件夹,并且仅当你传入 --store 时才访问存储库。

当某个仓库在存储库存在之前就已使用 OpenSpec,或当一个基本独立的仓库只是偶尔接触共享工作时,这很常见。

team-plans  (存储库)
└── openspec/          共享的 specs 和 changes
          ▲
          │ 仅当你传入 --store team-plans 时
web-app  (代码仓库)
└── openspec/          此仓库自己的内容
    ├── config.yaml
    ├── specs/
    └── changes/

仓库可以起初为 repo-local,之后再将其 specs 和 changes 移入存储库。将仓库的 specs 和 changes 移入存储库 说明了如何操作。

使用存储库时工件的创建位置 ​

使用存储库时,OpenSpec 还必须决定工件的创建位置。这取决于你的设置:

  • store-only(你的项目只写入存储库):每个工件都在存储库中创建。下面的 store: 行记录了这一点。
  • store-optional(你的项目有自己的 openspec/ 文件夹,同时也使用存储库):工件会在你的项目中创建,除非你在请求中指明存储库,或为该变更传入 --store。随后,你的智能体会在工作流的其余部分沿用该标志。

OpenSpec 会将工件写入以下两个位置之一:你项目的 openspec/ 文件夹,或存储库的 openspec/ 文件夹。它按以下顺序选择,第一个适用的选项生效:

  1. 命令上的 --store <id>。 始终优先,无论从哪个目录运行。
  2. 你项目的 openspec/ 文件夹。 如果你的项目有自己的 specs/ 或 changes/ 文件夹,OpenSpec 会使用它们。
  3. 你项目中的 store: 行。 这是 store-only 项目记录其存储库的方式。
  4. 你机器上的 defaultStore。 以上都不适用时的后备选项。

如果这些都不适用,并且你已注册存储库,命令会失败并列出它们。当某个存储库的 ID 与你的仓库在其 origin 远程中的名称匹配时,错误信息会指出该存储库以及选择它的 store: 行。OpenSpec 绝不会自行按名称选择存储库,因为不同组织中的仓库可能同名。

当 OpenSpec 选择某个存储库时,它会在命令输出之前打印 Using OpenSpec root: ...。

store: 行(store-only 项目) ​

向你项目的 openspec/config.yaml 添加一行:

yaml
# web-app/openspec/config.yaml
store: team-plans

现在,你或你的智能体在项目内运行的所有内容都会使用该存储库,无需输入标志:

bash
# 在 web-app 内,已连接
openspec status
yaml
Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
No active changes. Create one with: openspec new change <name> --store team-plans
  • 没有该行:在 store-only 项目中运行普通命令时,OpenSpec 会停止并报错,列出你已注册的存储库。
  • 提交它:克隆你项目的队友也会获得该行。他们仍需要在自己的机器上注册该存储库(设置存储库的第 3 步),否则 OpenSpec 会报错并提示他们注册。
  • 与实际文件夹并存:如果你的项目同时还有 specs/ 或 changes/ 文件夹,OpenSpec 会使用这些文件夹,并忽略该行,同时给出警告。

在 store-only 仓库中安装集成 ​

从代码仓库的根目录运行 init,以安装 AI 工具集成文件,同时不将规划移回该仓库:

bash
# 在 web-app 内,位于仓库根目录
openspec init --tools claude
  • 集成文件:写入代码仓库。
  • openspec/config.yaml:逐字节保留,包括 store: 行。
  • openspec/specs/ 和 openspec/changes/:不会在代码仓库中创建。

OpenSpec 会拒绝从代码仓库的子目录运行此命令。请从仓库根目录运行。

OpenSpec 在这里也会拒绝 --language,因为语言设置属于外部存储库的配置。请在存储库根目录运行 init,或直接编辑该配置。

你机器上的 defaultStore ​

如果你参与的所有项目都使用同一个存储库,设置一次即可。当 OpenSpec 没有找到标志、没有本地 openspec/ 文件夹,也没有 store: 行时,就会回退到它:

bash
# 当其他内容都未指定存储库时,使用 team-plans
openspec config set defaultStore team-plans

# 撤销它
openspec config unset defaultStore

保持本地操作的命令。 init、update、templates、schemas 以及 openspec schema 子命令仅作用于当前目录,不接受 --store。

将仓库的 specs 和 changes 移入存储库 ​

要将仓库从 repo-local 变为 store-only:

  1. 将仓库 openspec/specs/ 和 openspec/changes/ 中的所有内容移动到存储库中的相同文件夹。
  2. 删除现已为空的文件夹,使仓库的 openspec/ 文件夹中只保留 config.yaml。
  3. 向该 config.yaml 添加 store: 行。

现在在仓库内运行 openspec status,会以 Using OpenSpec root: team-plans 开头。

在存储库中工作 ​

无论对你还是对你的智能体,工作流都不会改变。Propose、apply 和 archive 仍按原有方式运行。唯一的区别是工件的创建位置,上一节 已对此进行说明。

在 store-only 仓库内部创建变更,它会落在存储库中:

bash
# 在 web-app 内;store: 行会将其路由到 team-plans
openspec new change add-login
yaml
Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
Created change 'add-login' at /Users/you/openspec/team-plans/openspec/changes/add-login/
Schema: spec-driven
Next: openspec status --change add-login --store team-plans
  • 它去了哪里:进入存储库对应的 Git 仓库,而不是你的代码旁边。
  • 共享它:在你提交并推送存储库对应的 Git 仓库之前,该变更只存在于你的本地检出中。队友拉取后即可看到它。工作流写入的每个工件也是如此。
  • 文档中的路径:无论文档在何处显示 openspec/ 路径,在存储库设置中,该文件夹都属于存储库。

当工件被创建在你意想不到的位置时,openspec doctor 会在不做任何更改的情况下检查你的设置,并针对每条发现打印修复建议:

bash
# 检查当前根目录及其存储库
openspec doctor
yaml
Doctor

Root
  Location: /Users/you/openspec/team-plans
  OpenSpec root: ok
  Store: team-plans (metadata ok)

References
  (none declared)

openspec context 会列出当前目录所使用的根目录和存储库,适合在你想要同样概览但不进行检查时使用。

要在同一个编辑器窗口中打开存储库和某个仓库,以便你的智能体可以同时读取两者,请参阅 Worksets(测试版)。

从其他存储库读取规格 ​

你的仓库可以保留自己的 openspec/ 文件夹,同时让代理读取其他存储库的规格。在仓库的 openspec/config.yaml 中的 references: 下声明该存储库:

yaml
# api-server/openspec/config.yaml
references:
  - team-plans

引用是只读的。你的工作仍保留在你的仓库中,引用只改变代理获取的信息。

当工作流创建工件时,其指令会获得引用存储库规格的索引,每个规格都包含一行摘要和获取它的确切命令:

xml
<referenced_stores>
<!-- 只读上游上下文。获取你需要的内容;引用你使用的内容。 -->
存储库 team-plans (/Users/you/openspec/team-plans):
  - payments:向客户收费和退款的规则。
  获取:openspec show <spec-id> --type spec --store team-plans
</referenced_stores>

引用还可以包含存储库的克隆 URL,用于尚未拥有该存储库的机器:

yaml
references:
  - team-plans
  - { id: design-system, remote: "git@github.com:acme/design-system.git" }

声明 URL 后,openspec doctor 会将缺失的存储库转换为可直接粘贴的修复方案:

yaml
# output wrapped to fit
References
  - team-plans: 正常 (/Users/you/openspec/team-plans)
  - design-system: 引用的存储库 'design-system' 未在此机器上注册。
    修复: git clone -- git@github.com:acme/design-system.git '/Users/you/openspec/design-system' &&
         openspec store register '/Users/you/openspec/design-system' --id design-system

Beta 限制 ​

  • 结构可能变化:命令名称、标志和文件格式可能在不同版本之间发生变化。升级后请重新阅读此页面。
  • 不同步,设计如此:OpenSpec 从不克隆、拉取或推送。过期的检出会显示过期的规格,直到你拉取为止,引用从磁盘上的任何内容读取。
  • 每个存储库名称一个检出:在已注册的名称下注册第二个文件夹会失败,并提示先运行 openspec store unregister。