Skip to content

Commit eee081e

Browse files
committed
detached process
1 parent 09a8d24 commit eee081e

1 file changed

Lines changed: 22 additions & 8 deletions

File tree

src/bin/codegraph.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import { Command } from 'commander';
2626
import * as path from 'path';
2727
import * as fs from 'fs';
28+
import { spawn } from 'child_process';
2829
import CodeGraph, { getCodeGraphDir, findNearestCodeGraphRoot } from '../index';
2930
import type { IndexProgress } from '../index';
3031
import { runInstaller } from '../installer';
@@ -957,8 +958,11 @@ program
957958
/**
958959
* codegraph sync-if-dirty [path]
959960
*
960-
* Syncs the index only if .codegraph/.dirty exists.
961-
* Removes the marker BEFORE syncing so edits during sync
961+
* Checks if .codegraph/.dirty exists and, if so, spawns a detached
962+
* background process to run `codegraph sync`. The hook process exits
963+
* immediately so Claude Code's Stop hook never blocks.
964+
*
965+
* Removes the marker BEFORE spawning so edits during sync
962966
* create a new marker for the next Stop event.
963967
* Runs silently and always exits 0.
964968
*/
@@ -972,7 +976,7 @@ program
972976
if (!projectRoot) {
973977
process.exit(0);
974978
}
975-
const dirtyPath = path.join(getCodeGraphDir(projectRoot), '.dirty');
979+
const dirtyPath = path.join(getCodeGraphDir(projectRoot!), '.dirty');
976980

977981
// No marker → nothing to do (sub-ms exit)
978982
if (!fs.existsSync(dirtyPath)) {
@@ -983,14 +987,24 @@ program
983987
try { fs.unlinkSync(dirtyPath); } catch { /* ignore */ }
984988

985989
// If not fully initialized (no DB), exit
986-
if (!CodeGraph.isInitialized(projectRoot)) {
990+
if (!CodeGraph.isInitialized(projectRoot!)) {
987991
process.exit(0);
988992
}
989993

990-
// Run sync
991-
const cg = await CodeGraph.open(projectRoot);
992-
await cg.sync();
993-
cg.destroy();
994+
// Spawn `codegraph sync` as a detached background process
995+
// so this hook exits immediately and doesn't block Claude Code
996+
const isWindows = process.platform === 'win32';
997+
const child = spawn(
998+
isWindows ? 'codegraph' : process.argv[0]!,
999+
isWindows ? ['sync', '--quiet', projectRoot!] : [process.argv[1]!, 'sync', '--quiet', projectRoot!],
1000+
{
1001+
detached: true,
1002+
stdio: 'ignore',
1003+
windowsHide: true,
1004+
shell: isWindows,
1005+
}
1006+
);
1007+
child.unref();
9941008
} catch {
9951009
// Never fail — this runs at the end of Claude responses
9961010
}

0 commit comments

Comments
 (0)