fix: Hide console window on Windows when spawning child processes (#166)

* fix: Hide console window on Windows when spawning child processes

Add windowsHide: true to spawnSync and execSync calls to prevent
empty console windows from appearing on Windows when hooks execute.

Fixes two spawn points:
- worker-utils.ts: PM2 spawn when starting worker service
- user-message-hook.ts: Node spawn for context display

Reference: https://nodejs.org/api/child_process.html (windowsHide option)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Add windowsHide to remaining execSync calls for complete Windows console window hiding

This completes the Windows console window fix by adding `windowsHide: true` to all remaining `execSync` calls:

- src/services/worker-service.ts:220 - pgrep command for orphaned process detection
- src/services/worker-service.ts:226 - pkill command for process cleanup
- src/services/worker/SDKAgent.ts:414 - where/which claude command for finding executable

These operations are less frequent than the user-prompt hook, but should still avoid spawning console windows on Windows for a complete fix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Alex Newman <thedotmack@users.noreply.github.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Alex Newman <thedotmack@users.noreply.github.com>
This commit is contained in:
Alex Newman
2025-12-04 16:02:35 -05:00
committed by GitHub
parent 9e66a4843e
commit e1d2ffeb02
8 changed files with 14 additions and 12 deletions
+2 -1
View File
@@ -44,7 +44,8 @@ try {
// Cross-platform path to context-hook.js in the installed plugin
const contextHookPath = join(homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack', 'plugin', 'scripts', 'context-hook.js');
const output = execSync(`node "${contextHookPath}" --colors`, {
encoding: 'utf8'
encoding: 'utf8',
windowsHide: true
});
const port = getWorkerPort();
+2 -2
View File
@@ -217,13 +217,13 @@ export class WorkerService {
// Find orphaned uvx processes (which spawn chroma servers)
try {
const processes = execSync('pgrep -fl uvx', { encoding: 'utf-8', stdio: 'pipe' }).trim();
const processes = execSync('pgrep -fl uvx', { encoding: 'utf-8', stdio: 'pipe', windowsHide: true }).trim();
if (processes) {
const processCount = processes.split('\n').length;
logger.info('WORKER', 'Cleaning up orphaned MCP processes', { count: processCount });
// Kill the processes
execSync('pkill -f uvx', { stdio: 'pipe' });
execSync('pkill -f uvx', { stdio: 'pipe', windowsHide: true });
logger.success('WORKER', `Cleaned up ${processCount} orphaned MCP server processes`);
}
} catch (error: any) {
+1 -1
View File
@@ -411,7 +411,7 @@ export class SDKAgent {
*/
private findClaudeExecutable(): string {
const claudePath = process.env.CLAUDE_CODE_PATH ||
execSync(process.platform === 'win32' ? 'where claude' : 'which claude', { encoding: 'utf8' })
execSync(process.platform === 'win32' ? 'where claude' : 'which claude', { encoding: 'utf8', windowsHide: true })
.trim().split('\n')[0].trim();
if (!claudePath) {
+2 -1
View File
@@ -67,7 +67,8 @@ async function startWorker(): Promise<boolean> {
const result = spawnSync(pm2Command, ['start', ecosystemPath], {
cwd: pluginRoot,
stdio: 'pipe',
encoding: 'utf-8'
encoding: 'utf-8',
windowsHide: true
});
if (result.status !== 0) {
throw new Error(result.stderr || 'PM2 start failed');