worktree 文件更精確地說明,預設基礎是遠端儲存庫的預設分支,通常是 origin/main。您的功能分支並不在其中,您本地 main 分支上尚未推送的提交也不會包含在內。
解決方案只需一個設定,但要確認您是否需要它,則需要執行幾個 Git 指令。我本人並未實際執行過這個教學,它是根據目前的 Claude Code 和 Git 文件所建構,因此如果某個步驟在您的版本上行為不同,worktree 文件才是最終的參考依據。
步驟 1:建立遠端儲存庫沒有的功能分支
您需要一個具有 origin 遠端儲存庫的專案,這一點很重要。如果沒有配置遠端儲存庫,或者 origin/HEAD 未被快取且無法取得,Claude Code 會退回到您的本地 HEAD。一個沒有遠端的臨時儲存庫將無法重現此問題。
請取一個小型 Node 專案(package.json 中有 "type": "module"),其 main 分支已推送。建立一個新分支並新增一個函式:
```javascript
// src/orders.js (added on feature/refund)
export function refund ( order ) {
if ( order . status !== " paid " ) {
throw new Error ( " only paid orders can be refunded " );
}
return { ... order , status : " refunded " };
}
```
```bash
git switch -c feature/refund
git add src/orders.js
git commit -m "Add refund() for paid orders"
```
在委派任務之前請先提交變更。新的 Git worktree 是從一個提交檢出的,因此無論 base 設定為何,您尚未提交的編輯都會保留在您的工作區中。在此同時,請將 .claude/worktrees/ 加入 .gitignore,因為 Claude Code 會在此處建立 worktree,您不希望它們在您的主要工作區中顯示為未追蹤檔案。
步驟 2:子代理檔案
專案子代理位於 .claude/agents/ 目錄中。將以下內容儲存為 .claude/agents/test-writer.md:
```markdown
---
name: test-writer
description: Writes node:test tests for code named in the request
tools: Read, Write, Edit, Bash, Grep, Glob
isolation: worktree
---
First run git log --oneline -3 and git branch --show-current and include both outputs in your reply. If the function you were asked to test does not exist in this checkout, say so and stop without changing any file. Otherwise write tests under test/ with node:test, run node --test, and commit the tests on your current branch. Reply with the branch name and the commit hash.
```
name 和 description 是兩個必填欄位。這裡關鍵的一行是 isolation: worktree,請務必精確拼寫,因為 frontmatter 參考資料指出,Claude Code 會忽略它不認識的欄位而不會報告錯誤,因此拼寫錯誤會導致子代理悄悄地編輯您的主要工作區。
Claude Code 會在幾秒鐘內偵測到對 .claude/agents/ 的編輯,但新 agents 目錄中的第一個代理檔案除外,此時需要重啟 Claude Code 一次才能載入。在 feature/refund 分支上啟動 Claude Code,並透過名稱呼叫子代理,這樣 Claude 就不會選擇其他代理。
您可以手動輸入 @agent-<name>,例如:@agent-test-writer add tests for refund() in src/orders.js。
上述提示詞要求子代理首先列印自己的 Git log。如果其最頂層的提交是您已推送的 main 分支尖端,而不是「Add refund() for paid orders」,那麼您就成功重現了這個問題。
步驟 3:使用 Git 檢查基礎
第一次執行沒有任何變更,因此不會留下 worktree,而子代理列印的 Git log 是它從何處開始的唯一記錄。Git 可以告訴您該記錄是否符合預期。預設的基礎是 origin/HEAD,因此請檢查您的功能提交是否在其中:
```bash
git remote set-head origin --auto # cache origin/HEAD if missing
git rev-parse --abbrev-ref origin/HEAD
git merge-base --is-ancestor feature/refund origin/HEAD
echo $?
```
第二個指令會顯示預設 worktree 從哪個分支開始,通常是 origin/main。根據 git-merge-base 手冊,如果第一個提交是第二個提交的祖先,--is-ancestor 會以狀態碼 0 退出,否則為 1。這裡的 1 表示您的功能分支尖端不在子代理開始的分支中。
您也可以比較雜湊值。執行 git log --oneline -1 origin/HEAD,並將其與子代理自己的 Git log 的第一行並列,它們應該匹配。還有一個細節:當儲存庫在過去 24 小時內未被 fetch 時,Claude Code 會在建立 worktree 之前 fetch 預設分支,最長五秒,如果 fetch 失敗則使用快取的參考。因此,基礎可能比您上次 pull 的 origin/main 更新。
步驟 4:將 worktree.baseRef 設定為 "head"
worktree.baseRef 接受兩個值:"fresh"(預設值):從遠端儲存庫的預設分支建立分支。"head":從您目前的本地 HEAD 建立分支,包含您尚未推送的提交和功能分支狀態。這是文件推薦的選項,用於「需要操作進行中工作的隔離子代理」。
您不能將其設定為分支名稱。對於特定的現有分支,請自行使用 Git 建立 worktree。您可以將其放入 .claude/settings.local.json 中自行嘗試,或者如果您的團隊希望每個 worktree 都從當前工作開始,則放入已提交的 .claude/settings.json 中:
```json
{
"worktree" : {
"baseRef" : "head"
}
}
```
此設定涵蓋 Claude Code 建立的所有 worktree,因此 claude --worktree 會話也會從 HEAD 建立分支。這是一個權衡:"fresh" 對於應該從乾淨狀態開始的無關任務來說是更好的預設值,而 "head" 則適用於擴展尚未合併的工作。
在 feature/refund 分支上啟動一個新的 Claude Code 會話,並發送相同的 @agent-test-writer 指令。這次子代理應該能找到 refund() 函式,撰寫測試並將其提交到自己的分支上。
步驟 5:清理規則,然後合併回主分支
子代理的 worktree 遵循兩條規則。如果子代理完成時沒有任何變更,其 worktree 會立即被移除。如果子代理有變更,則會保留在磁碟上;一個與 cleanupPeriodDays 設定相關的定期掃描會在稍後將其移除,但會跳過任何仍包含已變更或未追蹤檔案或未推送提交的 worktree。
因此,如果第一次執行如提示詞所說沒有觸碰任何檔案而停止,則不會留下任何東西,git worktree list 只會顯示您的主要工作區。如果第二次執行提交了測試,其 worktree 仍然存在。
找到它:git worktree list。尋找 .claude/worktrees/ 下方的行。末尾括號中的名稱是子代理的分支。其命名方案沒有文件說明,因此請從此輸出中讀取,而不是猜測:
```bash
AGENT_BRANCH = <branch from git worktree list>
git merge-base --is-ancestor feature/refund "$AGENT_BRANCH"
echo $?
git log --oneline feature/refund.."$AGENT_BRANCH"
```
狀態碼 0 表示您的功能提交在子代理的分支中。帶有兩個點的 log 只列出子代理在其之上新增的提交。
從您的主要工作區合併,仍停留在 feature/refund 分支上:
```bash
git merge --ff-only "$AGENT_BRANCH"
git worktree remove .claude/worktrees/<name>
git branch -d "$AGENT_BRANCH"
```
--ff-only 僅在 feature/refund 自子代理啟動以來沒有移動過時才有效。如果您在此期間進行了提交,請使用普通的 git merge。在刪除分支之前移除 worktree,因為 Git 不會刪除在 worktree 中已檢出的分支。
如果 git worktree remove 因 worktree 被鎖定而拒絕,請檢查誰持有該鎖。Claude Code 在代理執行時會持有 Git worktree 鎖,並在代理完成時釋放它;掃描也會釋放因會話進程退出而留下的鎖。如果仍有鎖定,請先執行 git worktree unlock .claude/worktrees/<name>。除非您已確認該資料夾中沒有您想要的內容,否則不要使用 --force。
在 Hermes 中,同樣的規則也適用於更高一層
我是 Hermes IDE 的開發者,因此請考慮到這一點。Hermes 在任務層級而非子代理層級運作:⌘N(Windows 和 Linux 上為 Ctrl+Shift+N)會為每個任務在自己的 worktree 中啟動一個 hermes/<name> 分支,並將任務作為代理的第一個提示詞。
當工作完成時,「Land」操作會提交、開啟一個 pull request 或本地合併到任務開始的分支中,並且可以撤銷。Hermes 2.3.4 中的 ⌘N 新任務表單顯示了輸入的任務、Claude Code 的晶片、orders-api 專案、一個新的 hermes/ worktree、接受編輯、模型和工作量,以及 claude 命令的「Hermes 將執行」預覽。
這兩層是堆疊的。如果 Claude Code 在 Hermes 任務中執行並生成您的 test-writer 子代理,則相同的 worktree.baseRef 規則適用。worktree 文件指出,在 worktree 內部,"head" 會解析為該 worktree 的 HEAD,而不是主要工作區的 HEAD。
設定為 "head" 後,子代理會從 hermes/<name> 任務分支建立分支。以下三種檔案中的任何一種都有效:您的使用者層級 ~/.claude/settings.json、在任務開始的分支上提交的 .claude/settings.json,或主要工作區的 .claude/settings.local.json,設定文件指出 Claude Code 即使在 macOS 和 Linux 的 worktree 內部也會讀取它。
使用預設值時,子代理會像以前一樣從遠端的預設分支建立分支。Review Desk 的 Worktrees 標籤列出了 Hermes 建立的任務 worktree,包含分支、時間和磁碟大小,這有助於您決定要合併哪些以及要丟棄哪些。Review Desk 的 Worktrees 標籤顯示了 ~/code 下 orders-api、web-app 和 orders-types 各有一個 Hermes worktree,每個 worktree 的 hermes/ 分支、任務、時間和磁碟大小,以及可用的磁碟空間。
Hermes 是免費的,在 BSL 1.1 下開源,並可在 macOS、Windows 和 Linux 上運行。它不隸屬於 Anthropic、OpenAI、Nous Research 或任何代理供應商。如果您想嘗試任務層級的版本,請下載 Hermes。
如果這篇文章對您有用,子代理的實用性取決於您提供給它的上下文,而它開始檢出的工作區就是該上下文的一部分。《AI Agents Pocket Guide》涵蓋了代理之間委派、隔離和交接工作的模式。它是《Pocket Guides for Developers》系列八本短書之一,涵蓋了代理、RAG、提示詞、可觀察性、事件、資料庫和系統設計。
如果您在一個儲存庫上運行多個代理,Hermes IDE 可以免費試用,其程式碼可在 GitHub 上找到。