chore: claude Notification Hook이 Windows 환경에서도 동작하도록#655
Conversation
Walkthrough이 변경사항은 시스템 알림 메커니즘을 Python 기반으로 통합하고 교차 플랫폼 지원을 추가합니다. Windows용 PowerShell 스크립트와 macOS를 포함한 다중 플랫폼 Python 래퍼를 새로 도입하고, 설정 파일에서 기존 명령어를 이 새로운 Python 스크립트로 대체하며 오류 발생 시 폴백 메커니즘을 제공합니다. 세부 변경사항
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @.claude/settings.json:
- Line 12: Update the two hook command strings in .claude/settings.json to
remove Unix-only shell syntax and explicitly invoke PowerShell on Windows:
replace the Notification hook command that references notify.py and the
PostToolUse hook command that references post-edit-check.py so they no longer
use "2>/dev/null" or "||"; instead call PowerShell to run the corresponding .ps1
scripts (use the existing .claude/hooks/notify.ps1 or a post-edit-check
PowerShell script if present) and fall back to the Python script when PowerShell
is not available, ensuring the JSON "command" values for those hooks (the
Notification and PostToolUse entries) are cross-platform and Windows-compatible.
🧹 Nitpick comments (2)
.claude/hooks/notify.ps1 (1)
1-9: 전반적으로 깔끔한 Windows 알림 스크립트입니다 👍다만, 스크립트가 중간에 중단되거나 예외가 발생할 경우
$n.Dispose()가 호출되지 않아 시스템 트레이에 아이콘이 남을 수 있습니다.try/finally블록으로 감싸면 더 안전합니다.🛡️ try/finally로 안전하게 정리하는 제안
Add-Type -AssemblyName System.Windows.Forms $n = New-Object System.Windows.Forms.NotifyIcon -$n.Icon = [System.Drawing.SystemIcons]::Information -$n.Visible = $true -$n.BalloonTipTitle = "Claude Code" -$n.BalloonTipText = "Awaiting your input" -$n.ShowBalloonTip(5000) -Start-Sleep -Milliseconds 5100 -$n.Dispose() +try { + $n.Icon = [System.Drawing.SystemIcons]::Information + $n.Visible = $true + $n.BalloonTipTitle = "Claude Code" + $n.BalloonTipText = "Awaiting your input" + $n.ShowBalloonTip(5000) + Start-Sleep -Milliseconds 5100 +} finally { + $n.Dispose() +}.claude/hooks/notify.py (1)
9-19: Linux 환경에 대한 지원이 빠져 있습니다.
- macOS (Darwin):
osascript로 알림 — ✅- Windows: PowerShell 스크립트 위임 — ✅
- Linux: 지원 없음 — ❓
Linux 사용자가 이 설정을 사용할 경우 아무런 알림도 받지 못하고 조용히 넘어갑니다.
notify-send등을 활용하는 Linux 분기를 추가하거나, 최소한 지원하지 않는 플랫폼에 대해 안내 메시지를 출력하면 좋겠습니다.💡 Linux 지원 및 미지원 플랫폼 안내 추가 제안
elif system == "Windows": ps1_path = os.path.join(script_dir, "notify.ps1") subprocess.run([ "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", ps1_path ]) +elif system == "Linux": + subprocess.run([ + "notify-send", "Claude Code", "Awaiting your input" + ]) +else: + print(f"Unsupported platform for notifications: {system}")
| { | ||
| "type": "command", | ||
| "command": "osascript -e 'display notification \"Awaiting your input\" with title \"Claude Code\"'" | ||
| "command": "python3 .claude/hooks/notify.py 2>/dev/null || python .claude/hooks/notify.py" |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Claude Code Cursor IDE hook execution Windows shell compatibility
💡 Result:
On Windows, Claude Code hooks execute exactly the command string you configure (they’re “user-defined shell commands”). The official hooks guide even provides Windows examples that explicitly invoke powershell.exe -Command ..., which is the most reliable pattern on Windows shells. (docs.claude.com)
Why .sh hooks often fail in Cursor/Windows
If your hook is configured like this:
{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh" }…Claude Code may open the .sh file in VS Code/Cursor instead of executing it on Windows (a reported Windows bug/behavior). (github.com)
Practical Windows-compatible fixes
- Call PowerShell directly (recommended for native Windows):
{ "type": "command", "command": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"C:\\path\\to\\hook.ps1\"" }(Or inline -Command "..." as shown in the docs.) (docs.claude.com)
- If you want to keep
.sh, invoke Bash explicitly (Git Bash or WSL), don’t execute the.shpath bare:
- Claude Code on native Windows commonly relies on Git for Windows’
bash.exe, and you may need to set:CLAUDE_CODE_GIT_BASH_PATH="C:\Program Files\Git\bin\bash.exe"(docs.claude.com)
- Then configure the hook like (example):
{
"type": "command",
"command": "\"C:\\Program Files\\Git\\bin\\bash.exe\" -lc \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh\""
}Cursor IDE note
If something works in standalone CMD/PowerShell but not in Cursor’s integrated terminal, it’s often because the integrated terminal doesn’t inherit the same environment (so variables like CLAUDE_CODE_GIT_BASH_PATH may not be visible there). (reddit.com)
Citations:
- 1: https://docs.claude.com/en/docs/claude-code/hooks-guide
- 2: [BUG] Hook .sh scripts open in VSCode instead of executing on Windows Terminal/PowerShell anthropics/claude-code#9758
- 3: https://docs.claude.com/en/docs/claude-code/hooks-guide
- 4: https://docs.claude.com/en/docs/claude-code/getting-started?utm_source=openai
- 5: https://www.reddit.com/r/ClaudeCode/comments/1pe1oji/troubles_to_use_it_on_cursor/?utm_source=openai
🌐 Web query:
Cursor IDE .claude/hooks configuration Windows cmd.exe PowerShell
💡 Result:
Where to configure hooks (Cursor / Claude Code)
Claude Code hooks are read from these JSON files (user- or project-scoped): ~/.claude/settings.json, .claude/settings.json, or .claude/settings.local.json. (docs.anthropic.com)
They run shell commands, receiving event context as JSON on stdin. (docs.anthropic.com)
After editing hooks, Claude Code takes a startup snapshot; changes typically require review via the /hooks menu to apply. (docs.anthropic.com)
On Windows, ~ maps to your home directory (typically C:\Users\<you>), so user settings are usually:
C:\Users\<you>\.claude\settings.json
PowerShell hook (recommended on Windows)
1) Put a script somewhere, e.g.
- Project:
<repo>\.claude\hooks\my-hook.ps1
Example my-hook.ps1 (reads stdin JSON):
# .claude/hooks/my-hook.ps1
$inputJson = [Console]::In.ReadToEnd() | ConvertFrom-Json
# Example: log tool + command
$tool = $inputJson.tool_name
$cmd = $inputJson.tool_input.command
"[$(Get-Date -Format o)] $tool :: $cmd" | Out-File -Append -FilePath "$env:CLAUDE_PROJECT_DIR\.claude\hook.log" -Encoding utf8
exit 02) Reference it from .claude/settings.json
Use $CLAUDE_PROJECT_DIR so it works regardless of current working directory. (docs.anthropic.com)
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"\\\"$CLAUDE_PROJECT_DIR\\\"\\.claude\\hooks\\my-hook.ps1\""
}
]
}
]
}
}(That quoting pattern is important if your project path contains spaces, per the docs’ guidance to quote $CLAUDE_PROJECT_DIR.) (docs.anthropic.com)
cmd.exe hook (if you really want cmd)
You can call cmd.exe /d /s /c ..., but handling stdin JSON in pure batch is awkward, so the common pattern is: cmd.exe → call powershell.exe anyway.
Example:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "cmd.exe /d /s /c \"powershell.exe -NoProfile -ExecutionPolicy Bypass -File \\\"%CLAUDE_PROJECT_DIR%\\.claude\\hooks\\my-hook.ps1\\\"\""
}
]
}
]
}
}If you tell me which hook event you’re targeting (PreToolUse, PostToolUse, PermissionRequest, etc.) and what you want to do (block commands, log, run formatters/tests), I can provide a ready-to-paste config + script for that specific case.
Citations:
- 1: https://docs.anthropic.com/en/docs/claude-code/hooks
- 2: https://docs.anthropic.com/en/docs/claude-code/hooks
- 3: https://docs.anthropic.com/en/docs/claude-code/hooks
- 4: https://docs.anthropic.com/en/docs/claude-code/hooks
- 5: https://docs.anthropic.com/en/docs/claude-code/hooks
🏁 Script executed:
# Check if this is a Cursor/Claude Code project and look for any shell configuration
find . -name ".cursor*" -o -name ".claude*" -type d 2>/dev/null | head -20
git ls-files | grep -E "(settings|config|hooks)" | head -20Repository: solid-connection/solid-connect-server
Length of output: 1476
🏁 Script executed:
# Look for documentation about hook execution
find . -name "*.md" -o -name "*.txt" | xargs grep -l "hook\|shell\|execute" 2>/dev/null | head -10Repository: solid-connection/solid-connect-server
Length of output: 63
🏁 Script executed:
cat -n ./.claude/settings.jsonRepository: solid-connection/solid-connect-server
Length of output: 904
🏁 Script executed:
cat -n ./.claude/hooks/notify.ps1Repository: solid-connection/solid-connect-server
Length of output: 451
Windows에서 작동하지 않는 유닉스 셸 문법 수정 필요
현재 .claude/settings.json의 훅 명령어가 Windows 호환성 목표와 맞지 않습니다. 공식 Claude Code 문서에 따르면, Windows에서는 2>/dev/null, || 같은 유닉스 셸 문법이 작동하지 않습니다. 프로젝트에 이미 PowerShell 버전(notify.ps1)이 있음에도 불구하고, 현재 설정은 그것을 사용하고 있지 않습니다.
수정이 필요한 항목:
-
Notification 훅 (12행)
- 현재:
python3 .claude/hooks/notify.py 2>/dev/null || python .claude/hooks/notify.py - 문제: Unix 셸 리다이렉션(
2>/dev/null)과 논리 연산자(||) 불가 - 해결: PowerShell을 명시적으로 호출하도록 변경 필요
- 현재:
-
PostToolUse 훅 (23행)
- 현재:
python3 .claude/hooks/post-edit-check.py 2>/dev/null || python .claude/hooks/post-edit-check.py - 문제: 동일한 유닉스 셸 문법 사용
- 해결: 크로스플랫폼 호환 명령어로 변경 필요
- 현재:
두 훅 모두 공식 권장사항(PowerShell 명시적 호출)에 따라 수정하면 Windows에서도 안정적으로 작동합니다. 저장소에 이미 있는 notify.ps1 같은 리소스를 활용하여 완전한 Windows 지원을 갖출 수 있습니다.
🤖 Prompt for AI Agents
In @.claude/settings.json at line 12, Update the two hook command strings in
.claude/settings.json to remove Unix-only shell syntax and explicitly invoke
PowerShell on Windows: replace the Notification hook command that references
notify.py and the PostToolUse hook command that references post-edit-check.py so
they no longer use "2>/dev/null" or "||"; instead call PowerShell to run the
corresponding .ps1 scripts (use the existing .claude/hooks/notify.ps1 or a
post-edit-check PowerShell script if present) and fall back to the Python script
when PowerShell is not available, ensuring the JSON "command" values for those
hooks (the Notification and PostToolUse entries) are cross-platform and
Windows-compatible.
관련 이슈
작업 내용
settings.json에 작성된 hooks는 masOS 기준으로 작성되어, windows에서도 정상 동작하도록 수정했습니다.별도의 알림 파이썬 스크립트를 작성하여 OS별로 작업을 선택합니다.
스크립트를 수행 시
python으로 실행하는 구문을 추가했는데, windows 환경에서python3는C:\Users\chosh\AppData\Local\Microsoft\WindowsApps\python3를 가리키기에, 두 방식 모두 시도하도록 변경했습니다. 일단python으로 스크립트 수행하고, 제대로 동작하지 않으면(python이 설치되어 있지 않은 경우, macOS는python3가 기본 설치되어 있음)python3로 스크립트를 수행합니다.특이 사항
리뷰 요구사항 (선택)