[BUG] UserPromptSubmit hooks hang indefinitely on Windows (stdin pipe not closed)
Description
UserPromptSubmit hooks hang indefinitely on Windows when the hook script reads from stdin via json.load(sys.stdin). The same script works perfectly on macOS and also runs fine when tested manually on Windows with piped stdin (echo '{}' | python3 script.py).
SessionStart hooks using the exact same stdin-reading pattern (json.load(sys.stdin)) work correctly on Windows. Only UserPromptSubmit hooks exhibit this behavior.
Reproduction Steps
- Create a minimal UserPromptSubmit hook that reads stdin:
#!/usr/bin/env python
import json, sys
def main():
try:
hook_input = json.load(sys.stdin)
except (json.JSONDecodeError, EOFError):
return
# immediately returns - no heavy processing
if __name__ == "__main__":
main()
- Register it in
.claude/settings.json:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "python3 \".claude/hooks/my-hook.py\""
}
]
}
]
}
}
- Run on Windows:
echo "hello" | claude --print - Observe: hangs for several minutes before eventually responding (or never responds)
Expected Behavior
The hook should execute quickly (< 1 second) just as it does on macOS.
Actual Behavior
The hook hangs indefinitely. json.load(sys.stdin) appears to never receive EOF, causing it to wait for more data forever.
Debugging Evidence
| Configuration | Windows Result | macOS Result |
|---|---|---|
| {} (no hooks) | ~8s ✅ | Normal ✅ |
| SessionStart hooks only (3 hooks, all read stdin) | 7s ✅ | Normal ✅ |
| SessionStart + UserPromptSubmit | Hangs 5-11 min ❌ | Normal ✅ |
| Manual: echo '{}' \| python3 hook.py | Instant ✅ | Instant ✅ |
This confirms the issue is in how Claude Code pipes stdin to UserPromptSubmit hooks on Windows, not in the script itself.
Environment
- OS: Windows 10 (Build 19045)
- Python: 3.13.3
- Claude Code: latest (auto-updated)
- Shell: PowerShell 5.1
- Drive: External SSD (USB), but also reproduced on internal paths
Related Issues
- #46601 — Same stdin pipe issue but for Stop hooks on Windows (our case is UserPromptSubmit)
- #14219 — Windows 11 hooks failing silently
Root Cause Hypothesis
Claude Code likely does not properly close/EOF the stdin pipe for UserPromptSubmit (and possibly Stop/PostToolUse) hook subprocesses on Windows. On macOS, POSIX pipe semantics handle this correctly. On Windows, the pipe handle may remain open, causing json.load(sys.stdin) or sys.stdin.read() to block waiting for more data that never arrives.
SessionStart hooks appear to use a different code path that correctly closes the pipe.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗