如何在多個 repo 共用 agent skills 而不分歧
將 skill 視為相依性,集中維護一個共用 repository,讓 8 個 repo 各自固定並檢視指定版本,避免複本悄悄分歧。
如何在多個儲存庫之間共用 agent skills
若要在多個儲存庫之間共用 agent skills,請停止複製檔案,改為建立相依性。維護一個 skills 儲存庫,為它建立 tag,並讓各專案固定使用指定的 tag。接著為每項 skill 加入 smoke test,並按照檢視相依性版本更新的方式,檢視每次版本更新。
這包含四個部分:共用的單一真實來源、各儲存庫固定的版本、每項 skill 的 smoke test,以及檢視流程。以下內容會說明每個部分存在的原因、2026 年推出的工具如何處理這些需求,以及如何在不使用任何外部服務的情況下,透過自架的 git remote 建立完整流程。
agent skill 是一個資料夾,其中包含 SKILL.md 檔案,以及所需的任何 script 和 reference file。若這個單位對你而言是新的,請先閱讀什麼是 agent skill,以及 SKILL.md 如何運作。本頁說明的是圍繞這個單位的供應鏈。
技能的存放位置,以及難以共用的原因
Claude Code 會從 3 個位置載入技能,技能文件列出了各個路徑。
~/.claude/skills/<skill-name>/SKILL.md是個人層級。它會載入到你的所有專案,但不會載入到其他人的專案。.claude/skills/<skill-name>/SKILL.md是專案層級。簽出該 repository 的人都會載入它。<plugin>/skills/<skill-name>/SKILL.md內含於 plugin 中。啟用該 plugin 的位置都會載入它。
對團隊而言,中間這個位置最實用,因為它會提交到版本庫,所有 clone 該 repo 的人都會取得它。但問題也從這裡開始。.claude/skills/ 中的技能屬於單一 repository。你有 8 個 repository,因此同一個技能會被複製 8 次。
frontmatter 無法解決這個問題。Agent Skills spec 允許 6 個鍵,而負責強制執行這項規範的發佈路徑,在你使用其他鍵時會列出允許的鍵:
Unexpected key(s) in SKILL.md frontmatter: argument-hint. Allowed properties are: allowed-tools, compatibility, description, license, metadata, name請注意缺少的項目:沒有 version 鍵。檔案內容不會記錄哪一份複本較新。這是合理的,因為技能是文件,不是套件。但這也表示版本管理必須由檔案外層的機制負責,而該機制需要由你建立。
問題一:8 份副本悄悄分歧
第一天使用複製貼上沒有問題。到了第 60 天就會失效。有人修正了 payments repo 中的錯誤指示,卻沒有同步修改其他 7 份。另一個人又在 orders 中加入分頁規則。現在,相同的 skill 名稱會因 agent 啟動所在的目錄不同而產生兩種不同的審查結果,而且兩位開發人員都不知道原因。
這項失敗不會產生明顯訊號,因為系統沒有錯誤狀態。skill 是文字內容。過時的指示會產生看似有把握但錯誤的回答,而這類錯誤的代價最高。agent 不會將你的副本與其他人的副本進行比對,因此唯一的訊號,就是有人發現兩個 repo 的內容不一致。
問題二:沒有任何機制鎖定版本
即使團隊將技能集中管理,常見的共用方式仍是執行複製步驟:設定指令碼、入職文件中的 curl 行,或同步資料夾的 shell 別名。這些方式都會安裝目前分支頂端的內容。
因此,即使兩位開發人員使用相同應用程式的相同 commit,也可能執行不同版本的指示,因為他們在不同日期執行同步。發生 agent 執行結果不佳的問題後,這也讓團隊無法回答關鍵問題:產生此結果的技能是哪個版本?如果沒有記錄修訂版本,該次執行就無法重現,錯誤報告也無法據此採取行動。
問題三:沒有人知道這項 skill 是否仍然有效
skill 沒有編譯器。它是提供給模型的指示,因此即使檔案逐位元組完全相同,也可能停止運作。模型升級後,遵循長篇指示的程度可能改變。skill 呼叫的命令列工具可能重新命名某個 flag。參考檔案中的 URL 可能開始回傳 404,導致 agent 根據錯誤頁面工作。
上述情況都不會明確報錯。agent 仍然會回答。只是答案比上個月更差,而這種變化很難在每次 pull request 中逐一察覺。
2026 年工具版本解決的問題
目前已有多種解法陸續推出,但對於版本應該存放在哪裡,結論並不一致。
鎖定檔。 Vercel Labs 提供的 skills 命令列工具(vercel-labs/skills,採用 MIT 授權;截至 2026 年 8 月 5 日為 v1.5.22)會從 git repository 將 skills 安裝到 agent 預期的目錄,並支援超過 70 種 agent 的目錄結構。npx skills add <repo> 用於安裝,npx skills update 用於升級,npx skills list 用於顯示目前已有的項目。安裝項目的記錄是每位使用者一份,而不是每個 repository 一份。該專案的開放請求(issue 283)要求加入 skills install 命令,從鎖定檔重新安裝所有已追蹤的 skill,讓第二台機器取得相同的項目集合。這項請求可視為目前狀態的報告。鎖定檔的概念已經確立,但每個專案各自管理鎖定檔的部分仍在建置中。
規格與測試。 SkillSpec 採取另一種方向。它將 SKILL.md 視為需要檢查的契約,而不是可以直接信任的文字說明;其目標是讓 skills「可遵循、可測試且可證明」。skillspec doctor <path> 會回報 agent 可能中斷流程的位置。skillspec boundary map <path> 會回報 skill 能存取的範圍,skillspec boundary assess <path> 則依風險為這些結果排序。它是以 Rust 撰寫的 crate,採用 MIT 或 Apache 2.0 雙重授權;截至 2026 年 7 月 29 日為 0.2.2 版。請安裝指定版本,而不是最新版本:
cargo install skillspec --version 0.2.2 --locked
skillspec --version--locked 會使用該 crate 發布時所採用的相依套件版本進行建置,因此建置不會在過程中產生版本漂移。skillspec --version 應輸出 0.2.2。若顯示其他數字,表示你的 PATH 中有較早的舊版 binary 優先被找到。
供應商實務。 Google 在一篇說明 如何建置、測試及擴充 agent skills 的文章中,介紹了其在 google/skills 建置 skills 的方式。撇開規模不談,其機制就是一般的持續整合(CI)。每個 skill 在合併前,都必須通過 frontmatter metadata、行數、目錄結構及命名規則的 linter 檢查。任何回傳 404 的 URL 都會讓 link checker 使建置失敗,藉此抓出 agent 自行產生但看似合理的連結。作者必須在 skill 旁提供 evaluation prompt 套件與評分規則。排程 evaluation job 會每週針對整個 library 執行測試,以偵測回歸問題;每個 skill 也都有指定負責人,品質下降時必須由該負責人修正。
三個答案背後的共同模式
你不必在這三者中擇一。它們背後只有一種結構,而純 git 就能提供完整支援。
- 單一真實來源。每個 skill 只有一個存放位置,各個 repository 都指向該位置,而不是各自保存副本。
- 每個 repository 固定一個版本。每個專案記錄所使用的確切 revision,因此升級就是在該專案中建立一個具備作者與日期的 commit。
- 每個 skill 都有 smoke test。提供一項可執行的檢查,確認該 skill 仍能產生其承諾的結果。
- 審查流程。共用 skill 的變更必須經過審查,每個使用者在採用前都能看到差異。
這就是相依性的結構。skill 成為共用 artifact 的速度,比相關工具的發展更快。因此,使用你已經信任的工具,是最安全的做法。
小型團隊使用自架 Git 遠端儲存庫的配置
一個儲存庫存放所有技能。其他內容都不放在其中,因此其歷史記錄會成為指令的變更日誌。
agent-skills/
skills/
api-review/
SKILL.md
release-notes/
SKILL.md
tests/
api-review.sh
release-notes.sh
CHANGELOG.md以標籤表示發布版本。請使用附註標籤,因為其中包含訊息與日期;訊息應說明使用者為何需要升級:
git tag -a v1.4.0 -m "api-review: require pagination on list endpoints"
git push origin v1.4.0無論遠端儲存庫使用 Gitea、Forgejo、GitLab,或是自有 VPS 上透過 SSH 使用 bare repository,以下內容都不需變更。整體架構就是 Git 加上 symlink。
使用 git submodule 固定版本
submodule 會在你的 repository 中記錄另一個 repository 的單一確切 commit。這筆記錄就是固定版本。在每個使用該 submodule 的專案中:
git submodule add https://git.example.com/team/agent-skills.git vendor/agent-skills
git -C vendor/agent-skills fetch --tags
git -C vendor/agent-skills checkout v1.4.0
mkdir -p .claude/skills
ln -s ../../vendor/agent-skills/skills/api-review .claude/skills/api-review
git add .gitmodules vendor/agent-skills .claude/skills/api-review
git commit -m "Pin shared agent skills to v1.4.0"symlink 是這項機制能運作的關鍵。專案層級的 skill 項目可以是指向磁碟其他位置目錄的 symlink,而 Claude Code 會沿著它解析,並從目標讀取 SKILL.md。因此,該 skill 會以一般專案 skill 的形式載入,但實際檔案內容位於你指定 commit 的 submodule 中。
檢查固定版本:
git submodule status正常的輸出行會以空格開頭,接著依序顯示 commit、path,以及最近的 tag:
4d1a7c2f0b93e5a1c8d6f2b40e7a95c3d1f8b602 vendor/agent-skills (v1.4.0)開頭的 - 表示 submodule 尚未初始化,因此 .claude/skills/api-review 沒有指向任何內容,該 skill 也不會顯示錯誤而靜默地無法載入。使用 git submodule update --init 修正。開頭的 + 表示目前 checkout 的 commit 與記錄的 commit 不同,因此該開發者執行的是其他人沒有的指示。新的 clone 需要執行 git clone --recurse-submodules;這一行應寫入 README,因為單純執行 clone 會讓 vendor/agent-skills 保持空白,且不會顯示錯誤。
升級必須刻意進行,這正是固定版本的目的:
git -C vendor/agent-skills fetch --tags
git -C vendor/agent-skills diff v1.4.0 v1.5.0 -- skills/
git -C vendor/agent-skills checkout v1.5.0
git add vendor/agent-skills
git commit -m "Bump shared agent skills to v1.5.0"diff 行是審查路徑。它會顯示其他使用該 submodule 的 repository 都將套用的相同變更,而且適合放入 pull request。
改用外掛市集進行固定版本
如果不希望每位開發人員都學習 submodule,Claude Code 外掛系統會替你處理散布,而且支援自架的遠端來源。請在 skills repository 的 .claude-plugin/marketplace.json 放置目錄:
{
"name": "acme-agents",
"owner": { "name": "Platform team", "email": "platform@example.com" },
"plugins": [
{
"name": "team-skills",
"description": "Shared review and release skills",
"version": "1.4.0",
"source": {
"source": "url",
"url": "https://git.example.com/team/agent-skills.git",
"ref": "v1.4.0",
"sha": "4d1a7c2f0b93e5a1c8d6f2b40e7a95c3d1f8b602"
}
}
]
}這裡涉及兩個不同的來源,混淆兩者是最常見的錯誤。市集來源是指取得目錄本身的位置,接受以 ref 指定 branch 或 tag,但不接受 sha。目錄內的外掛來源則同時接受兩者;兩者都設定時,sha 才是實際採用的固定版本。因此,exact-commit pin 應放在目錄項目中。
接著,各個使用中的 repository 在其已提交的 .claude/settings.json 中宣告此市集:
{
"extraKnownMarketplaces": {
"acme-agents": {
"source": {
"source": "url",
"url": "https://git.example.com/team/agent-skills.git",
"ref": "v1.4.0"
}
}
},
"enabledPlugins": {
"team-skills@acme-agents": true
}
}信任 project folder 的團隊成員會收到安裝市集的提示,系統也會為其啟用外掛,不必另外透過 wiki 頁面說明操作方式。此時 skills 會對應至 /team-skills:api-review,因為外掛 skills 會以外掛名稱建立命名空間,不會與相同名稱的 project skill 衝突。推送新 tag 後,使用端執行 /plugin marketplace update acme-agents 以重新整理,若安裝摘要要求執行 /reload-plugins,再執行該指令。
撰寫單一 skill 的 smoke test
smoke test 是針對含有已知故障的 fixture 執行腳本化 agent,並加入一項 assertion。Claude Code 可透過 -p 以非互動方式執行,使用者呼叫的 skill 也能在此模式中運作:將 /skill-name 放入 prompt 字串,執行開始前就會展開。
#!/usr/bin/env bash
set -euo pipefail
claude -p "/api-review Read fixtures/orders-api.md and list the rule ids it breaks." \
--allowedTools "Read" \
--output-format json \
--json-schema '{"type":"object","properties":{"rule_ids":{"type":"array","items":{"type":"string"}}},"required":["rule_ids"]}' \
| jq -e '.structured_output.rule_ids | index("pagination-required")' > /dev/nullfixtures/orders-api.md 是包含一項刻意故障的短檔案。Assertion 要確認 skill 指出該故障。當 filter 產生 null 時,jq -e 會以非零狀態結束,因此停止捕捉種入故障的 skill 會使腳本失敗。執行失敗時,claude 本身會以非零狀態結束,而 set -euo pipefail 會將任一失敗轉換為失敗的測試。
模型在不同執行期間會改寫答案,因此不要對完整句子進行 assertion。請針對 skill 應輸出的識別碼,或你要求的 schema 欄位進行 assertion,並讓 fixture 保持精簡,以降低每次執行的成本。
在 CI 中加入 --bare。若未加入,claude -p 會載入互動式工作階段使用的相同內容,包括 hooks、plugins,以及執行該工作階段之機器上的 CLAUDE.md,因此團隊成員的個人設定可能改變結果。Bare mode 會略過所有自動探索,因此也會略過你要測試的 skill;請明確載入該 skill。Bare mode 也不會讀取你的 subscription login,因此請先在環境中設定 ANTHROPIC_API_KEY:
claude --bare -p "/team-skills:api-review Read fixtures/orders-api.md and list the rule ids it breaks." \
--plugin-dir vendor/agent-skills \
--allowedTools "Read" \
--output-format json使用 --output-format stream-json 時,執行的第一個事件會回報已載入的 plugins,並為未載入的 plugins 附帶 plugin_errors 陣列。若 plugin_errors 非空,請讓 CI 工作失敗。這能捕捉指向已不存在 revision 的 pin;否則這類問題看起來只像 agent 悄悄忽略了你的團隊規範。
共享 skill 是可執行的指令
有兩項功能使這個說法成為字面上的事實,而且當檔案來自其他團隊時,兩者都很重要。
首先,SKILL.md 可以在模型讀取任何內容前執行 shell 命令。內文中的下列行會進行預處理:
- Current branch: !`git rev-parse --abbrev-ref HEAD`命令會在載入 skill 的機器上執行,輸出會取代模型所接收文字中的預留位置。以三個反引號接著 ! 開頭的圍欄區塊,也會以相同方式執行多個命令。這些操作在執行期間不會逐一取得核准。讀取共享 skill,就等於讀取其中的命令替換內容。
其次,frontmatter 可以預先核准工具。allowed-tools 會在觸發該 skill 的回合中,授予列出的工具,且不顯示權限提示。對 project skill 而言,使用者接受該資料夾的 workspace trust 對話方塊後,這項授權才會生效。Claude Code 文件清楚說明了後果:信任 repository 前,請先檢查 project skill,因為 skill 可以自行授予廣泛的工具存取權。
因此,請將 skill 升級完全比照相依套件升級處理。在機制允許的情況下,使用確切的 commit 固定版本,因為 tag 可能被移動,而 branch 定義上就會移動。在鎖定的機器上,設定中的 "disableSkillShellExecution": true 會將每個命令替換為字面文字 [shell command execution disabled by policy],而不予執行;若透過 managed settings 套用,使用者無法覆寫這項設定。Bundled skill 和 managed skill 不受此設定影響。
同樣的注意事項也適用於 skill 讀取的內容。會執行 env 或開啟 config file 的 skill,會將找到的任何內容載入模型的 context;這正是 讓 secret 遠離所執行的 agent 所涵蓋的問題。會擷取網頁或執行 query 的 skill,則是將相同的暴露風險指向外部,因為擷取的文字會進入 context,看起來與你撰寫的指令完全相同;在 將 agent 指向自己的 SearXNG instance 進行網頁搜尋 前,值得先了解這項邊界。
升級版本時應閱讀的內容
- 每個
SKILL.md本文的差異,因為這些文字就是 agent 將遵循的指示。 - 每個命令替換,因為 skill 載入時會在你的電腦上執行這些命令。
allowed-tools的任何變更,因為該行會在未提示的情況下授予工具使用權。- tag 背後的測試執行結果。如果共用 repository 在 CI 中執行自己的 smoke test,所固定的 tag 應附有通過的執行結果。
如果 reviewer 無法在 10 分鐘內讀完整份差異,表示該 skill 已經過於龐大。請將它拆分。相同原則也適用於 agent 會讀取的 repository 文件:將持久規則保留在 AGENTS.md 與 HUMAN.md 的拆分方式 所述的檔案中,將架構理由寫在 為 agent 撰寫的 DESIGN.md 中,並讓 skill 維持為範圍明確的程序。
模型或工具變更導致技能失效
技能未經任何人編輯,底層仍可能發生多項變更。模型升級會改變長指令的遵循可靠性,因此原本依賴模型執行到第九步的技能,可能不再執行到該步驟。命令列工具重新命名旗標後,代理程式仍會使用舊旗標,讀取錯誤訊息後自行處理。參照的 URL 也可能開始回傳 404。代理程式 harness 改變技能選取方式後,原本能成功匹配的 description 可能不再獲選。
因此,在這種架構中,smoke test 承擔了關鍵作用。除了每次 push 時執行,也應排程執行每個技能的測試。Google 每週針對完整技能庫執行評估工作,原因就在於此。對只有 ten 個技能的團隊而言,在小型 VPS 上設定每週 cron job 即已足夠。這是開發人員發現問題前,得知技能失效的唯一方式。
可攜性同樣有幫助。Agent Skills spec 將 frontmatter 限制為 six 個 keys,因此依照該規格撰寫的技能,可在不同於原始開發工具的其他工具中載入;而每增加一個特定 harness 的 key,就等於押注於單一 vendor。撰寫能在模型替換後持續運作的技能,是另一項專門技術,詳見 讓技能適用於任何模型。
FAQ
如何在多個儲存庫共用一項 agent skill?
將 skill 放在專用的 git 儲存庫中,為其版本建立 tag,讓各個使用專案參照 tag,而不是複製檔案。有兩種方式可行。git submodule 會記錄確切的 commit,從 .claude/skills/<name> 建立指向該 submodule 的 symlink,即可讓它以一般專案 skill 的形式載入。Plugin marketplace 則透過 /plugin 執行相同工作,並在使用端儲存庫的 .claude/settings.json 中宣告固定版本。兩者都會將版本記錄在 git 歷史中,因此可以確認特定 agent 執行所使用的指示。
可以將 agent skill 固定到特定版本嗎?
不能直接在 SKILL.md 中設定,因為該 frontmatter 沒有 version key。版本固定必須由檔案外層的機制處理。git submodule 本身會固定確切的 commit。在 Claude Code plugin marketplace 中,plugin source 可使用 ref 指定 branch 或 tag,並使用 sha 指定確切的 commit;兩者同時存在時,以 sha 為準。marketplace source 本身只接受 ref。建議固定 commit,因為 tag 在審查完成後仍可能被移動。
skill 的 smoke test 應驗證什麼?
驗證穩定的內容。針對包含已知錯誤的 fixture,以非互動方式執行 skill,然後確認輸出中出現特定識別碼,例如該 skill 應回報的規則 ID。使用 --output-format json 和 --json-schema 要求結構化輸出,可讓檢查結果精確;jq -e 則會在缺少該值時讓 script 失敗。不要驗證完整句子,因為模型在不同執行期間可能改寫回答。
從其他團隊的儲存庫安裝共用 skill 是否安全?
應將它視為程式碼相依性,因為它是可執行的指示。SKILL.md 可透過 ! command substitution 形式,在載入時執行 shell 命令;frontmatter 的 allowed-tools 欄位則可在不提示的情況下預先核准工具。每次更新版本時都應檢視 diff,固定到確切的 commit 而不是 branch,並優先使用由自有團隊控制的來源。在受管理的電腦上,設定中的 "disableSkillShellExecution": true 可完全阻止 command substitution 執行。
共用 skill 能在 Claude Code 以外的 agent 中運作嗎?
這取決於使用哪些 frontmatter。Agent Skills spec 定義六個 key:name、description、license、compatibility、metadata 和 allowed-tools。只使用這些 key 的 skill,可在實作該 spec 的工具間載入,也能在 Claude Code 中直接載入。其他工具專用的 key,以及超出 spec 的 body 功能,可能會在其他環境中遭到忽略或拒絕。因此,預計廣泛共用的 skill 不應包含這些內容。