EnterWorktree (name mode) writes core.hooksPath into the shared repo config; ExitWorktree doesn't restore it

Open 💬 0 comments Opened Jun 10, 2026 by MisterTuur

Environment

Claude Code desktop app on macOS 26.5.1 (CLI claude --version: 2.1.97). Multi-session use on the same repos via EnterWorktree/ExitWorktree, worktree.baseRef: "fresh".

Observed behavior (proven by controlled experiment)

Starting from core.hooksPath unset in a repo:

| Action | core.hooksPath afterwards |
|---|---|
| git worktree add (manual) | unset (clean) |
| EnterWorktree with path: (enter existing worktree) | unset (clean) |
| EnterWorktree with name: (create worktree) | <abs>/.git/hooks — written to the SHARED repo config |
| ExitWorktree action=remove afterwards | still <abs>/.git/hooks — not restored |

Because this lands in the shared .git/config, it outlives the worktree and applies to the main checkout and all other worktrees. Any repo that wires its versioned hooks via core.hooksPath (e.g. npm preparegit config core.hooksPath .githooks) has them silently disabled for every checkout the moment any session creates a name-mode worktree — and re-disabled after every repair, since every new name-mode worktree rewrites it. We chased this as a mystery config-mutator across four repos before isolating it; combined with stale hook copies it produced an afternoon of blocked pushes across parallel sessions.

Related doc-vs-behavior gap

ExitWorktree action=remove documents "deletes the worktree directory and its branch", but after a mid-session git branch -m worktree-<name> task/<name> rename it (a) refuses removal counting already-pushed commits as discardable, and (b) after discard_changes: true removes the directory but leaves the renamed local branch behind.

Suggestions

  • Use extensions.worktreeConfig + per-worktree config.worktree for the hooksPath override instead of mutating shared state; or restore the prior value on exit.
  • Track the worktree by path rather than original branch name so a renamed branch is still recognized as the worktree's own.

Happy to provide the experiment transcript.

View original on GitHub ↗