Don't let Windows kill your vibe coding flow.
Every Claude Code plugin assumes you're on macOS or Linux.
On Windows, your sessions start with a wall of red hook errors.
win-hooks fixes that. Automatically. Every session.
You install a shiny new Claude Code plugin, start a session, and:
SessionStart hook error: /bin/bash: command not found
PreToolUse hook error: scripts/check.sh: No such file or directory
PostToolUse hook error: semgrep: command not found
Every. Single. Plugin. Written on a Mac, tested on Linux, shipped with .sh scripts Windows has never heard of.
Install win-hooks once. Forget about it forever.
claude plugin marketplace add LilMGenius/win-hooks
claude plugin install win-hooksNext session, win-hooks silently patches every broken plugin before you even notice. No config, no flags, no manual fixing.
Every time Claude Code starts, win-hooks runs a pipeline:
scan plugins → patch hooks.json → normalize settings.json → verify & auto-repair
- Scans
~/.claude/plugins/installed_plugins.jsonfor all installed plugins - Detects
.shscripts, missing binaries, and Unix-only commands - Creates a polyglot
.cmdentry point and extensionless bash wrappers - Patches each plugin's
hooks.json(originals backed up as.bak) - Normalizes
settings.jsonhook commands —C:\...backslash paths → forward slashes, and barenode/python/python3/npx/npm→ quoted absolute paths - Verifies & auto-repairs — strips BOM, normalizes CRLF, validates JSON, and repairs broken, missing, or recursive wrappers
- Skips anything already compatible — safe to run a thousand times
It all runs silently; you only hear from win-hooks when something needs your attention.
The happy path is silent, so win-hooks logs a one-line heartbeat to ~/.claude/win-hooks/last-run.log each session (disk only, never in your conversation, rotated to the last 50 lines):
tail -n 5 ~/.claude/win-hooks/last-run.logphase=done→ it healed this session.- lone
phase=start→ cut off mid-run (usually a timeout; self-corrects next session). - no file → it hasn't dispatched yet.
/win-hooks:status surfaces this for you. The SessionStart timeout auto-sizes to your plugin count (a round 1–10 min) so large installs never get killed mid-run; the new size applies next session (or after /reload-plugins).
| Command | Description |
|---|---|
/win-hooks:fix |
Manually trigger the patcher (auto-runs at session start) |
/win-hooks:status |
Show compatibility status of all installed plugins |
When a plugin updates, its install path changes and patches are lost. This is by design. Run /reload-plugins (or restart Claude Code) → win-hooks re-detects and re-patches automatically. Zero maintenance.
- Windows 10/11 with Git for Windows
- Claude Code CLI (includes Node.js, used for JSON validation)
Bonus: win-hooks keeps
python3hooks working too — even when Windows only has the Microsoft Store "Python was not found" stub — by routing them through a real interpreter it finds at patch time.
The core trick is a .cmd file that is simultaneously valid batch and valid bash:
: << 'CMDBLOCK'
@echo off
REM Windows cmd.exe runs this part → finds Git Bash → delegates
"C:\Program Files\Git\bin\bash.exe" "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
exit /b %ERRORLEVEL%
CMDBLOCK
# bash runs this part → executes directly
exec bash "${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"- Windows:
cmd.exeignores the heredoc, runs the batch portion, finds Git Bash, delegates. - macOS/Linux: bash treats
:as a no-op, skips to the shell portion, runs natively.
plugin/
├── hooks/
│ ├── hooks.json ← patched to point to _hooks/
│ └── hooks.json.bak ← original backup
├── _hooks/ ← win-hooks creates this
│ ├── run-hook.cmd ← polyglot entry point
│ └── <wrapper> ← extensionless bash wrapper
└── scripts/
└── setup.sh ← original (untouched)
Wrappers live in a dedicated _hooks/ directory — original plugin files are never modified.
Contributors: see
CLAUDE.mdfor the internal pipeline (scanner → patcher → verifier) and per-issue case notes.
Built for the Windows developers who refuse to switch to Mac just to vibe code.
MIT — Use it, fork it, vibe with it.