Bug Description
On Windows, user-defined command hooks (SessionStart, PreToolUse, PostToolUse, etc.) stop firing under certain conditions. In our case, hooks worked with an npm-installed Claude Code, stopped working when a native installer binary (~/.local/bin/claude.exe) was also present and took PATH precedence, and resumed working after removing the native binary.
We have not yet confirmed whether the native installer alone (without npm coexistence) has the same issue. The root cause may be a conflict between the two installation methods rather than a defect in either one.
Environment
- OS: Windows 11 Enterprise 10.0.26100
- Claude Code version: 2.1.41 (both binaries)
- npm path:
AppData\Roaming\npm\claude.cmd
- Native installer path:
~\.local\bin\claude.exe
Steps to Reproduce
-
Install Claude Code via npm: npm install -g @anthropic-ai/claude-code
-
Also have the native installer binary present at ~\.local\bin\claude.exe
-
Configure user-defined hooks in .claude/hooks.json (e.g., SessionStart hooks that write to an audit log)
-
Start a session — ~\.local\bin\claude.exe takes PATH precedence over npm
-
Observe that no user-defined hooks fire (verified by checking audit log)
-
Remove or rename ~\.local\bin\claude.exe so npm's claude.cmd resolves instead
-
Start a new session
-
Observe that all user-defined hooks fire correctly
Evidence
Tested across 7 sessions. Hook firing correlated with which binary was resolved via PATH:
| Session |
Binary |
Version |
Hooks? |
| 1-2 |
npm (claude.cmd) |
2.1.39 |
YES |
| 3 |
native (claude.exe) |
2.1.41 |
NO |
| 4 |
native (claude.exe) |
2.1.41 |
YES (intermittent) |
| 5-6 |
native (claude.exe, shadowing npm) |
2.1.41 |
NO |
| 7 |
npm (claude.cmd) after removing native |
2.1.41 |
YES |
Internal Claude Code callbacks (e.g., PostToolUse:Read callback) appear in session JSONL even when user-defined hooks don't fire — only user-defined command hooks are affected.
What We Don't Know
- Whether the native installer alone (npm uninstalled) fires hooks correctly
- Whether the coexistence of both installation methods is the root cause
- Whether this is Windows-specific
Additional Context
hooks.json is valid JSON with correct script paths
- All hook scripts execute correctly when run manually (
echo {} | python script.py)
- No
disableAllHooks setting configured
- This is a blocker for projects that depend heavily on hooks (e.g., framework enforcement, TDD compliance, session bootstrapping)
Current Workaround
Remove the native installer binary and use the npm-installed version:
ren %USERPROFILE%\.local\bin\claude.exe claude.exe.bak
Bug Description
On Windows, user-defined
commandhooks (SessionStart, PreToolUse, PostToolUse, etc.) stop firing under certain conditions. In our case, hooks worked with an npm-installed Claude Code, stopped working when a native installer binary (~/.local/bin/claude.exe) was also present and took PATH precedence, and resumed working after removing the native binary.We have not yet confirmed whether the native installer alone (without npm coexistence) has the same issue. The root cause may be a conflict between the two installation methods rather than a defect in either one.
Environment
AppData\Roaming\npm\claude.cmd~\.local\bin\claude.exeSteps to Reproduce
Install Claude Code via npm:
npm install -g @anthropic-ai/claude-codeAlso have the native installer binary present at
~\.local\bin\claude.exeConfigure user-defined hooks in
.claude/hooks.json(e.g., SessionStart hooks that write to an audit log)Start a session —
~\.local\bin\claude.exetakes PATH precedence over npmObserve that no user-defined hooks fire (verified by checking audit log)
Remove or rename
~\.local\bin\claude.exeso npm'sclaude.cmdresolves insteadStart a new session
Observe that all user-defined hooks fire correctly
Evidence
Tested across 7 sessions. Hook firing correlated with which binary was resolved via PATH:
claude.cmd)claude.exe)claude.exe)claude.exe, shadowing npm)claude.cmd) after removing nativeInternal Claude Code callbacks (e.g.,
PostToolUse:Read callback) appear in session JSONL even when user-defined hooks don't fire — only user-definedcommandhooks are affected.What We Don't Know
Additional Context
hooks.jsonis valid JSON with correct script pathsecho {} | python script.py)disableAllHookssetting configuredCurrent Workaround
Remove the native installer binary and use the npm-installed version: