[bug] [area:agents] [platform:macos] Agent(isolation: "worktree") post-creation setup silently rewrites...
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Environment
- Platform: macOS Darwin 25.6.0 (Apple Silicon)
- Claude Code CLI:
2.1.173 (Claude Code)(confirmed byclaude --version) - Transport: CLI / local subprocess
- Repository type: Private repository with
core.hooksPath = .githooksconfigured (custom hook directory for pre-commit/pre-push security controls)
Summary
When the Claude Code Agent tool is invoked with isolation: "worktree", its post-creation setup step writes .git/config in the shared (parent) repository, overwriting core.hooksPath from the operator-configured value (.githooks) to the default (.git/hooks). This silently disables any custom git hook security controls in the shared repo. All subsequent commits and pushes from the shared repo run with dead hooks and no observable indication of failure — the hooks appear to pass (default .git/hooks stubs exit 0).
Reproduction Steps
- Configure a git repository with a custom
core.hooksPath:
````
git config core.hooksPath .githooks
- Place security-control scripts in
.githooks/pre-commitand.githooks/pre-push(executable). - Verify hooks fire correctly: make a commit, confirm hook output appears.
- Dispatch an
Agenttool call withisolation: "worktree"from within a Claude Code session rooted at this repository. - After the agent completes and its worktree is removed, inspect the shared repo's
.git/config:
````
git config core.hooksPath
- Make a new commit and observe that no hook output appears.
Expected Behavior
The Agent tool's worktree isolation post-creation setup should not modify the shared repository's existing core.hooksPath. At minimum, if the worktree setup must configure core.hooksPath for its own purposes, it should restore the pre-existing value in the shared repo config when the worktree is torn down.
Actual Behavior
After the first Agent(isolation: "worktree") dispatch, core.hooksPath in the shared repository's .git/config is overwritten from .githooks to .git/hooks. The change is silent — no warning or log message indicates it occurred. The sample hook stubs at .git/hooks/ exit 0 unconditionally, so all subsequent commits and pushes appear to succeed normally with no hook feedback at all.
Impact
Security-control class. This affects repositories where git hooks enforce access controls (secret scanning, sensitive-path blocking, credential leak prevention). When core.hooksPath is silently rewritten:
- All pre-commit and pre-push security controls stop firing with no observable indication
- The operator cannot distinguish a passing hook from a dead one (silent exit-0 behavior is identical to a live clean pass)
- An arbitrary number of commits and pushes may bypass security controls before the rewrite is detected by an out-of-band check
In our case, the hooks guard against accidental commits of sensitive paths (memory files, credential files, portfolio data, Plaid API tokens). The hooks were active for approximately two weeks before this incident; the rewrite was not detected until the following session when a manual git config core.hooksPath check was part of a session-open checklist. All pushes between the rewrite event and detection ran unguarded.
Timeline Evidence
The config write was pinned to the exact dispatch timestamp by Time Machine snapshot bisection: two consecutive hourly snapshots (18:14 and 20:15 local EDT) showed the config at the prior .githooks value in the earlier snapshot and at .git/hooks at timestamp 2026-06-09 18:38:43 in the later. This was the first Agent(isolation: "worktree") dispatch since the hook installation, and the config-write timestamp matches the dispatch timestamp to the second. No other process was identified that could have written .git/config in that window.
Manual git worktree add was separately verified to NOT touch the shared repo's core.hooksPath. The behavior is specific to the Agent tool's isolation: "worktree" post-creation setup path.
Workarounds We Use
- Standing prohibition on
isolation: "worktree"in this repository. Agents needing an isolated tree use manualgit worktree addinstead (verified not to touchcore.hooksPath).
- Clobber-resilience symlink shim:
.git/hooks/pre-commitand.git/hooks/pre-pushare symlinks pointing into.githooks/. If anything rewritescore.hooksPathback to.git/hooks, the hooks still resolve to the live control scripts. Requires re-creating the symlinks post-clone.
- Observable-pass output: Every clean hook run prints a versioned confirmation line (e.g.,
pre-commit guard v2: N paths scanned, 0 blocks). A silent exit-0 is treated as a dead hook, not a clean pass.
- Session-open canary: A 3-test suite (
test_hooks_canary.py) verifiescore.hooksPathvalue,GUARD_VERSIONconstant, and executable bit on every session open. Any regression is caught at the next session start.
Suggested Fix
The worktree post-creation setup should not modify the shared repository's existing core.hooksPath. Options:
- Preferred: Don't write
core.hooksPathto the shared repo config at all — the worktree has its own.git/(or.gitfile) and can configure itself in isolation. - Acceptable: If the shared repo config must be touched, snapshot the prior
core.hooksPathvalue before writing and restore it on worktree removal. - Minimum: Document the behavior explicitly in the
Agenttool reference so operators knowisolation: "worktree"modifies the parent repo's git config.
What Should Happen?
The Agent tool's worktree isolation post-creation setup should not modify the shared repository's existing core.hooksPath. At minimum, if the worktree setup must configure core.hooksPath for its own purposes, it should restore the pre-existing value in the shared repo config when the worktree is torn down.
Error Messages/Logs
Steps to Reproduce
- Configure a git repository with a custom
core.hooksPath:
````
git config core.hooksPath .githooks
- Place security-control scripts in
.githooks/pre-commitand.githooks/pre-push(executable). - Verify hooks fire correctly: make a commit, confirm hook output appears.
- Dispatch an
Agenttool call withisolation: "worktree"from within a Claude Code session rooted at this repository. - After the agent completes and its worktree is removed, inspect the shared repo's
.git/config:
````
git config core.hooksPath
- Make a new commit and observe that no hook output appears.
Claude Model
Not sure / Multiple models
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.173 (Claude Code) (confirmed by claude --version)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗