Skip to content

Windows: createLocalBashOperations() can flash a console window from hidden/background Node processes #4699

@sodie2323

Description

@sodie2323

What happened?

On Windows, when createLocalBashOperations() runs bash from a hidden/background Node process, a black console window can briefly appear.

This does not usually happen when running bash from pi’s normal interactive TUI, but it is visible when pi is used from an SDK/background process.

Likely cause: spawn(shell, ...) in the bash tool does not set windowsHide: true.

Steps to reproduce

Create repro-child.mjs:

 import { appendFileSync } from "node:fs";
 import { createLocalBashOperations } from "@earendil-works/pi-coding-agent";

 const log = new URL("./repro.log", import.meta.url);
 const ops = createLocalBashOperations();

 appendFileSync(log, `child pid=${process.pid}\n`);

 await ops.exec("echo bash-start; pwd; sleep 8; echo bash-done", process.cwd(), {
   onData: (buf) => appendFileSync(log, buf),
 });

 appendFileSync(log, "\nchild done\n");

Create repro-launch.mjs:

 import { spawn } from "node:child_process";
 import { fileURLToPath } from "node:url";

 const childScript = fileURLToPath(new URL("./repro-child.mjs", import.meta.url));

 const child = spawn(process.execPath, [childScript], {
   cwd: process.cwd(),
   detached: true,
   stdio: "ignore",
   windowsHide: true,
 });

 child.unref();

 console.log(`launched hidden child pid=${child.pid}`);
 console.log("Watch for a black bash console window for ~8 seconds.");

Run:

 node repro-launch.mjs

Expected behavior

No console window should appear when pi starts bash from a hidden/background process.

A likely fix is to add windowsHide: true to the bash spawn options, and possibly also to Windows helper spawns like where and taskkill.

Version

0.75.3

Suggested fix

Add windowsHide: true to Windows child process launches used by local bash execution.

Main fix:

 const child = spawn(shell, [...args, command], {
   cwd,
   detached: process.platform !== "win32",
   env: env ?? getShellEnv(),
   stdio: ["ignore", "pipe", "pipe"],
   windowsHide: true,
 });

This is in the local bash backend, currently around:

 packages/coding-agent/src/core/tools/bash.ts
 createLocalBashOperations()

It may also be worth adding windowsHide: true to Windows helper process calls in shell utilities, for example:

 spawnSync("where", ["bash.exe"], {
   encoding: "utf-8",
   timeout: 5000,
   windowsHide: true,
 });

and:

 spawn("taskkill", ["/F", "/T", "/PID", String(pid)], {
   stdio: "ignore",
   detached: true,
   windowsHide: true,
 });

These are likely in:

 packages/coding-agent/src/utils/shell.ts

I tested the same repro with a local copy of the bash execution logic plus windowsHide: true, and the black console window no
longer appeared.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinginprogressIssue is being worked on

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions