Claude Code feature request: skip paranoid auto-spawn when cwd is already inside a worktree
Filed by: end-user (Matthew Davis) via CO-PARANOID-MODE-OVER-SPAWN-001 (2026-05-06)
Claude Code version: 2.1.121 (npm-installed)
Platform: Windows 11
Severity: workflow friction (RECURRING-4 over 7 days; ~10–15 min recovery tax per recurrence)
Summary
When CLAUDE_AUTO_WORKTREE_ALWAYS=1 is set in ~/.claude/settings.json:env and the user opens Claude inside a pre-existing worktree (e.g., <repo>/.claude/worktrees/<semantic-name>/), the harness still spawns a fresh <repo>/.claude/worktrees/claude/<adjective-noun-hex>/ worktree and lands the session there — discarding the user's intended substrate.
The expected behavior: paranoid mode skips auto-spawn when cwd is already inside an isolated worktree. The current behavior: paranoid mode is unconditional, races the user's prepared isolation.
RECURRING-4 evidence
| Date | Session scope | Expected cwd | Spawn-injected cwd | Recovery |
|---|---|---|---|---|
| 2026-04-30 AM | Tier 1 Stream A | parent checkout | parent checkout (paranoid did NOT fire here — sibling CO-WORKTREE-AUTO-SPAWN-DIAG-001 inverse failure) | n/a |
| 2026-04-30 PM | Stream B Component B | parent checkout | parent checkout (sibling failure) | manual git worktree add post-discovery |
| 2026-05-06 (1st) | SPEC-GGS-001-BUILD-PHASE-2 S3 build | reflexstack-phase-2 worktree | claude/<random> worktree | inline cd-soft-move + --self-declare ISOLATED-VIA-OPTOUT |
| 2026-05-06 (2nd) | SPEC-GGS-001-BUILD-PHASE-2 S4 post-clearance | ggs-001-build-phase-2-s4-cont worktree | charming-payne-a9f477 worktree | same recipe |
| 2026-05-06 (3rd, this CO's fix-session) | CO-PARANOID-MODE-OVER-SPAWN-001 diagnostic | parent checkout (per launch prompt §1) | blissful-dewdney-a55644 worktree | same recipe |
Each recurrence costs ~10–15 min recovery tax (rename branch off harness-random claude/<adj-noun-hex> to a semantic name, self-declare in the registry, re-orient toolchain to operate from the spawn-injected path).
Why opt-out doesn't help
CLAUDE_NO_AUTO_WORKTREE=1 exists but is overridden by paranoid mode per the user-side spec SPEC-SESSION-ISOLATION-001 v1.0.1 §5 Axis 3 matrix:
Setting both at the same time → paranoid mode wins (safer)
That precedence is correct for the unprepared-cwd case (race-surface elimination). It is incorrect for the prepared-worktree case (race surface is already nil; paranoid spawn imposes cost without benefit).
Proposed behavior
Pre-spawn check at session-launch:
- If cwd path contains
.claude/worktrees/(or, equivalently,git rev-parse --git-common-dirreturns a path that differs fromgit rev-parse --git-dirindicating we're in a worktree, not the main checkout), THEN skip auto-spawn regardless ofCLAUDE_AUTO_WORKTREE_ALWAYSvalue.
- Optionally: also surface a new env var
CLAUDE_NO_AUTO_WORKTREE_FORCE=1for an absolute opt-out — overrides paranoid in all cases. (Useful for power users who never want auto-spawn on any cwd.)
The skip should be additive: paranoid continues to fire correctly when cwd is the parent checkout, ~, or any non-worktree path. The F3-S-07 LIVE RACE precedent that justifies paranoid mode (a parallel session swapping .git/HEAD mid-session on a shared checkout) is preserved for unprepared sessions.
Workaround currently used (R-B)
Pre-launch shell wrapper at ~/.claude/scripts/launch-claude-cwd-aware.{ps1|sh} introspects cwd before invoking claude:
# launch-claude-cwd-aware.ps1
$cwd = (Get-Location).Path
if ($cwd -replace '\\', '/' -match '/\.claude/worktrees/') {
$env:CLAUDE_AUTO_WORKTREE_ALWAYS = "0"
$env:CLAUDE_NO_AUTO_WORKTREE = "1"
}
& claude @args
Effective if shell-set process env overrides ~/.claude/settings.json:env — empirically open. If settings.json wins, the wrapper is a no-op and inline recovery (rename + self-declare) remains the workaround.
Inline recovery recipe (currently working, ~10–15 min)
# 1. Detect: branch matches claude/<adjective-noun-hex>
git branch --show-current
# 2. Rename branch to semantic
git branch -m claude/<random> <co-or-spec-derived-name>
# 3. Self-declare in session registry
node ~/.claude/scripts/discover-sessions.cjs --self-declare \
--repo "<repo-path>" \
--decision ISOLATED-VIA-OPTOUT \
--branch "<semantic-branch>" \
--pid <session-pid>
# 4. Continue work in the spawn-injected worktree (or cd-soft-move to prepared worktree)
This works but is brittle: relies on operator discipline; pays the tax every session-open.
Specs / context
- SPEC-SESSION-ISOLATION-001 v1.0.1 §5 Axis 3 (paranoid-vs-opt-out matrix) — current "paranoid wins" precedence
- F3-S-07 LIVE RACE precedent — empirical justification for paranoid mode (recoverable race; recovery is manual)
- CO-PARANOID-MODE-OVER-SPAWN-001 — full RECURRING-4 evidence + R-A/R-B/R-C path analysis
- CO-WORKTREE-AUTO-SPAWN-DIAG-001 — sibling CO documenting the inverse failure (paranoid NOT firing when it should)
What this issue does NOT request
- Changes to
CLAUDE_AUTO_WORKTREE_ALWAYSsemantics on parent-checkout cwd. Paranoid should still fire there. The fix is narrow: skip when cwd is already a worktree. - Removal of paranoid mode globally. The mode is load-bearing; the F3-S-07 race risk is real.
- Changes to
~/.claude/scripts/spawn-worktree.cjs(a user-side primitive that does NOT consumeCLAUDE_AUTO_WORKTREE_ALWAYS; orthogonal to the auto-spawn behavior).
---
Authored 2026-05-06 by the CO-PARANOID-MODE-OVER-SPAWN-001 fix session as part of resolution path R-C (escalation in parallel with R-B wrapper). Inline-recovery and R-B wrapper continue to work as user-side mitigations until a harness-side fix lands.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗