diff --git a/hooks/gsd-context-monitor.js b/hooks/gsd-context-monitor.js index cae8fc930..c3f5630c3 100644 --- a/hooks/gsd-context-monitor.js +++ b/hooks/gsd-context-monitor.js @@ -27,9 +27,14 @@ const STALE_SECONDS = 60; // ignore metrics older than 60s const DEBOUNCE_CALLS = 5; // min tool uses between warnings let input = ''; +// Timeout guard: if stdin doesn't close within 3s (e.g. pipe issues on +// Windows/Git Bash), exit silently instead of hanging until Claude Code +// kills the process and reports "hook error". See #775. +const stdinTimeout = setTimeout(() => process.exit(0), 3000); process.stdin.setEncoding('utf8'); process.stdin.on('data', chunk => input += chunk); process.stdin.on('end', () => { + clearTimeout(stdinTimeout); try { const data = JSON.parse(input); const sessionId = data.session_id; diff --git a/hooks/gsd-statusline.js b/hooks/gsd-statusline.js index dfc03fa3d..9d3fb5b59 100755 --- a/hooks/gsd-statusline.js +++ b/hooks/gsd-statusline.js @@ -8,9 +8,13 @@ const os = require('os'); // Read JSON from stdin let input = ''; +// Timeout guard: if stdin doesn't close within 3s (e.g. pipe issues on +// Windows/Git Bash), exit silently instead of hanging. See #775. +const stdinTimeout = setTimeout(() => process.exit(0), 3000); process.stdin.setEncoding('utf8'); process.stdin.on('data', chunk => input += chunk); process.stdin.on('end', () => { + clearTimeout(stdinTimeout); try { const data = JSON.parse(input); const model = data.model?.display_name || 'Claude';