feat(cli): codegraph stop / list to manage background daemons (#861)
Adds first-class daemon control (the #845 pain point: no clean way to stop a runaway daemon). `codegraph stop [path]` stops the current/given project's daemon (SIGTERM -> SIGKILL fallback, sweeps artifacts); `stop --all` stops every daemon; `list`/`ps` shows running daemons (--json for scripts). Discovery via a small self-healing registry: each daemon records its root under ~/.codegraph/daemons/ on start, removes it on graceful shutdown; readers prune dead pids. Cross-platform by construction (files + process.kill). Validated live on macOS, Linux (docker), and Windows (VM): registry unit 6/6 and real-daemon stop/list 6/6 on each.
This commit is contained in:
@@ -54,6 +54,7 @@ import {
|
||||
getDaemonSocketPath,
|
||||
} from './daemon-paths';
|
||||
import { CodeGraphPackageVersion } from './version';
|
||||
import { registerDaemon, deregisterDaemon } from './daemon-registry';
|
||||
|
||||
/** Default idle linger after the last client disconnects. */
|
||||
const DEFAULT_IDLE_TIMEOUT_MS = 300_000;
|
||||
@@ -191,6 +192,10 @@ export class Daemon {
|
||||
startedAt: Date.now(),
|
||||
};
|
||||
|
||||
// Drop a discovery record so `codegraph list` / `stop --all` can find us.
|
||||
// Best-effort; a missing record only means list's liveness prune covers it.
|
||||
registerDaemon({ root: this.projectRoot, ...lock });
|
||||
|
||||
process.stderr.write(
|
||||
`[CodeGraph daemon] Listening on ${this.socketPath} (pid ${process.pid}, v${CodeGraphPackageVersion}). Idle timeout ${this.idleTimeoutMs}ms.\n`
|
||||
);
|
||||
@@ -244,6 +249,7 @@ export class Daemon {
|
||||
}
|
||||
this.engine.stop();
|
||||
this.cleanupLockfile();
|
||||
deregisterDaemon(this.projectRoot);
|
||||
if (process.platform !== 'win32') {
|
||||
try { fs.unlinkSync(this.socketPath); } catch { /* may already be gone */ }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user