fix: eliminate Windows console popups during daemon spawn and Chroma operations (#751)
* fix: eliminate Windows console popups during daemon spawn and Chroma operations Two changes to fix Windows Terminal popup issues: 1. Worker daemon spawn (ProcessManager.spawnDaemon): - Windows: Use WMIC to spawn truly independent process without console - WMIC creates processes that survive parent exit and have no console association - Properly handles paths with spaces via double-quoting - Unix: Unchanged behavior with standard detached spawn 2. PID file handling (worker-service.ts): - Worker now writes its own PID after listen() succeeds (all platforms) - Removes race condition where spawner wrote PID before worker was ready - On Windows, spawner PID was useless anyway 3. Chroma vector search (ChromaSync.ts): - Temporarily disabled on Windows to prevent MCP SDK subprocess popups - Will be re-enabled when we migrate to persistent HTTP server architecture - Windows users still get full observation storage, just no semantic search Tested on Windows 11 via SSH - worker spawns without console popups, survives parent process exit, and all lifecycle commands (start/stop/restart) work correctly. Fixes #748, #708, #681, #676, #675 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add YAML frontmatter to slash commands for discoverability Commands /do and /make-plan were not appearing in Claude Code because they lacked the required YAML frontmatter metadata. Added description and argument-hint fields to both commands. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: bigphoot <bigphoot@gmail.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -262,21 +262,55 @@ export async function cleanupOrphanedProcesses(): Promise<void> {
|
||||
/**
|
||||
* Spawn a detached daemon process
|
||||
* Returns the child PID or undefined if spawn failed
|
||||
*
|
||||
* On Windows, uses WMIC to spawn a truly independent process that
|
||||
* survives parent exit without console popups. WMIC creates processes
|
||||
* that are not associated with the parent's console.
|
||||
*
|
||||
* On Unix, uses standard detached spawn.
|
||||
*
|
||||
* PID file is written by the worker itself after listen() succeeds,
|
||||
* not by the spawner (race-free, works on all platforms).
|
||||
*/
|
||||
export function spawnDaemon(
|
||||
scriptPath: string,
|
||||
port: number,
|
||||
extraEnv: Record<string, string> = {}
|
||||
): number | undefined {
|
||||
const isWindows = process.platform === 'win32';
|
||||
const env = {
|
||||
...process.env,
|
||||
CLAUDE_MEM_WORKER_PORT: String(port),
|
||||
...extraEnv
|
||||
};
|
||||
|
||||
if (isWindows) {
|
||||
// Use WMIC to spawn a process that's independent of the parent console
|
||||
// This avoids the console popup that occurs with detached: true
|
||||
// Paths must be individually quoted for WMIC when they contain spaces
|
||||
const execPath = process.execPath;
|
||||
const script = scriptPath;
|
||||
// WMIC command format: wmic process call create "\"path1\" \"path2\" args"
|
||||
const command = `wmic process call create "\\"${execPath}\\" \\"${script}\\" --daemon"`;
|
||||
|
||||
try {
|
||||
execSync(command, {
|
||||
stdio: 'ignore',
|
||||
windowsHide: true
|
||||
});
|
||||
// WMIC returns immediately, we can't get the spawned PID easily
|
||||
// Worker will write its own PID file after listen()
|
||||
return 0;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Unix: standard detached spawn
|
||||
const child = spawn(process.execPath, [scriptPath, '--daemon'], {
|
||||
detached: true,
|
||||
stdio: 'ignore',
|
||||
windowsHide: true,
|
||||
env: {
|
||||
...process.env,
|
||||
CLAUDE_MEM_WORKER_PORT: String(port),
|
||||
...extraEnv
|
||||
}
|
||||
env
|
||||
});
|
||||
|
||||
if (child.pid === undefined) {
|
||||
@@ -284,6 +318,7 @@ export function spawnDaemon(
|
||||
}
|
||||
|
||||
child.unref();
|
||||
|
||||
return child.pid;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user