claude-code - 💡(How to fix) Fix Background sessions block `Edit`/`Write` outside a worktree with no opt-out — gate is unconditional once `CLAUDE_JOB_DIR` is set

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…

When a Claude Code session is launched as a background job (i.e. with CLAUDE_JOB_DIR set in the environment), the Edit and Write tools refuse to operate on any path inside the current checkout unless the session is currently inside .claude/worktrees/.... The refusal message is:

"This background session hasn't isolated its changes yet. Call EnterWorktree first so edits land in a worktree instead of the shared checkout, then retry this edit using the worktree path."

There is no documented or undocumented env var / settings.json key that disables this gate. This is a problem for non-code repos where worktrees are actively harmful — notably Obsidian vaults, where another process (Obsidian.app or Obsidian Git) owns the working copy and would not see edits made on a sibling worktree branch.

Error Message

  1. The tool returns the error above. Tool output is rejected at the harness/preflight layer; the user-supplied file content never lands.

Root Cause

Non-code repos are a real use case for Claude Code. The Obsidian-vault pattern (Markdown notes managed by a separate desktop app that holds the canonical state) is the obvious one, but the same applies to any repo where another process — a deployment pipeline, a sync daemon, a doc generator — owns the working copy and worktree branches are friction rather than safety. For these, the background-session bg-worktree gate is pure cost: it adds a merge step, hides changes from the owning app, and is bypassable from Bash anyway.

A clean opt-out would let users keep the default-safe behavior in code repos while disabling it where it isn't wanted.

Code Example

// pseudocode
     if (currentWorktreeSession) return targetInOriginalCwd && !targetInWorktreePath
       ? "This session is now isolated in <wt>. Edit the worktree copy of this file instead of the shared-checkout path."
       : null;
     const cwd = getOriginalCwd();
     if (cwd.includes("/.claude/worktrees/")) return null;   // already in a wt — fine
     if (!target.startsWith(cwd + sep)) return null;          // outside repo — fine
     if (!isBgSessionRequiringIsolation(cwd)) return null;    // bg-session predicate
     return "This background session hasn't isolated its changes yet. Call EnterWorktree first…";

---

// ~/.claude/settings.json
{
  "worktree": {
    "requireForBackgroundSessions": false
  }
}
RAW_BUFFERClick to expand / collapse

Summary

When a Claude Code session is launched as a background job (i.e. with CLAUDE_JOB_DIR set in the environment), the Edit and Write tools refuse to operate on any path inside the current checkout unless the session is currently inside .claude/worktrees/.... The refusal message is:

"This background session hasn't isolated its changes yet. Call EnterWorktree first so edits land in a worktree instead of the shared checkout, then retry this edit using the worktree path."

There is no documented or undocumented env var / settings.json key that disables this gate. This is a problem for non-code repos where worktrees are actively harmful — notably Obsidian vaults, where another process (Obsidian.app or Obsidian Git) owns the working copy and would not see edits made on a sibling worktree branch.

Repro (verified on 2.1.139)

  1. In a git repo, launch a background Claude Code session (anything that sets CLAUDE_JOB_DIR in the agent's env).
  2. From that session, call the Edit tool on any tracked file at the repo root — do not call EnterWorktree first.
  3. The tool returns the error above. Tool output is rejected at the harness/preflight layer; the user-supplied file content never lands.

The same session can:

  • Read any file (no gate)
  • Run arbitrary Bash against the same paths, including in-place rewrites via python3 / sed -i '' (no gate)
  • Run external CLIs that mutate the same files (e.g. obsidian append file=... content=...) (no gate)

So the gate is specific to the Edit/Write tool path, and trivially circumventable from Bash, which makes its protective value low while the friction is high.

What I tried

  1. Set CLAUDE_NO_AUTO_WORKTREE=1 in ~/.claude/settings.json under env. No effect on this gate. Verified the var is in the daemon's env (env | grep CLAUDE_NO_AUTO_WORKTREE returns =1) but the gate still fires.

  2. Inspected the shipped binary (~/.local/share/claude/versions/2.1.139):

    • strings <binary> | grep CLAUDE_NO_AUTO_WORKTREE returns 0 matches. The env var name doesn't appear anywhere in the binary, so it's a complete no-op. (This deserves either implementation or documentation as not-a-thing — multiple Claude sessions appear to suggest it as a fix.)
    • The gate string is reachable. Surrounding logic (decompiled from raw bytes):
      // pseudocode
      if (currentWorktreeSession) return targetInOriginalCwd && !targetInWorktreePath
        ? "This session is now isolated in <wt>. Edit the worktree copy of this file instead of the shared-checkout path."
        : null;
      const cwd = getOriginalCwd();
      if (cwd.includes("/.claude/worktrees/")) return null;   // already in a wt — fine
      if (!target.startsWith(cwd + sep)) return null;          // outside repo — fine
      if (!isBgSessionRequiringIsolation(cwd)) return null;    // bg-session predicate
      return "This background session hasn't isolated its changes yet. Call EnterWorktree first…";
    • isBgSessionRequiringIsolation(cwd) is the only configurable hook in the chain, and there's no string in the binary that suggests it reads any env var or settings key — it's effectively process.env.CLAUDE_JOB_DIR != null.
  3. CLAUDE_BG_ISOLATION exists in the binary but is set by Agent({ isolation: "worktree" }) per spawn and controls a different preflight message ("Call EnterWorktree as your first action — before reading files or running commands"). It is not a global on/off and setting it to "" from outside has no effect on the gate above.

Proposed fix

Add an opt-out — either a settings key or an env var — that makes isBgSessionRequiringIsolation return false. E.g.:

// ~/.claude/settings.json
{
  "worktree": {
    "requireForBackgroundSessions": false
  }
}

Or equivalently CLAUDE_BG_REQUIRE_WORKTREE=0. Either name is fine — the important thing is that there be one.

Documenting CLAUDE_NO_AUTO_WORKTREE as either implemented-and-doing-X or not-a-real-flag would also help; right now it appears in conversations and settings.json as a remedy but does nothing.

Why this matters

Non-code repos are a real use case for Claude Code. The Obsidian-vault pattern (Markdown notes managed by a separate desktop app that holds the canonical state) is the obvious one, but the same applies to any repo where another process — a deployment pipeline, a sync daemon, a doc generator — owns the working copy and worktree branches are friction rather than safety. For these, the background-session bg-worktree gate is pure cost: it adds a merge step, hides changes from the owning app, and is bypassable from Bash anyway.

A clean opt-out would let users keep the default-safe behavior in code repos while disabling it where it isn't wanted.

Environment

  • Claude Code 2.1.139 (binary path: ~/.local/share/claude/versions/2.1.139)
  • macOS 25.5.0, arm64
  • Session type: background job (CLAUDE_JOB_DIR set)
  • Repo: Obsidian vault (Markdown only, no build step), main owned by Obsidian Git

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING