diagnose
git clone https://github.com/LilMGenius/win-hooks
T=$(mktemp -d) && git clone --depth=1 https://github.com/LilMGenius/win-hooks "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/diagnose" ~/.claude/skills/lilmgenius-win-hooks-diagnose && rm -rf "$T"
skills/diagnose/SKILL.mdWin-Hooks Diagnostics
Diagnose and fix Claude Code plugin hook compatibility issues on Windows.
Common Error Patterns
"JSON Parse error: Unrecognized token ''" / ":: command not found" / "#!/bin/bash: No such file or directory" / "<<(을)를 지정된 경로를 찾지 못했습니다"
Root cause: UTF-8 BOM (EF BB BF) in any hook file. In hooks.json it causes JSON parse errors; in
run-hook.cmd it breaks bash's : builtin AND it pushes the leading : off line-start so cmd.exe stops recognizing it as a label and instead parses the polyglot's << heredoc opener as redirection (mojibake: <<��(��) ������� �ʾҽ��ϴ�); in wrapper scripts it breaks shebang parsing. Typically caused by Windows editors or PowerShell Out-File.
Fix: Run /win-hooks:fix — verify --fix strips BOM from every file in hooks/, _hooks/, and any file referenced from hooks.json (e.g., scripts/run-hook.cmd shipped by ralph-loop).
"Hook load failed: JSON Parse error"
Root causes (check in order):
- UTF-8 BOM in hooks.json
- CRLF line endings causing parser issues
- Corrupted hooks.json from interrupted patching
- Invalid JSON syntax from bad text replacement
Fix: Run
/win-hooks:fix which runs the full pipeline including verify --fix.
"SyntaxError" from python3/node on a .py/.js hook file
Root cause: Plugin ships bash wrapper scripts with
.py/.js extension that call the interpreter on themselves (e.g., pretooluse.py is #!/bin/bash but contains python3 pretooluse.py). Python/Node can't parse bash syntax.
Fix: Run /win-hooks:fix — verify --fix disables recursive wrappers with exit 0.
"No such file or directory" for hook command
Root cause: Hook references a
.sh script or bare command that doesn't exist on Windows.
Fix: Run /win-hooks:fix to create polyglot wrappers.
"MODULE_NOT_FOUND" in Node.js hooks
Root cause: Windows backslash paths in
settings.json hook commands get mangled during execution — backslashes are interpreted as escape characters, producing paths like Userssmsme.configaincreport-usage.js.
Fix: Run /win-hooks:fix which converts C:\... to C:/... in settings.json hooks via fix-backslash-paths.
"'node' is not recognized as an internal or external command" / "'node'은(는) 내부 또는 외부 명령... 아닙니다" on Stop/SessionStart hooks
Root cause:
settings.json hook command starts with a bare interpreter (node, python, python3, npx, npm) that's on Git Bash's PATH but not resolvable by cmd.exe at hook launch. Error text may appear CP949-garbled (e.g. 'node'��(��) ���� �Ǵ� �ܺ� ����...). Note: the similar-looking <<(을)를 지정된 경로를 찾지 못했습니다 (mojibake <<��(��) ������� �ʾҽ��ϴ�) is a different error — that one is BOM-corrupted polyglot wrapper (see the BOM section above).
Fix: Run /win-hooks:fix — fix-bare-commands rewrites the command to a quoted absolute path like "C:/Program Files/nodejs/node.exe" <script>.
Why Hooks Break on Windows
Most Claude Code plugins are developed on Unix. Their hooks use:
scripts called directly (cmd.exe cannot execute these).sh- Bare Unix commands not in Windows PATH (e.g.,
,semgrep
)shellcheck
path with${CLAUDE_PLUGIN_ROOT}
extension (triggers Claude Code's auto-detection).sh- Unix-specific shell syntax (
, pipes, etc.)$(...)
Diagnosis Procedure
Step 1: Identify Platform
Check that platform is
win32. If not, this skill does not apply.
Step 2: Find win-hooks install path
sed '1s/^\xEF\xBB\xBF//' ~/.claude/plugins/installed_plugins.json | awk ' /win-hooks/ { found=1 } found && /"installPath"/ { sub(/.*"installPath"[[:space:]]*:[[:space:]]*"/, "") sub(/".*/, "") print exit } ' | sed 's/[\\][\\]*/\//g'
Save the output path as PLUGIN_ROOT.
Step 3: Run health check
bash "<PLUGIN_ROOT>/scripts/verify"
This detects:
| Issue Type | Meaning |
|---|---|
| bom | UTF-8 BOM in any hook file (hooks/, _hooks/, or any file referenced from hooks.json) |
| json_invalid | hooks.json is not valid JSON |
| json_crlf | CRLF line endings in hooks.json |
| wrapper_missing | Patched hook references nonexistent wrapper script |
| cmd_missing | _hooks/run-hook.cmd is missing |
| recursive_wrapper | Bash wrapper (.py/.js) calls python3/node on itself |
| backslash_path | settings.json hook command has Windows backslash paths |
| bare_command | settings.json hook command uses bare interpreter not resolvable by cmd.exe |
Step 4: Run incompatibility scanner
bash "<PLUGIN_ROOT>/scripts/find-incompatible"
Step 5: Report Findings
Present a table:
| Plugin | Issue | Detail | Status | |--------|-------|--------|--------| | name | type | info | OK/FIX |
Fix Procedure
Automatic (recommended)
bash "<PLUGIN_ROOT>/hooks/patch-all"
This runs the full pipeline:
→ detects incompatible hooksfind-incompatible
→ creates wrappers, patches hooks.json (sanitizes BOM/CRLF, validates JSON)apply-patches
→ auto-repairs any remaining encoding issuesverify --fix
Manual repair for specific files
For BOM/CRLF issues only:
bash "<PLUGIN_ROOT>/scripts/verify" --fix
For restoring a broken hooks.json from backup:
cp <plugin>/hooks/hooks.json.bak <plugin>/hooks/hooks.json
Then re-run patch-all.
Hook Event Types
Any of these can have incompatible commands:
| Category | Events |
|---|---|
| Session | SessionStart, SessionEnd, InstructionsLoaded |
| User Input | UserPromptSubmit |
| Tools | PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest |
| Agents | SubagentStart, SubagentStop, Stop, TeammateIdle, TaskCompleted |
| Context | PreCompact, PostCompact, ConfigChange |
| Integration | Notification, Elicitation, ElicitationResult |
| Worktree | WorktreeCreate, WorktreeRemove |
Automatic Prevention
The win-hooks plugin runs its patcher at every SessionStart. If you install or update a plugin, simply restart Claude Code - the patcher will detect and fix new incompatibilities automatically.
Rollback
# Restore a plugin's original hooks.json cp <plugin>/hooks/hooks.json.bak <plugin>/hooks/hooks.json
Troubleshooting
Hook still errors after patching:
- Check if Git Bash is installed at
C:\Program Files\Git\bin\bash.exe - Verify the wrapper script has correct content:
cat <plugin>/_hooks/<wrapper-name> - Run with debug:
to see hook execution detailsclaude --debug hooks
python3 not found (other plugins):
- win-hooks automatically copies
→python.exe
ifpython3.exe
is missingpython3 - If Python is not installed at all, plugins that require Python will still fail
Plugin update overwrites fix:
- This is expected. Restart Claude Code and win-hooks will re-patch automatically.