diff --git a/plugin/scripts/session-end.mjs b/plugin/scripts/session-end.mjs index 019149c30..de2f6d53f 100755 --- a/plugin/scripts/session-end.mjs +++ b/plugin/scripts/session-end.mjs @@ -51,7 +51,7 @@ async function main() { headers: authHeaders(), signal: AbortSignal.timeout(3e4) }).catch(() => {}); - setTimeout(() => process.exit(0), 1500).unref(); + setTimeout(() => process.exit(0), 1500); } main(); diff --git a/src/hooks/session-end.ts b/src/hooks/session-end.ts index 6a9fc429c..1ce7773fe 100644 --- a/src/hooks/session-end.ts +++ b/src/hooks/session-end.ts @@ -63,7 +63,11 @@ async function main() { }).catch(() => {}); } - setTimeout(() => process.exit(0), 1500).unref(); + // Force-exit after 1500ms regardless of in-flight fetches. Without this, + // .unref() makes the timer passive and pending fetch() calls keep the event + // loop alive until their AbortSignal timeouts fire (up to 120s), causing + // Claude Code to cancel the hook with "Hook cancelled". + setTimeout(() => process.exit(0), 1500); } main();