Skip to content

Worktrees outside .claude/worktrees/ cost one approval prompt per switch #94265

Description

@nborracha

Worktrees outside .claude/worktrees/ cost one approval prompt per switch

Summary

Two behaviours compound into an approval prompt on every worktree switch, for repos that keep
their worktrees somewhere other than .claude/worktrees/:

  1. Worktree→worktree switching is rejected unless the target is under .claude/worktrees/, so
    moving between trees requires ExitWorktree back to the launch directory and re-entering.
  2. An approved path is not remembered. Re-entering a path already approved in the same session
    prompts again.

Either alone is liveable. Together they mean an agent alternating between two tickets pays an
approval on every hop, forever.

I understand the first-entry prompt is deliberate, and that neither an EnterWorktree permission
rule nor "don't ask again" suppresses it. This report is about the repeat.

Version

  • Claude Code 2.1.251
  • macOS 15.6 (Apple silicon)
  • Worktrees at <repo>/.worktrees/<ticket-id>, created by a repo-owned wrapper around
    git worktree add (not claude --worktree), and registered in git worktree list.

Repro 1 — direct switching is rejected outside .claude/worktrees/

With the session already inside <repo>/.worktrees/A, calling
EnterWorktree path=<repo>/.worktrees/B fails:

Cannot enter worktree: <repo>/.claude/worktrees does not exist,
so <repo>/.worktrees/B …

Both A and B are registered worktrees of the current repository and appear in git worktree list.
Entering either one from the launch directory works. Only the worktree→worktree switch is
refused, which is what forces the exit-and-re-enter cycle that triggers Repro 2.

Observed sequence from one real session:

07:44:09  -> .worktrees/TICKET-A   ok
08:01:16  -> .worktrees/TICKET-B   ERROR (.claude/worktrees does not exist)
08:10:51  -> .worktrees/TICKET-B   ok      (after exiting to the launch directory)
08:22:53  -> .worktrees/TICKET-A   ok      (re-entry of 07:44's path)

Repro 2 — an approved path is not remembered (confirmed first-hand)

git worktree add .worktrees/REPRO -b repro-branch

From the repo root, in one session:

  1. EnterWorktree path=<repo>/.worktrees/REPRO → prompts. Approve.
  2. ExitWorktree action=keep → back in the repo root.
  3. EnterWorktree path=<repo>/.worktrees/REPRO — the identical path — → prompts again.

Expected: step 3 does not prompt. Same session, same path, approved one step earlier, nothing
about it changed.

Actual: two prompts for two entries of the same path. Confirmed by the user watching the
session; the tool returned success both times.

Workarounds tested, none effective

Attempt Result
permissions.allow: ["EnterWorktree"] No effect — documented as not suppressing this prompt
permissions.defaultMode: "bypassPermissions" in project settings Silently ignored; session starts in Manual mode
additionalDirectories No effect (also reported in #23109)
PermissionRequest hook returning allow Does not apply — workspace-trust surface, not a tool-permission prompt

That leaves --dangerously-skip-permissions, which also removes confirmation for credential reads,
writes outside the working directory, force pushes and arbitrary network access. Giving all of that
up to avoid one prompt per worktree switch is not a trade a team should have to make.

Relationship to existing issues

Neither covers re-entry of an already-approved path, or the switching restriction that makes
re-entry the only way to move between trees.

Suggested resolutions

1. Allow worktree→worktree switching for any worktree registered to the current repository, not
only those under .claude/worktrees/. git worktree list already establishes ownership — the same
check that governs entry from the launch directory — so the restriction looks incidental rather
than a security boundary. This is the part that reads as an outright bug: a legitimate operation on
a legitimate worktree of the current repo is refused, and the suggested remedy in the error text
(create .claude/worktrees/) asks the repo to adopt a tool-specific layout it may share with other
tooling.

Worth being precise about what this alone fixes: it removes the error and the exit-and-re-enter
detour, but not the prompt count. A → B → A still prompts three times while an approved path is
not remembered. It is the smaller, better-bounded change, and it stops a valid call from failing.

2. Remember an approved worktree path for the session. This is what actually reduces prompts:
A → B → A becomes two, because returning to A is a decision already made. The first entry into each
tree still prompts, so the checkpoint keeps its security value — what goes away is re-litigating an
approval the user gave minutes earlier.

3. Failing both, a scoped opt-in (trustedWorkspacePatterns per #23109, or honouring
additionalDirectories here) so the choice is not "prompt every switch" or "disable everything".

Fixing 1 and 2 together is what makes parallel worktree work ergonomic; either alone is a partial
improvement.

Context

A monorepo running several agent sessions in parallel, one git worktree per ticket, at
<repo>/.worktrees/<ticket-id>. That location predates Claude Code's own worktree support and is
shared by non-Claude tooling, so moving to .claude/worktrees/ would couple the repo layout to one
vendor. Switching between tickets mid-session is the normal workflow, not an edge case.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:permissionsbugSomething isn't workinghas reproHas detailed reproduction stepsplatform:macosIssue specifically occurs on macOS

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions