Hooks fail in git worktrees: $CLAUDE_PROJECT_DIR resolves to worktree, missing .claude/helpers/
Description
When Claude Code spawns an agent in a git worktree (via isolation: "worktree" or EnterWorktree), hooks configured in .claude/settings.json that reference $CLAUDE_PROJECT_DIR/.claude/helpers/ fail because $CLAUDE_PROJECT_DIR resolves to the worktree path, not the original repository root.
The .claude/ directory (including helpers/, settings.json, etc.) is not part of the git repository — it lives only in the main repo's working directory. Git worktrees do not copy or symlink non-tracked directories, so the helpers are missing in the worktree.
Reproduction
- Have a project with hooks configured in
.claude/settings.jsonthat reference helper scripts:
``json``
{
"hooks": {
"Stop": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/helpers/auto-memory-hook.mjs\" sync"
}]
}]
}
}
- Run Claude Code in a git worktree (either via
isolation: "worktree"agent spawning, orEnterWorktree)
- Observe hook failure:
```
Stop hook error: Failed with non-blocking status code: node:internal/modules/cjs/loader:1386
throw err;
^
Error: Cannot find module '/Users/user/project/.claude/worktrees/worktree-name/.claude/helpers/auto-memory-hook.mjs'
at Function._resolveFilename (node:internal/modules/cjs/loader:1383:15)
...
```
Expected Behavior
Hooks should resolve $CLAUDE_PROJECT_DIR to the original repository root (where .claude/ actually exists), not the worktree path. Alternatively, Claude Code could:
- Symlink
.claude/into the worktree on creation - Provide a separate env var like
$CLAUDE_ORIGINAL_PROJECT_DIRthat always points to the main repo - Fall back to the main repo's
.claude/when the worktree doesn't have one
Environment
- Claude Code version: latest (Claude Opus 4.6)
- Node.js: v22.22.0
- OS: macOS (Darwin 23.5.0)
- Git worktrees created under:
<repo>/.claude/worktrees/
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗