Skip to content

Commit ee758e1

Browse files
oalanicolasclaude
andcommitted
fix: address CodeRabbit review issues for PR #582
- precompact-session-digest.cjs: spawn detached child process instead of require()-ing runner in-process. The runner uses setImmediate internally which kept the event loop alive and caused the hook to block (wait for the 9 s safety timeout) instead of being fire-and-forget. Context is forwarded via AIOX_HOOK_CONTEXT env var to the inline Node script. - synapse-engine.cjs: replace process.exitCode = 0 with process.exit(0) in the timeout callback. process.exitCode alone does not terminate the process when active handles remain (e.g. stdout backpressure), defeating the 5 s hard limit that protects Claude Code from a blocking hook. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1b56576 commit ee758e1

2 files changed

Lines changed: 21 additions & 3 deletions

File tree

.claude/hooks/precompact-session-digest.cjs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,23 @@ async function main() {
8585
provider: 'claude',
8686
};
8787

88-
const { onPreCompact } = require(runnerPath);
89-
await onPreCompact(context);
88+
// Spawn a detached child process so the digest is fire-and-forget.
89+
// Using require() in-process keeps the event loop alive (setImmediate inside
90+
// the runner), causing the hook to block until the 9 s safety timeout.
91+
// The child receives context via AIOX_HOOK_CONTEXT env var and calls
92+
// onPreCompact() exported by the runner module.
93+
const { spawn } = require('child_process');
94+
const inlineScript = [
95+
`const ctx = JSON.parse(process.env.AIOX_HOOK_CONTEXT || '{}');`,
96+
`const { onPreCompact } = require(${JSON.stringify(runnerPath)});`,
97+
`onPreCompact(ctx).catch(() => {});`,
98+
].join('\n');
99+
const child = spawn(process.execPath, ['-e', inlineScript], {
100+
detached: true,
101+
stdio: 'ignore',
102+
env: { ...process.env, AIOX_HOOK_CONTEXT: JSON.stringify(context) },
103+
});
104+
child.unref();
90105
}
91106

92107
/** Entry point runner — sets safety timeout and executes main(). */

.claude/hooks/synapse-engine.cjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ async function main() {
9090
/** Entry point runner — lets Node exit naturally after stdout flush. */
9191
function run() {
9292
const timer = setTimeout(() => {
93-
process.exitCode = 0;
93+
// process.exitCode alone won't terminate the process if active handles
94+
// remain (e.g. stdout backpressure). Use process.exit() to enforce the
95+
// 5 s hard limit and guarantee the hook never blocks Claude Code.
96+
process.exit(0);
9497
}, HOOK_TIMEOUT_MS);
9598
timer.unref();
9699
main()

0 commit comments

Comments
 (0)