* Spawn the shared daemon as a fully detached background process: its own * session/process group (so a SIGHUP/SIGINT to the launcher's terminal can't * reach it) with stdio decoupled from the launcher (logs to * `.codegraph/daemon.log`). Re-invokes the *same* CLI faithfully across dev and * bun
(root: string)
| 176 | * launcher proxies through the single winner. |
| 177 | */ |
| 178 | function spawnDetachedDaemon(root: string): void { |
| 179 | const scriptPath = process.argv[1]; |
| 180 | if (!scriptPath) { |
| 181 | // No resolvable CLI entry point to re-invoke — let the caller fall back to |
| 182 | // direct mode rather than spawn something broken. |
| 183 | throw new Error('cannot resolve CLI script path to spawn the daemon'); |
| 184 | } |
| 185 | |
| 186 | let logFd: number | null = null; |
| 187 | let stdio: StdioOptions = 'ignore'; |
| 188 | try { |
| 189 | logFd = fs.openSync(path.join(getCodeGraphDir(root), 'daemon.log'), 'a'); |
| 190 | stdio = ['ignore', logFd, logFd]; |
| 191 | } catch { |
| 192 | stdio = 'ignore'; // no log file — discard daemon output rather than fail |
| 193 | } |
| 194 | try { |
| 195 | // The daemon has no host: scrub the threaded host pid so it can't leak |
| 196 | // into the daemon's env (and from there into anything the daemon spawns), |
| 197 | // where a long-dead session's host pid would trigger spurious shutdowns. |
| 198 | const env: NodeJS.ProcessEnv = { ...process.env, [DAEMON_INTERNAL_ENV]: '1' }; |
| 199 | delete env[HOST_PPID_ENV]; |
| 200 | const child = spawn( |
| 201 | process.execPath, |
| 202 | [...process.execArgv, scriptPath, 'serve', '--mcp', '--path', root], |
| 203 | { |
| 204 | detached: true, |
| 205 | stdio, |
| 206 | windowsHide: true, |
| 207 | env, |
| 208 | }, |
| 209 | ); |
| 210 | child.unref(); |
| 211 | } finally { |
| 212 | // The child holds its own dup of the log fd now; the launcher doesn't need it. |
| 213 | if (logFd !== null) { |
| 214 | try { fs.closeSync(logFd); } catch { /* ignore */ } |
| 215 | } |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | /** |
| 220 | * MCP Server for CodeGraph |
no test coverage detected