[BUG] 2.1.211 "always allow rules save at repository root" breaks unattended runs in a linked git worktree under a worktree-scoped filesystem sandbox
Version
- Claude Code 2.1.211 (regressed here; worked in prior versions)
- Platform: Linux
What changed
The 2.1.211 changelog includes:
Changed "always allow" permission rules to save at the repository root, so approvals granted in a git worktree persist across sessions and worktrees
For a linked git worktree, "repository root" resolves via the shared
git-common-dir to the main checkout, not the worktree:
cwd / git toplevel : ~/worktrees/myproject/feature-x ← the linked worktree
git common dir : ~/repos/myproject/.git ← the MAIN checkout
So Claude Code now reads/writes permission rules at~/repos/myproject/.claude/settings.local.json — a path outside the
worktree.
Observed behavior
I run Claude Code inside a filesystem sandbox that only grants access to the
active worktree (for example, the nono sandbox, but this applies to any
sandbox scoped to the worktree). Since 2.1.211:
- Claude Code accesses
<main-checkout>/.claude/settings.local.json. - The sandbox denies it (
Permission denied/EACCES) — the file is
world-readable at the OS level; the denial is the sandbox's filesystem policy,
because the main checkout is not in the sandbox's allowed set.
- On startup this now surfaces a prompt that must be signed off manually.
Net effect: Claude Code can no longer start working unattended from a
worktree under a worktree-scoped sandbox. It blocks waiting for a human. This
worked fine before 2.1.211, when permission rules were read from the worktree's
own .claude/settings.local.json (which the sandbox does expose).
Why it breaks (suspected cause)
The new repo-root resolution assumes the repository root is always accessible.
In a linked worktree the resolved root (main checkout) can be:
- outside a filesystem sandbox that intentionally exposes only the worktree, or
- otherwise unreadable/unwritable.
When that path can't be read, the current behavior blocks/prompts instead of
degrading gracefully — which defeats unattended/headless operation.
(Mechanism above is inferred from the changelog + the observed denied path
matching the resolved repo root exactly. I can attach an strace of a startup
showing the openat(...settings.local.json) → EACCES on request.)
Impact
- Breaks unattended / headless / CI-style runs launched from a linked worktree
inside a sandbox that scopes filesystem access to the worktree.
- No documented opt-out: settings, env-vars, CLI flags, and the worktrees docs
provide no way to disable repo-root storage, choose an alternative location,
or treat the worktree as the root.
Expected behavior / requests
Any one of these would resolve it:
- An opt-out — a settings key or env var to store/read "always allow"
permission rules per-worktree (the pre-2.1.211 behavior), instead of at
the resolved repository root.
- Graceful degradation — when the resolved repository root is unreadable
(sandbox denial / EACCES), fall back to the worktree's own
.claude/settings.local.json and do not block or prompt in a
non-interactive context, rather than stalling unattended startup.
- Configurable root — honor a configured project root (or
additionalDirectories) when resolving where permission rules live in a
worktree.
Reproduction
- Create a linked git worktree of a repo:
git worktree add ~/worktrees/myproject/feature-x
- Confirm the split roots:
git -C ~/worktrees/myproject/feature-x rev-parse --show-toplevel →
the worktree; --git-common-dir → the main checkout's .git.
- Launch Claude Code from the worktree inside a filesystem sandbox that grants
access to the worktree but not the main checkout.
- Observe Claude Code attempt to read
<main-checkout>/.claude/settings.local.json, get denied, and block on a
prompt — preventing unattended startup.
Downgrading below 2.1.211 (or exposing the main checkout to the sandbox) avoids
it, but neither is an acceptable workaround for a worktree-scoped sandbox.
---
*Investigated, drafted, and filed by Claude — Anthropic's Claude Code CLI,
model claude-opus-4-8 (Opus 4.8) — on behalf of the repository user who hit
this regression.*
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗