claude-code - 💡(How to fix) Fix [BUG] `claude --worktree <name>` bases on origin/<default> not parent HEAD + prepends `worktree-` to branch name — breaks multi-session identifier-verbatim convention

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

Because the parent shell can't always rely on the harness defaults, our SESSION_RESUME/README.md § "When a new chat session starts" now has a sub-section "Harness-defaults reconciliation (known operator step)" that documents the 2-step verify-and-reconcile (git reset --hard origin/<intended-base> + git branch -m worktree-<name> <name>) plus the recommended alternative: don't use claude --worktree at all for sessions opened off a non-default integration branch; run git worktree add .claude/worktrees/<name> -b <name> origin/<intended-base> manually and start Claude inside it. That manual path is what this very session (b669-upstream-report) used to file this issue.

Fix Action

Fix / Workaround

In-repo mitigation we shipped

The mitigation closes the gap operationally but the harness defaults still surprise everyone the first time, and every multi-session cohort pays a per-session reconciliation tax.

RAW_BUFFERClick to expand / collapse

Describe the bug

claude --worktree <chat-name> has two silent defaults that together break a multi-session coordination convention many users rely on — every team I've talked to that runs N parallel sessions for a single repo treats the worktree dir / branch name / per-session pointer file / cross-session log session field as a single shared identifier per session. The harness defaults silently rewrite both the base and the branch name, so the identifier the user typed at claude --worktree is no longer byte-identical with the worktree dir or the branch:

  1. Wrong base — the worktree is created on origin/<github-default-branch> (typically main or master) instead of the parent shell's current HEAD branch. For repos where the GitHub default branch is far behind the active integration branch (long-lived feature lines, release cuts, post-merge tracking branches), the worktree is born missing recent commits — including, in our empirical case, the very plan doc the session was asked to execute. See related #45316 for the wrong-base symptom in isolation.
  2. worktree- branch-name prefix — the harness names the branch worktree-<chat-name> instead of clean <chat-name>. This means git worktree list and git branch --show-current return a different string than the worktree directory name, breaking any multi-session reconciliation that keys on a single identifier (e.g. cross-referencing git worktree list against per-session pointer files or a coordination log). Related #54653 / #31969 touch branch naming from different angles.

Steps to reproduce

  1. Have a repo where the parent shell's current HEAD is not the GitHub default branch (e.g. on a long-lived integration branch round-6-post-merge-tracking while default is master).
  2. Run claude --worktree my-session-name.
  3. Observe:
    • git rev-parse HEAD in the new worktree points at origin/master (or wherever the GitHub default is), not at the parent shell's HEAD.
    • git branch --show-current returns worktree-my-session-name, not my-session-name.

Expected behavior

  • claude --worktree <name> bases the worktree on the parent shell's current HEAD by default (the working set the user just came from is the most likely intended base).
  • An explicit --worktree-base <ref> flag for when the default isn't right.
  • The branch name is exactly <name> (no worktree- prefix). The convention should be: the string the user typed is the string everywhere — worktree dir, branch, anything else.

Actual behavior

  • Worktree based on origin/<github-default-branch> regardless of parent shell HEAD.
  • Branch named worktree-<name>, so the worktree dir is <name> but the branch is worktree-<name> — they no longer match.

Empirical anchor (2-event, ~24h apart, same repo)

  1. 2026-05-23 worktree-review-archive session-start — parent shell on round-6-post-merge-tracking (~140 commits ahead of origin/master); claude --worktree worktree-review-archive produced a worktree on origin/master with branch worktree-worktree-review-archive. The plan doc the session was asked to execute didn't exist on the harness-chosen base. Reconciled manually via git reset --hard origin/round-6-post-merge-tracking + git branch -m worktree-worktree-review-archive worktree-review-archive.
  2. 2026-05-24 track-and-address session-start — deliberately avoided claude --worktree and used git worktree add .claude/worktrees/track-and-address -b track-and-address origin/round-6-post-merge-tracking manually exactly to dodge the same defaults a second time. This session (the one filing this issue, b669-upstream-report) did the same.

In-repo mitigation we shipped

Because the parent shell can't always rely on the harness defaults, our SESSION_RESUME/README.md § "When a new chat session starts" now has a sub-section "Harness-defaults reconciliation (known operator step)" that documents the 2-step verify-and-reconcile (git reset --hard origin/<intended-base> + git branch -m worktree-<name> <name>) plus the recommended alternative: don't use claude --worktree at all for sessions opened off a non-default integration branch; run git worktree add .claude/worktrees/<name> -b <name> origin/<intended-base> manually and start Claude inside it. That manual path is what this very session (b669-upstream-report) used to file this issue.

The mitigation closes the gap operationally but the harness defaults still surprise everyone the first time, and every multi-session cohort pays a per-session reconciliation tax.

Proposed fix

  1. Base — default to the parent shell's HEAD (via git rev-parse HEAD in the cwd at invocation time). Accept an explicit --worktree-base <ref> flag for override.
  2. Branch name — use <name> verbatim. Drop the worktree- prefix from the auto-generated branch name. If a <name> branch already exists, fail loudly rather than silently mangling.

Together, these would let claude --worktree <name> honor the "the string you typed is the string everywhere" convention, eliminating per-session reconciliation friction for multi-session coordination workflows.

Related

  • #45316 — wrong-base symptom in isolation
  • #31969 / #54653 / #61419 / #60588 — adjacent worktree branch-naming / base-selection concerns

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

  • claude --worktree <name> bases the worktree on the parent shell's current HEAD by default (the working set the user just came from is the most likely intended base).
  • An explicit --worktree-base <ref> flag for when the default isn't right.
  • The branch name is exactly <name> (no worktree- prefix). The convention should be: the string the user typed is the string everywhere — worktree dir, branch, anything else.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING