Worktree creation rewrites shared core.hooksPath, silently disabling repo-managed git hooks for the whole clone
Environment
- Claude Code version: v2.1.170
- Platform: Linux
- Verified: 2026-06-10
Description
When Claude Code creates a session worktree (the desktop "worktree" checkbox, --worktree, or isolation: "worktree" for agents), it checks for <mainRepo>/.husky and then <mainRepo>/.git/hooks, and if the repo's core.hooksPath differs from that path it runs:
git config core.hooksPath <absolute path to mainRepo/.git/hooks>
with the cwd set to the new worktree, logging "Configured worktree to use hooks from main repository".
The problem: linked worktrees share the clone's config file, so this git config write lands in the SHARED .git/config. That silently disables any repo-managed custom hooks directory (for example the common committed-hooks pattern core.hooksPath=hooks) for the main checkout AND every other worktree, not just the session worktree.
Two factors make this worse:
.git/hooksalways exists (git populates it with sample files), so the "does hooksPath differ from .git/hooks" comparison fires for essentially every repo that uses a custom hooksPath.- The rewrite is re-asserted on every new worktree creation, so even if the user notices and restores their
core.hooksPath, the next Claude Code worktree session clobbers it again. There is no way to durably keep the setting.
Steps to reproduce
- Create a repo with a committed hooks directory:
````
git init demo && cd demo
mkdir hooks
printf '#!/bin/sh\necho "pre-push gate ran"\nexit 1\n' > hooks/pre-push
chmod +x hooks/pre-push
git config core.hooksPath hooks
git add . && git commit -m "init"
- Start a Claude Code session with worktree isolation (desktop worktree checkbox,
claude --worktree, or an agent withisolation: "worktree"). - From the MAIN checkout, run
git config core.hooksPath.
Expected: still hooks.
Actual: it now points at <repo>/.git/hooks (absolute path), and the committed pre-push hook no longer runs anywhere in the clone.
Real-world impact
In a work repo using committed hooks via core.hooksPath=hooks, all pre-push quality gates were silently disabled for the entire clone for several days before anyone noticed. The repo ultimately had to ship forwarding shim scripts inside .git/hooks (each shim exec-ing the corresponding committed hook) just to coexist with the rewrite.
Suggested fixes
Any of these would resolve it, listed in order of preference:
- Respect an existing
core.hooksPaththat already resolves to a repo-managed directory. Only rewrite whencore.hooksPathis unset, or when.huskyactually exists (the husky case appears to be what this logic was built for). - If hooks must be redirected for the session worktree, scope the write to that worktree only: enable
extensions.worktreeConfigand usegit config --worktree core.hooksPath ...so the shared.git/configis never touched. - At minimum, surface the config change to the user instead of applying it silently. A one-line notice that "core.hooksPath was changed from X to Y in the shared repo config" would have saved days of silently-skipped pre-push gates.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗