From 5f36d2bf9a49dff3fb27e7fb361da3a5e39dfc23 Mon Sep 17 00:00:00 2001 From: CrystallDEV Date: Wed, 10 Dec 2025 00:15:14 +0100 Subject: [PATCH] fix(windows): hide terminal windows when spawning child processes --- scripts/smart-install.js | 20 ++++++++------------ src/services/worker-service.ts | 9 +++++++++ src/services/worker/BranchManager.ts | 6 ++++-- src/shared/paths.ts | 3 ++- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/scripts/smart-install.js b/scripts/smart-install.js index ee79f332..d1767779 100644 --- a/scripts/smart-install.js +++ b/scripts/smart-install.js @@ -17,18 +17,14 @@ import { join } from 'path'; import { homedir } from 'os'; import { createRequire } from 'module'; -// CRITICAL: Always use marketplace directory for ALL operations -// This script may run from the cache directory (plugin/scripts/) but must -// operate on the marketplace directory where package.json and node_modules live. -// This ensures cross-platform compatibility and avoids cache directory confusion. -const MARKETPLACE_ROOT = join(homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack'); -// Use MARKETPLACE_ROOT for all paths - this script can be deployed anywhere -// but always operates on the marketplace directory -const PLUGIN_ROOT = MARKETPLACE_ROOT; -const PACKAGE_JSON_PATH = join(PLUGIN_ROOT, 'package.json'); -const VERSION_MARKER_PATH = join(PLUGIN_ROOT, '.install-version'); -const NODE_MODULES_PATH = join(PLUGIN_ROOT, 'node_modules'); +// CRITICAL: Always use marketplace directory for npm install and PM2/ecosystem +// This script may run from cache directory (plugin/) which has no package.json +// The marketplace root is the canonical location with package.json and node_modules +const MARKETPLACE_ROOT = join(homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack'); +const PACKAGE_JSON_PATH = join(MARKETPLACE_ROOT, 'package.json'); +const VERSION_MARKER_PATH = join(MARKETPLACE_ROOT, '.install-version'); +const NODE_MODULES_PATH = join(MARKETPLACE_ROOT, 'node_modules'); const BETTER_SQLITE3_PATH = join(NODE_MODULES_PATH, 'better-sqlite3'); // Colors for output @@ -264,7 +260,7 @@ async function runNpmInstall() { // Run npm install silently execSync(command, { - cwd: PLUGIN_ROOT, + cwd: MARKETPLACE_ROOT, stdio: 'pipe', // Silent output unless error encoding: 'utf-8', }); diff --git a/src/services/worker-service.ts b/src/services/worker-service.ts index ec9588b8..3abb1cba 100644 --- a/src/services/worker-service.ts +++ b/src/services/worker-service.ts @@ -6,6 +6,15 @@ * See src/services/worker/README.md for architecture details. */ +// Windows terminal window fix: Set process.type to trick MCP SDK into enabling windowsHide +// The SDK checks `process.type === 'renderer'` (Electron detection) before setting windowsHide. +// By setting process.type, the SDK's isElectron() check becomes truthy on Windows, hiding +// terminal windows when spawning uvx/python processes for Chroma MCP server. +// The type is sometimes not present resulting in the check being false. Setting it like this fixes it +if (process.platform === 'win32' && !process.type) { + (process as any).type = 'renderer'; +} + import express from 'express'; import http from 'http'; import path from 'path'; diff --git a/src/services/worker/BranchManager.ts b/src/services/worker/BranchManager.ts index df5a7a2a..07476f29 100644 --- a/src/services/worker/BranchManager.ts +++ b/src/services/worker/BranchManager.ts @@ -36,7 +36,8 @@ function execGit(command: string): string { return execSync(`git ${command}`, { cwd: INSTALLED_PLUGIN_PATH, encoding: 'utf-8', - timeout: 30000 + timeout: 30000, + windowsHide: true }).trim(); } @@ -47,7 +48,8 @@ function execShell(command: string, timeoutMs: number = 60000): string { return execSync(command, { cwd: INSTALLED_PLUGIN_PATH, encoding: 'utf-8', - timeout: timeoutMs + timeout: timeoutMs, + windowsHide: true }).trim(); } diff --git a/src/shared/paths.ts b/src/shared/paths.ts index 231c7326..e20854c3 100644 --- a/src/shared/paths.ts +++ b/src/shared/paths.ts @@ -89,7 +89,8 @@ export function getCurrentProjectName(): string { const gitRoot = execSync('git rev-parse --show-toplevel', { cwd: process.cwd(), encoding: 'utf8', - stdio: ['pipe', 'pipe', 'ignore'] + stdio: ['pipe', 'pipe', 'ignore'], + windowsHide: true }).trim(); return basename(gitRoot); } catch {