From 29b3417a7a6d87a0db48841ce5f316f9e9711352 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 18 May 2026 23:20:22 +0200 Subject: [PATCH] fix(windows): hide bash helper consoles closes #4699 --- packages/agent/CHANGELOG.md | 1 + packages/agent/src/harness/env/nodejs.ts | 7 ++++++- packages/coding-agent/CHANGELOG.md | 1 + packages/coding-agent/src/core/tools/bash.ts | 1 + packages/coding-agent/src/utils/shell.ts | 7 ++++++- 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/agent/CHANGELOG.md b/packages/agent/CHANGELOG.md index 44fa99ee..7c04cc4c 100644 --- a/packages/agent/CHANGELOG.md +++ b/packages/agent/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed - Fixed tail truncation for oversized single-line output that ends with a trailing newline ([#4715](https://github.com/earendil-works/pi/issues/4715)). +- Fixed Windows Node execution environment command spawns to hide helper console windows from background processes ([#4699](https://github.com/earendil-works/pi/issues/4699)). ## [0.75.3] - 2026-05-18 diff --git a/packages/agent/src/harness/env/nodejs.ts b/packages/agent/src/harness/env/nodejs.ts index b86f6fe8..931651bc 100644 --- a/packages/agent/src/harness/env/nodejs.ts +++ b/packages/agent/src/harness/env/nodejs.ts @@ -108,7 +108,10 @@ async function runCommand( let stdout = ""; let child: ReturnType; try { - child = spawn(command, args, { stdio: ["ignore", "pipe", "ignore"] }); + child = spawn(command, args, { + stdio: ["ignore", "pipe", "ignore"], + windowsHide: true, + }); } catch { resolve({ stdout: "", status: null }); return; @@ -192,6 +195,7 @@ function killProcessTree(pid: number): void { spawn("taskkill", ["/F", "/T", "/PID", String(pid)], { stdio: "ignore", detached: true, + windowsHide: true, }); } catch { // Ignore errors. @@ -275,6 +279,7 @@ export class NodeExecutionEnv implements ExecutionEnv { detached: process.platform !== "win32", env: getShellEnv(this.shellEnv, options?.env), stdio: ["ignore", "pipe", "pipe"], + windowsHide: true, }); } catch (error) { const cause = toError(error); diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 87dd1e88..7ff38a6a 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed - Fixed the subagent extension's parallel mode to return useful per-task output and failed-task diagnostics to the parent model instead of 100-character previews ([#4710](https://github.com/earendil-works/pi/issues/4710)). +- Fixed Windows local bash execution to hide helper console windows when launched from background SDK processes ([#4699](https://github.com/earendil-works/pi/issues/4699)). ## [0.75.3] - 2026-05-18 diff --git a/packages/coding-agent/src/core/tools/bash.ts b/packages/coding-agent/src/core/tools/bash.ts index 1d6591d4..20728500 100644 --- a/packages/coding-agent/src/core/tools/bash.ts +++ b/packages/coding-agent/src/core/tools/bash.ts @@ -76,6 +76,7 @@ export function createLocalBashOperations(options?: { shellPath?: string }): Bas detached: process.platform !== "win32", env: env ?? getShellEnv(), stdio: ["ignore", "pipe", "pipe"], + windowsHide: true, }); if (child.pid) trackDetachedChildPid(child.pid); let timedOut = false; diff --git a/packages/coding-agent/src/utils/shell.ts b/packages/coding-agent/src/utils/shell.ts index 1c235802..7e3cc8ef 100644 --- a/packages/coding-agent/src/utils/shell.ts +++ b/packages/coding-agent/src/utils/shell.ts @@ -15,7 +15,11 @@ function findBashOnPath(): string | null { if (process.platform === "win32") { // Windows: Use 'where' and verify file exists (where can return non-existent paths) try { - const result = spawnSync("where", ["bash.exe"], { encoding: "utf-8", timeout: 5000 }); + const result = spawnSync("where", ["bash.exe"], { + encoding: "utf-8", + timeout: 5000, + windowsHide: true, + }); if (result.status === 0 && result.stdout) { const firstMatch = result.stdout.trim().split(/\r?\n/)[0]; if (firstMatch && existsSync(firstMatch)) { @@ -190,6 +194,7 @@ export function killProcessTree(pid: number): void { spawn("taskkill", ["/F", "/T", "/PID", String(pid)], { stdio: "ignore", detached: true, + windowsHide: true, }); } catch { // Ignore errors if taskkill fails