Skip to content

存放庫 (測試版) ​

規劃跨越多個儲存庫的變更:一個存放庫,多個程式碼儲存庫。

OpenSpec 通常位於單一儲存庫中:一個與其所規劃程式碼相鄰的 openspec/ 資料夾。存放庫則是將該資料夾移至其自身的儲存庫,讓多個程式碼儲存庫可以共用。

每台機器完成一次性設定後,像 status、new change 和 archive 等指令就能在任何目錄中操作該存放庫。

         team-plans  (a store: OpenSpec in its own repo)
         ├── .openspec-store/store.yaml   the store's name
         └── openspec/
             ├── specs/
             └── changes/
                   ▲
                   │ set up once on each machine,
                   │ shared by pushing and cloning like any repo
     ┌─────────────┼─────────────┐
     │             │             │
 web-app       api-server     mobile-app
(code repo)   (code repo)    (code repo)

您可以像共用程式碼一樣,透過 Git 共用存放庫:提交、推送、拉取並自行審查。規格與變更會像程式碼一樣,使用分支與拉取請求 (pull request) 進行管理。

何時需要使用存放庫 ​

兩個常見的使用存放庫理由:

  • 前後端位於不同儲存庫:一個功能會同時涉及兩者,該計劃需要一個統一的位置,而不是分成兩半。

          shop-plans  (store)
          └── openspec/changes/add-discounts/    one plan for the feature
                    ▲
          ┌─────────┴─────────┐
          │                   │
      storefront             api
    (frontend repo)     (backend repo)
  • 一個產品,多個客戶端儲存庫:Android、iOS 和 Web 各自從自己的儲存庫發布,但共享相同的預期行為。規格描述的是行為而非實作,因此一份規格就能服務這三個平台。

            product-specs  (store)
            └── openspec/specs/checkout/spec.md    the expected behavior
                      ▲
        ┌─────────────┼─────────────┐
        │             │             │
    android-app    ios-app       web-app
    (code repo)   (code repo)   (code repo)

您可以擁有不只一個存放庫,但我們建議維持較少的數量。

設定 store ​

由一個人建立 store,然後其他人再加入。

  1. 建立 store(由一個人執行,每個團隊一次)。執行 openspec store setup 並回答提示:

    bash
    # 可從任何位置執行;它會詢問要建立什麼以及要建立到哪裡
    openspec store setup

    它會詢問三個問題:

    • store 名稱:team-plans
    • 這個 store 應該放在哪裡?:預先填入 ~/openspec/<name>,按 Enter 接受,或輸入其他路徑
    • 要建立這個 store 嗎?:顯示即將建立的內容,回答 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.
  2. 將它推送到你的 Git 主機。 先在你的主機上建立一個空的 team-plans 儲存庫。設定流程不會加入 Git remote,因此請將 store 連接到該儲存庫,然後推送:

    bash
    # 將 store 連接到 Git 主機上的空儲存庫
    cd ~/openspec/team-plans
    git remote add origin git@github.com:acme/team-plans.git
    
    # 發布它
    git push -u origin main
  3. 加入 store(每位隊友、每台機器一次):

    bash
    # 將 store 放到你的機器上
    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

    註冊會告訴你的機器這個 store 位於何處。store 的名稱已提交在其內部的 .openspec-store/store.yaml 中。設定流程已註冊建立者的副本,因此只有 clone 出來的副本需要執行此步驟。

  4. 確認設定成功,可從任何目錄執行:

    bash
    # 任何 OpenSpec 命令都能依名稱找到該 store
    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。這是預設。
  • store-only:你的儲存庫不保留自己的規格或變更。所有內容都位於 store 中。
  • store-optional:你的專案有自己的 openspec/ 資料夾,並且在你指定時也會連到 store。

預設:OpenSpec 位於你的儲存庫內(repo-local) ​

openspec init 會在你的程式碼旁放置一個 openspec/ 資料夾,該儲存庫的規格與變更就放在那裡。不會涉及 store。這是 設定你的專案 所教的設定方式,大多數專案不需要其他設定。

web-app  (code repo)
└── openspec/
    ├── specs/
    └── changes/

OpenSpec 位於你的儲存庫之外,在 store 中(store-only) ​

儲存庫不保留自己的規格或變更。它規劃的所有內容都位於 store 中,並由儲存庫設定中的一行連接兩者。

當一個團隊建置所有儲存庫並在同一處規劃時,這很常見。上述範例 都是這種形式。

team-plans  (store)
└── openspec/
    ├── specs/       the repo's specs live here
    └── changes/     its changes too
          ▲
          │ store: team-plans   (the connecting line)
web-app  (code repo)
└── openspec/
    └── config.yaml    nothing else

OpenSpec 同時位於你的儲存庫與 store 中(store-optional) ​

儲存庫自身的工作仍維持 repo-local,而 store 則保存共用的規格與變更。在儲存庫內,OpenSpec 會使用你專案的 openspec/ 資料夾,且只有在傳入 --store 時才會連到 store。

當儲存庫在 store 出現之前就已使用 OpenSpec,或當一個大致獨立的儲存庫偶爾才涉及共用工作時,這很常見。

team-plans  (store)
└── openspec/          the shared specs and changes
          ▲
          │ only when you pass --store team-plans
web-app  (code repo)
└── openspec/          this repo's own
    ├── config.yaml
    ├── specs/
    └── changes/

儲存庫可以從 repo-local 開始,之後再將其規格與變更移入 store。將儲存庫的規格與變更移入 store 說明了做法。

使用 store 時,產出物會建立在哪裡 ​

使用 store 時,OpenSpec 也必須決定產出物會建立在哪裡。這取決於你的設定:

  • store-only(你的專案只寫入 store):每個產出物都會建立在 store 中。下方的 store: 行會記錄這一點。
  • store-optional(你的專案有自己的 openspec/ 資料夾,同時也使用 store):除非你在請求中指名該 store,或為該變更傳入 --store,否則產出物會建立在你專案中。你的 agent 接著會在後續工作流程中沿用該旗標。

OpenSpec 會將產出物寫入兩個位置之一:你專案的 openspec/ 資料夾,或 store 的資料夾。它會依下列順序選擇,並以第一個適用者為準:

  1. 命令上的 --store <id>。 永遠優先,且可從任何目錄生效。
  2. 你專案的 openspec/ 資料夾。 如果你的專案有自己的 specs/ 或 changes/ 資料夾,OpenSpec 會使用它們。
  3. 你專案中的 store: 行。 store-only 專案用來記錄其 store 的方式。
  4. 你機器上的 defaultStore。 上述皆不適用時的後備選項。

如果上述皆不適用,且你已有註冊的 store,命令會失敗並列出這些 store。當某個 store 的 id 與你的儲存庫在其 origin remote 中的名稱相符時,錯誤訊息會指出該 store,以及選取它的 store: 行。OpenSpec 絕不會自行依名稱挑選 store,因為不同組織的儲存庫可能同名。

當 OpenSpec 選取 store 時,會在命令輸出之前印出 Using OpenSpec root: ...。

store: 行(store-only 專案) ​

在你專案的 openspec/config.yaml 中加入一行:

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

你或你的 agent 在專案內執行的所有操作,現在都會使用該 store,且不必輸入任何旗標:

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 會停止並顯示錯誤,列出你已註冊的 store。
  • 提交它:clone 你專案的隊友也會取得這一行。他們仍需要在各自的機器上註冊該 store(設定 store 的步驟 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,因為語言設定屬於外部 store 的設定。請在 store 根目錄執行 init,或直接編輯該設定。

你機器上的 defaultStore ​

如果你工作的每個專案都使用同一個 store,設定一次即可。當 OpenSpec 找不到旗標、本機 openspec/ 資料夾與 store: 行時,會改用它:

bash
# 當其他設定未指定 store 時,使用 team-plans
openspec config set defaultStore team-plans

# 取消設定
openspec config unset defaultStore

維持在本機執行的命令。 init、update、templates、schemas 以及 openspec schema 子命令只作用於目前目錄,且不接受 --store。

將儲存庫的規格與變更移入 store ​

若要將儲存庫從 repo-local 轉為 store-only:

  1. 將儲存庫 openspec/specs/ 與 openspec/changes/ 中的所有內容,移入 store 中同名的資料夾。
  2. 刪除這些已清空的資料夾,讓儲存庫的 openspec/ 資料夾只保留 config.yaml。
  3. 在該 config.yaml 中加入 store: 行。

在儲存庫內執行 openspec status,現在會以 Using OpenSpec root: team-plans 開頭。

在 store 中工作 ​

無論是你或你的 agent,工作流程都不變。Propose、apply 與 archive 的執行方式一如往常。唯一的差異是產出物建立的位置,上一節 已說明。

在 store-only 儲存庫內建立變更,該變更會落在 store 中:

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
  • 建立位置:位於 store 儲存庫中,而不是你的程式碼旁邊。
  • 分享方式:在你提交並推送 store 儲存庫之前,這項變更只存在於你的 checkout。隊友會在拉取後看到它。工作流程寫入的每個產出物也是如此。
  • 文件中的路徑:文件中只要出現 openspec/ 路徑,在 store 設定中,該資料夾就是 store 的資料夾。

當產出物建立在你意想不到的位置時,openspec doctor 會檢查你的設定而不做任何變更,並針對每項發現輸出修正方式:

bash
# 檢查目前的根目錄及其 store
openspec doctor
yaml
Doctor

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

References
  (none declared)

openspec context 會列出目前目錄所使用的根目錄與 store,適合在你想要相同概況但不想執行檢查時使用。

若要在同一個編輯器視窗中開啟 store 與儲存庫,讓你的 agent 能同時讀取兩者,請參閱 Worksets(beta)。

從其他 store 讀取 specs ​

你的 repo 可以保有自己獨立的 openspec/ 資料夾,同時仍能讓你的 agent 讀取其他 store 的 specs。在 repo 的 openspec/config.yaml 中,於 references: 底下宣告該 store:

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

References 是唯讀的。你的工作內容仍保存在你自己的 repo 中,而 reference 只會改變 agent 接收到的資訊。

當 workflow 建立一項產物時,其指令會附上一份所參考 store 的 specs 索引,每個項目都包含單行摘要,以及用來擷取該 spec 的確切指令:

xml
<referenced_stores>
<!-- Read-only upstream context. Fetch what you need; cite what you use. -->
Store team-plans (/Users/you/openspec/team-plans):
  - payments: Rules for charging and refunding customers.
  Fetch: openspec show <spec-id> --type spec --store team-plans
</referenced_stores>

Reference 也可以攜帶該 store 的 clone URL,方便尚未擁有該 store 的機器使用:

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

一旦宣告 URL,openspec doctor 便會將遺失的 store 轉換為可直接貼上執行的修正指示:

yaml
# output wrapped to fit
References
  - team-plans: ok (/Users/you/openspec/team-plans)
  - design-system: Referenced store 'design-system' is not registered on this machine.
    Fix: 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 絕不執行 clone、pull 或 push。過期的 checkout 在執行 pull 之前都會顯示過期的 specs,而 references 則是直接從磁碟上的內容讀取。
  • 每個 store 名稱僅限一個 checkout:以已註冊的名稱再註冊第二個資料夾會失敗,並附上先執行 openspec store unregister 的提示。