Claude Code Worktree Subagents uebersehen den Feature Branch: baseRef auf head setzen
Wer Claude Code Worktree Subagents nutzt, muss baseRef auf head setzen, damit diese den eigenen Feature Branch sehen koennen. Sonst arbeiten die Agenten am falschen Stand.

Du hast vor einer Stunde refund() geschrieben. Der Commit liegt auf feature/refund. Du übergibst ihn an einen Subagenten: "Schreibe Tests für refund() in src/orders.js." Der Subagent kommt zurück und teilt dir mit, dass es in dieser Datei kein refund() gibt.
Er hat nicht unrecht. In dem Checkout, der ihm gegeben wurde, existiert die Funktion nicht.
Claude Code erlaubt es, einen benutzerdefinierten Subagenten in einem eigenen Git-Worktree laufen zu lassen, mit einer einzigen Frontmatter-Zeile: isolation: worktree. Die Subagent-Dokumentation sagt, dass der Worktree "standardmäßig von deinem Default-Branch statt vom HEAD der übergeordneten Session aus gebrancht wird". Die Worktree-Dokumentation ist präziser: Die Basis ist standardmäßig der Default-Branch des Repositories auf dem Remote, meist origin/main. Dein Feature-Branch ist darin nicht enthalten. Ebenso wenig Commits auf deinem lokalen main, die du noch nicht gepusht hast.
Die Lösung ist eine einzige Einstellung. Zu prüfen, ob du sie brauchst, erfordert ein paar Git-Befehle. Ich habe diesen Durchlauf nicht selbst ausgeführt: Er basiert auf der aktuellen Claude-Code- und Git-Dokumentation, falls sich also ein Schritt auf deiner Version anders verhält, ist die Worktree-Dokumentation die maßgebliche Quelle.
Du brauchst ein Repository mit einem origin-Remote. Das ist wichtig. Wenn kein Remote konfiguriert ist oder origin/HEAD nicht gecacht ist und nicht geholt werden kann, fällt Claude Code auf deinen lokalen HEAD zurück. Ein Wegwerf-Repository ohne Remote wird das Problem nicht reproduzieren.
Nimm ein kleines Node-Projekt ( "type": "module" in package.json ), dessen main gepusht ist. Erstelle einen Branch und füge eine Funktion hinzu:
// src/orders.js (hinzugefügt auf feature/refund) export function refund ( order ) { if ( order. status!== " paid " ) { throw new Error ( " only paid orders can be refunded " ); } return {... order, status: " refunded " }; } git switch -c feature/refund git add src/orders.js git commit -m "Add refund() for paid orders" Commite, bevor du delegierst. Ein neuer Git-Worktree wird von einem Commit ausgecheckt, daher bleiben uncommittete Änderungen in deinem Checkout, unabhängig davon, welche Basiseinstellung gilt.
Füge in diesem Zuge.claude/worktrees/ zur.gitignore hinzu. Dort legt Claude Code seine Worktrees an, und du willst nicht, dass sie als ungetrackte Dateien in deinem Haupt-Checkout auftauchen.
Projekt-Subagenten liegen in.claude/agents/. Speichere Folgendes als.claude/agents/test-writer.md:
--- 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 und description sind die beiden Pflichtfelder. isolation: worktree ist die Zeile, die hier entscheidend ist. Schreibe sie exakt: Laut der Frontmatter-Referenz ignoriert Claude Code ein unbekanntes Feld ohne Fehlermeldung, ein Tippfehler führt also zu einem Subagenten, der stillschweigend deinen Haupt-Checkout bearbeitet.
Claude Code übernimmt Änderungen an.claude/agents/ innerhalb von Sekunden, ausgenommen die erste Agent-Datei in einem neuen agents-Verzeichnis: Starte Claude Code einmal neu, um sie zu laden.
Starte Claude Code auf feature/refund und rufe den Subagenten beim Namen auf, damit Claude keinen anderen wählt. Du kannst @agent-<name> von Hand eintippen:
@agent-test-writer add tests for refund() in src/orders.js Der obige Prompt veranlasst den Subagenten, zuerst sein eigenes git log auszugeben. Wenn sein oberster Commit dein gepushter main-Tip ist und nicht "Add refund() for paid orders", hast du das Problem reproduziert.
Der erste Lauf ändert nichts, hinterlässt also keinen Worktree, und das vom Subagenten ausgegebene git log ist der einzige Beleg dafür, wo er gestartet ist. Git verrät dir, ob dieser Beleg passt. Die Standardbasis ist origin/HEAD, prüfe also, ob dein Feature-Commit darin enthalten ist:
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 $? Der zweite Befehl nennt den Branch, von dem ein Standard-Worktree startet, meist origin/main. Laut dem Git-Merge-Base-Handbuch verlässt sich --is-ancestor mit Status 0, wenn der erste Commit ein Vorfahre des zweiten ist, und mit 1, wenn nicht. Eine 1 hier bedeutet, dass dein Feature-Tip nicht im Branch enthalten ist, von dem der Subagent gestartet ist.
Vergleiche auch die Hashes. Führe git log --oneline -1 origin/HEAD aus und stelle es neben die oberste Zeile des eigenen git log des Subagenten. Sie sollten übereinstimmen.
Noch ein Detail: Wenn das Repository in den letzten 24 Stunden nicht geholt wurde, holt Claude Code den Default-Branch, bevor es den Worktree erstellt, begrenzt auf fünf Sekunden, und verwendet den gecachten Ref, falls dieser Fetch fehlschlägt. Die Basis kann also neuer sein als das origin/main, das du zuletzt gepullt hast.
Du kannst es nicht auf einen Branch-Namen setzen. Für einen bestimmten vorhandenen Branch erstellst du den Worktree selbst mit git.
Lege es in.claude/settings.local.json ab, um es selbst auszuprobieren, oder in die committete.claude/settings.json, wenn dein Team möchte, dass jeder Worktree vom aktuellen Stand startet:
{ "worktree": { "baseRef": "head" } } Diese Einstellung gilt für jeden Worktree, den Claude Code erstellt, daher branched auch claude --worktree-Sessions von HEAD. Das ist der Kompromiss. "fresh" ist die bessere Standardeinstellung für unabhängige Aufgaben, die sauber starten sollen. "head" ist für die Weiterarbeit an Noch-nicht-gemergtem.
Starte eine neue Claude-Code-Session auf feature/refund und schicke dieselbe @agent-test-writer-Zeile. Diesmal sollte der Subagent refund() finden, Tests schreiben und sie auf seinem eigenen Branch committen.
Subagent-Worktrees folgen zwei Regeln. Ein Subagent, der ohne Änderungen abschließt, bekommt seinen Worktree sofort entfernt. Einer mit Änderungen bleibt auf der Festplatte; eine periodische Bereinigung, an dein cleanupPeriodDays-Setting gebunden, entfernt ihn später, überspringt aber jeden Worktree, der noch geänderte oder ungetrackte Dateien oder ungepushte Commits enthält.
Wenn der erste Lauf also, wie der Prompt es verlangte, ohne eine Datei anzufassen, gestoppt hat, bleibt nichts zurück, und git worktree list zeigt nur deinen Haupt-Checkout. Wenn der zweite Lauf Tests committet hat, ist sein Worktree noch da. Finde ihn:
git worktree list Such die Zeile unter.claude/worktrees/. Der Name in Klammern am Ende ist der Branch des Subagenten. Sein Namensschema ist nicht dokumentiert, lies ihn also aus dieser Ausgabe, statt zu raten:
AGENT_BRANCH = <branch from git worktree list> git merge-base --is-ancestor feature/refund " $AGENT_BRANCH " echo $? git log --oneline feature/refund.. " $AGENT_BRANCH " Eine 0 bedeutet, dass dein Feature-Commit im Branch des Subagenten enthalten ist. Das Log mit zwei Punkten listet nur die Commits auf, die der Subagent oben aufgesetzt hat.
Merge aus deinem Haupt-Checkout, weiterhin auf feature/refund:
git merge --ff-only " $AGENT_BRANCH " git worktree remove.claude/worktrees/<name> git branch -d " $AGENT_BRANCH " --ff-only funktioniert, wenn sich feature/refund seit dem Start des Subagenten nicht bewegt hat. Wenn du in der Zwischenzeit committet hast, verwende ein normales git merge. Entferne den Worktree, bevor du den Branch löschst, denn Git löscht keinen Branch, der in einem Worktree ausgecheckt ist.
Wenn sich git worktree remove weigert, weil der Worktree gesperrt ist, prüfe, wer die Sperre hält. Claude Code hält eine Git-Worktree-Sperre, während der Agent läuft, und gibt sie frei, wenn der Agent fertig ist; die Bereinigung gibt auch eine Sperre frei, die von einer Session mit beendetem Prozess zurückgeblieben ist. Falls noch eine besteht, führe zuerst git worktree unlock.claude/worktrees/<name> aus. Greife nicht zu --force, es sei denn, du hast geprüft, dass in diesem Ordner nichts liegt, das du brauchst.
Ich baue Hermes IDE, bewerte diesen Abschnitt also vor diesem Hintergrund. Hermes arbeitet auf Task-Ebene statt auf Subagent-Ebene: ⌘N (Ctrl+Shift+N auf Windows und Linux) startet jede Aufgabe auf ihrem eigenen hermes/<name>-Branch in ihrem eigenen Worktree, mit der Aufgabe als erstem Prompt des Agenten. Ist die Arbeit fertig, committet die Land-Aktion, öffnet einen Pull Request oder mergt lokal in den Branch, von dem die Aufgabe gestartet ist, und sie lässt sich rückgängig machen.
Das ⌘N-New-Task-Sheet in Hermes 2.3.4: die eingegebene Aufgabe, Chips für Claude Code, das orders-api-Projekt, ein neuer hermes/-Worktree, Accept edits, Modell und Effort sowie die "Hermes will run"-Vorschau des claude-Befehls.
Die beiden Ebenen stapeln sich. Läuft Claude Code innerhalb einer Hermes-Task und startet deinen test-writer-Subagenten, gilt dieselbe worktree.baseRef-Regel. Die Worktree-Dokumentation besagt, dass sich innerhalb eines Worktrees "head" auf den HEAD dieses Worktrees auflöst, nicht auf den des Haupt-Checkouts. Mit gesetztem "head" branched der Subagent vom hermes/<name>-Task-Branch. Eine von drei Dateien genügt: deine benutzerweite ~/.claude/settings.json, eine auf dem Task-Start-Branch committete.claude/settings.json oder die.claude/settings.local.json des Haupt-Checkouts, die laut Settings-Dokumentation Claude Code auch aus einem Worktree heraus auf macOS und Linux liest. Mit dem Standardwert branched der Subagent vom Default-Branch des Remotes, wie zuvor.
Der Worktrees-Tab des Review Desk listet die von Hermes angelegten Task-Worktrees auf, mit Branch, Alter und Plattengroesse. Das hilft dabei zu entscheiden, was gemerged und was verworfen werden soll.
Der Worktrees-Tab des Review Desk zeigt je einen Hermes-Worktree fuer orders-api, web-app und orders-types unter ~/code, mit dem jeweiligen hermes/-Branch, Task, Alter und Plattengroesse sowie dem freien Speicherplatz.
Hermes ist kostenlos, unter der BSL 1.1 als Quelloffen verfuegbar und laeuft auf macOS, Windows und Linux. Das Projekt steht in keiner Verbindung zu Anthropic, OpenAI, Nous Research oder einem anderen Agent-Anbieter. Wer die Task-basierte Version ausprobieren moechte, kann Hermes herunterladen.
Ein Subagent ist nur so nuetzlich wie der Kontext, den man ihm mitgibt, und das Checkout, von dem er startet, ist Teil dieses Kontexts. Der AI Agents Pocket Guide behandelt die Muster rund um Delegation, Isolation und die Uebergabe von Arbeit zwischen Agents. Er ist eines von acht Kurzbuchern der Reihe Pocket Guides for Developers, die Agents, RAG, Prompts, Observability, Events, Datenbanken und Systemdesign abdeckt. Wer mehrere Agents auf einem Repository betreibt, kann Hermes IDE kostenlos ausprobieren; der Code liegt auf GitHub.
Automatisch übersetzt. Das Original auf Englisch ist unten aufklappbar.
Original (Englisch) anzeigen
You wrote refund() an hour ago. It's committed on feature/refund. You hand it to a subagent: "add tests for refund() in src/orders.js." The subagent comes back and tells you there is no refund() in that file.
It isn't wrong. In the checkout it was given, the function doesn't exist.
Claude Code lets a custom subagent run in its own git worktree with one frontmatter line, isolation: worktree. The subagent docs say that worktree is "branched by default from your default branch rather than the parent session's HEAD." The worktree docs are more precise: the default base is the repository's default branch on the remote, usually origin/main. Your feature branch isn't in it. Neither are commits on your local main that you haven't pushed.
The fix is one setting. Checking that you need it takes a few git commands. I haven't run this walkthrough myself: it's built from the current Claude Code and git docs, so if a step behaves differently on your version, the worktree docs are the source of truth.
You need a repo with an origin remote. That part matters. When no remote is configured, or origin/HEAD isn't cached and can't be fetched, Claude Code falls back to your local HEAD. A throwaway repo with no remote won't reproduce the problem.
Take a small Node project ( "type": "module" in package.json ) whose main is pushed. Cut a branch and add a function:
// 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 " }; } Enter fullscreen mode Exit fullscreen mode git switch -c feature/refund git add src/orders.js git commit -m "Add refund() for paid orders" Enter fullscreen mode Exit fullscreen mode Commit before you delegate. A new git worktree is checked out from a commit, so edits you haven't committed stay in your checkout whatever the base setting is.
While you're here, add.claude/worktrees/ to.gitignore. That's where Claude Code creates worktrees, and you don't want them showing up as untracked files in your main checkout.
Project subagents live in.claude/agents/. Save this as.claude/agents/test-writer.md:
--- 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. Enter fullscreen mode Exit fullscreen mode name and description are the two required fields. isolation: worktree is the line that matters here. Spell it exactly: the frontmatter reference says Claude Code ignores a field it doesn't recognize without reporting an error, so a typo gives you a subagent that quietly edits your main checkout.
Claude Code picks up edits to.claude/agents/ within seconds, except the first agent file in a new agents directory: restart Claude Code once to load it.
Start Claude Code on feature/refund and call the subagent by name so Claude doesn't pick a different one. You can type @agent-<name> by hand:
@agent-test-writer add tests for refund() in src/orders.js Enter fullscreen mode Exit fullscreen mode The prompt above asks the subagent to print its own git log first. If its top commit is your pushed main tip and not "Add refund() for paid orders", you've reproduced it.
The first run changes nothing, so it leaves no worktree behind, and the subagent's printed git log is the only record of where it started. Git tells you whether that record fits. The default base is origin/HEAD, so check whether your feature commit is in it:
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 $? Enter fullscreen mode Exit fullscreen mode The second command names the branch a default worktree starts from, usually origin/main. Per the git-merge-base manual, --is-ancestor exits with status 0 if the first commit is an ancestor of the second, and 1 if it isn't. A 1 here means your feature tip isn't in the branch the subagent started from.
Compare hashes too. Run git log --oneline -1 origin/HEAD and put it next to the top line of the subagent's own git log. They should match.
One more detail: when the repository hasn't been fetched in the last 24 hours, Claude Code fetches the default branch before creating the worktree, capped at five seconds, and uses the cached ref if that fetch fails. So the base can be newer than the origin/main you last pulled.
You can't set it to a branch name. For a specific existing branch, create the worktree with git yourself.
Put it in.claude/settings.local.json to try it for yourself, or in the committed.claude/settings.json if your team wants every worktree to start from the current work:
{ "worktree": { "baseRef": "head" } } Enter fullscreen mode Exit fullscreen mode This setting covers every worktree Claude Code creates, so claude --worktree sessions branch from HEAD too. That's the trade-off. "fresh" is the better default for unrelated tasks that should start clean. "head" is for extending work that hasn't merged yet.
Start a new Claude Code session on feature/refund and send the same @agent-test-writer line. This time the subagent should find refund(), write tests and commit them on its own branch.
Subagent worktrees follow two rules. A subagent that finishes without changes has its worktree removed right away. One with changes stays on disk; a periodic sweep tied to your cleanupPeriodDays setting removes it later, but skips any worktree that still holds changed or untracked files or unpushed commits.
So if the first run stopped without touching a file, as the prompt told it to, nothing is left behind, and git worktree list shows only your main checkout. If the second run committed tests, its worktree is still there. Find it:
git worktree list Enter fullscreen mode Exit fullscreen mode Look for the row under.claude/worktrees/. The name in brackets at the end is the subagent's branch. Its naming scheme isn't documented, so read it from this output rather than guessing:
AGENT_BRANCH = <branch from git worktree list> git merge-base --is-ancestor feature/refund " $AGENT_BRANCH " echo $? git log --oneline feature/refund.. " $AGENT_BRANCH " Enter fullscreen mode Exit fullscreen mode A 0 means your feature commit is in the subagent's branch. The log with two dots lists only the commits the subagent added on top of it.
Merge from your main checkout, still on feature/refund:
git merge --ff-only " $AGENT_BRANCH " git worktree remove.claude/worktrees/<name> git branch -d " $AGENT_BRANCH " Enter fullscreen mode Exit fullscreen mode --ff-only works when feature/refund hasn't moved since the subagent started. If you committed in the meantime, use a plain git merge. Remove the worktree before deleting the branch, because git won't delete a branch that's checked out in a worktree.
If git worktree remove refuses because the worktree is locked, check who holds the lock. Claude Code holds a git worktree lock while the agent runs and releases it when the agent finishes, and the sweep also releases a lock left by a session whose process exited. If one is still in place, run git worktree unlock.claude/worktrees/<name> first. Don't reach for --force unless you've checked there's nothing in that folder you want.
I build Hermes IDE, so weigh this section with that in mind. Hermes works at the task level rather than the subagent level: ⌘N (Ctrl+Shift+N on Windows and Linux) starts each task on its own hermes/<name> branch in its own worktree, with the task as the agent's first prompt. When the work is done, the Land action commits, opens a pull request or merges locally into the branch the task started from, and it can be undone.
The ⌘N New task sheet in Hermes 2.3.4: the task typed, chips for Claude Code, the orders-api project, a new hermes/ worktree, Accept edits, model and effort, and the "Hermes will run" preview of the claude command.
The two layers stack. If Claude Code runs inside a Hermes task and spawns your test-writer subagent, the same worktree.baseRef rule applies. The worktree docs say that inside a worktree, "head" resolves to that worktree's HEAD, not the main checkout's. With "head" set, the subagent branches from the hermes/<name> task branch. Any of three files works: your user-level ~/.claude/settings.json, a.claude/settings.json committed on the branch the task started from, or the main checkout's.claude/settings.local.json, which the settings docs say Claude Code reads even from inside a worktree on macOS and Linux. With the default, the subagent branches from the remote's default branch, same as before.
The Review Desk's Worktrees tab lists the task worktrees Hermes made, with branch, age and disk size, which helps when you're deciding what to merge and what to throw away.
The Review Desk's Worktrees tab: one Hermes worktree each for orders-api, web-app and orders-types under ~/code, with each worktree's hermes/ branch, task, age and disk size, and the free disk space.
Hermes is free, source-available under BSL 1.1, and runs on macOS, Windows and Linux. It isn't affiliated with Anthropic, OpenAI, Nous Research or any agent vendor. Download Hermes if you want to try the task-level version.
A subagent is only as useful as the context you hand it, and the checkout it starts from is part of that context. The AI Agents Pocket Guide covers the patterns around delegation, isolation and handing work between agents. It's one of 8 short books in the Pocket Guides for Developers series, covering agents, RAG, prompts, observability, events, databases and system design. If you run several agents on one repo, Hermes IDE is free to try, and the code is on GitHub.