Skip to content

Comments

fix(hooks): add .cmd wrapper for Windows compatibility (#491)#496

Closed
dotuananh0712 wants to merge 2 commits intoobra:mainfrom
dotuananh0712:fix/windows-hooks-cmd-491
Closed

fix(hooks): add .cmd wrapper for Windows compatibility (#491)#496
dotuananh0712 wants to merge 2 commits intoobra:mainfrom
dotuananh0712:fix/windows-hooks-cmd-491

Conversation

@dotuananh0712
Copy link

@dotuananh0712 dotuananh0712 commented Feb 17, 2026

Summary

  • Creates session-start.cmd polyglot wrapper that works on both Windows (CMD.exe) and Unix (bash)
  • Updates hooks.json to reference the .cmd file instead of .sh

Fixes #491

SessionStart hook fails on Windows because hooks.json points to .sh file which CMD.exe cannot execute.

Changes

  1. New file: hooks/session-start.cmd - polyglot wrapper
  2. Modified: hooks/hooks.json - changed command path from .sh to .cmd

Verification

  • Verified: session-start.cmd runs correctly on Unix (outputs valid JSON)
  • Verified: hooks.json is valid JSON
  • On Windows: Claude Code runs hooks through CMD.exe, which will now execute the .cmd wrapper that invokes bash to run the original .sh script

Summary by CodeRabbit

  • New Features

    • Added Windows compatibility for plugin session initialization scripts through cross-platform wrapper support.
  • Documentation

    • Enhanced code reviewer documentation with clearer git command execution guidance to improve workflow clarity.

Adds guidance to run git diff commands separately instead of
chaining with && to avoid consent prompts.

Fixes obra#476
Creates session-start.cmd polyglot wrapper that works on both
Windows (CMD.exe) and Unix (bash). Updates hooks.json to reference
the .cmd file instead of .sh.

Fixes obra#491: SessionStart hook fails on Windows because hooks.json
points to .sh file which CMD.exe cannot execute.
@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

Changes introduce a Windows-compatible wrapper script (session-start.cmd) that invokes Git Bash to execute the Unix shell script, with the hook configuration updated to reference this wrapper instead of the .sh file directly. Documentation is enhanced to clarify git diff command execution patterns.

Changes

Cohort / File(s) Summary
Hook Configuration Update
hooks/hooks.json
Changed SessionStart hook command path from session-start.sh to session-start.cmd to enable Windows compatibility.
Cross-Platform Wrapper Script
hooks/session-start.cmd
New polyglot wrapper script supporting both Windows (CMD.exe via Git Bash) and Unix platforms; handles path normalization and delegates execution to session-start.sh.
Documentation Enhancement
skills/requesting-code-review/code-reviewer.md
Added explicit guidance to execute git diff commands separately without chaining, preventing consent prompt interruptions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 A CMD wrapper hops to the rescue,
When Windows said "I don't know what to do!"
Bash takes the stage with a polyglot dance,
Unix and CMD now share a romance. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes an unrelated commit adding guidance to skills/requesting-code-review/code-reviewer.md about avoiding && with git diff commands, which addresses issue #476 and is outside the scope of the Windows hooks fix. Remove or separate the code-reviewer.md changes (issue #476) into a distinct PR to keep this PR focused solely on the Windows hooks compatibility fix (issue #491).
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding a .cmd wrapper for Windows compatibility in the hooks module, which directly addresses issue #491.
Linked Issues check ✅ Passed The PR implements all core requirements from #491: adds a polyglot session-start.cmd wrapper, updates hooks.json to reference the .cmd file instead of .sh, and enables Windows compatibility for the SessionStart hook.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
hooks/hooks.json (1)

9-9: Change looks correct — consider adding single quotes for paths with spaces.

The .sh.cmd rename aligns with the new polyglot wrapper. One minor concern: if CLAUDE_PLUGIN_ROOT expands to a path containing spaces (e.g., C:\Users\Name With Spaces\…), the unquoted variable may break. Single-quoting the expansion protects against word splitting.

-            "command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.cmd",
+            "command": "'${CLAUDE_PLUGIN_ROOT}/hooks/session-start.cmd'",

This is a pre-existing concern (the old .sh path had the same issue), so it can be addressed separately. Based on learnings: "single quotes around the variable are necessary because Claude Code expands variables before passing the command to the shell."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/hooks.json` at line 9, Update the "command" value for the session-start
hook to quote the CLAUDE_PLUGIN_ROOT expansion so paths with spaces are
preserved: change the unquoted "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.cmd"
in the "command" field to use single quotes around the expansion (i.e., quote
the whole path string) to prevent word-splitting when CLAUDE_PLUGIN_ROOT
contains spaces.
hooks/session-start.cmd (1)

21-21: Drop the -l (login shell) flag — it's unnecessary and may cause side effects.

The -l flag makes bash run as a login shell, sourcing ~/.bash_profile and similar. This adds startup overhead and may pull in user-specific environment changes that interfere with the hook script. A plain bash invocation is sufficient here.

-"C:\Program Files\Git\bin\bash.exe" -l "%SCRIPT_DIR%/session-start.sh"
+"C:\Program Files\Git\bin\bash.exe" "%SCRIPT_DIR%/session-start.sh"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/session-start.cmd` at line 21, Change the Bash invocation that
currently uses the login-shell flag by removing "-l" from the command that runs
session-start.sh; i.e., update the invocation of "C:\Program
Files\Git\bin\bash.exe" -l "%SCRIPT_DIR%/session-start.sh" so it calls bash
without "-l" (leave the path to session-start.sh as-is) to avoid login-shell
side effects and extra startup overhead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@hooks/session-start.cmd`:
- Line 21: The hardcoded Git Bash path in session-start.cmd ("C:\Program
Files\Git\bin\bash.exe") can fail for portable, 32-bit, or custom
installs—update the script to first try resolving bash from PATH (e.g., using
where/which) and, if not found, fall back to checking common locations like
%ProgramFiles%\Git\bin\bash.exe and %ProgramFiles(x86)%\Git\bin\bash.exe before
erroring; modify the call site in session-start.cmd that invokes bash so it uses
the discovered executable or a clear error message if none found.
- Around line 1-27: The hooks/session-start.cmd file must use CRLF line endings
for Windows CMD; update the repository metadata and the file: add a
.gitattributes entry (e.g., "*.cmd text eol=crlf" or "hooks/session-start.cmd
text eol=crlf") to enforce CRLF for .cmd files, then convert
hooks/session-start.cmd to CRLF line endings (ensure the initial CMDBLOCK batch
section and the rest of the file are saved with CRLF) and commit both the
.gitattributes change and the normalized file so CMD.exe will parse the batch
labels and commands correctly.

---

Nitpick comments:
In `@hooks/hooks.json`:
- Line 9: Update the "command" value for the session-start hook to quote the
CLAUDE_PLUGIN_ROOT expansion so paths with spaces are preserved: change the
unquoted "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.cmd" in the "command" field
to use single quotes around the expansion (i.e., quote the whole path string) to
prevent word-splitting when CLAUDE_PLUGIN_ROOT contains spaces.

In `@hooks/session-start.cmd`:
- Line 21: Change the Bash invocation that currently uses the login-shell flag
by removing "-l" from the command that runs session-start.sh; i.e., update the
invocation of "C:\Program Files\Git\bin\bash.exe" -l
"%SCRIPT_DIR%/session-start.sh" so it calls bash without "-l" (leave the path to
session-start.sh as-is) to avoid login-shell side effects and extra startup
overhead.

@obra obra added bug Something isn't working windows hooks Hook system (SessionStart, Stop, etc.) labels Feb 21, 2026
@obra
Copy link
Owner

obra commented Feb 21, 2026

Closing — this is superseded by v4.3.1 (PR #523), which takes a similar approach: restoring the polyglot run-hook.cmd wrapper, renaming session-start.sh to an extensionless session-start, and using POSIX-safe path resolution.

Thank you for the contribution and for helping diagnose these Windows issues!

@obra obra closed this Feb 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working hooks Hook system (SessionStart, Stop, etc.) windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SessionStart hook fails on Windows — hooks.json points to .sh file which CMD.exe cannot execute

2 participants