Windows: hide command-safety PowerShell parser process to avoid pwsh.exe console flashes

Open 💬 9 comments Opened Apr 22, 2026 by WanderlustCoder
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

On Windows, @openai/codex 0.122.0 (native codex.exe) spawns a command-safety PowerShell parser process as:

pwsh.exe -NoLogo -NoProfile -NonInteractive -EncodedCommand <...>

When codex.exe itself is launched hidden by a parent process, the descendant pwsh.exe still briefly flashes a visible console window. This appears to be because the PowerShell parser child process is spawned without Windows hide/no-window creation flags.

Evidence

Captured on Windows 11 on 2026-04-22 while running TORQUE factory Codex tasks:

torque-server (node.exe, windowsHide:true)
  └── codex.exe  (spawned directly, not through codex.cmd / node wrapper)
        └── pwsh.exe -NoLogo -NoProfile -NonInteractive -EncodedCommand <...>

The parent windowsHide:true is applied to codex.exe. The pwsh.exe descendant still flashes a visible console. We already bypassed the npm/node wrapper (@openai/codex/bin/codex.js) and spawn the bundled native binary directly; the remaining visible window is from the native binary's own child process.

Likely call site

In the current upstream tree, the command-safety parser process is started in:

codex-rs/shell-command/src/command_safety/powershell_parser.rs

Specifically, PowershellParserProcess::spawn() builds:

let mut child = Command::new(executable)
    .args([
        "-NoLogo",
        "-NoProfile",
        "-NonInteractive",
        "-EncodedCommand",
        encoded_parser_script(),
    ])
    .stdin(Stdio::piped())
    .stdout(Stdio::piped())
    .stderr(Stdio::null())
    .spawn()?;

I do not see a Windows-specific creation_flags() call on this Command before .spawn().

Suggested fix

On Windows, apply CREATE_NO_WINDOW to the PowerShell parser child process:

#[cfg(windows)]
use std::os::windows::process::CommandExt;

#[cfg(windows)]
const CREATE_NO_WINDOW: u32 = 0x08000000;

let mut command = Command::new(executable);
command
    .args([
        "-NoLogo",
        "-NoProfile",
        "-NonInteractive",
        "-EncodedCommand",
        encoded_parser_script(),
    ])
    .stdin(Stdio::piped())
    .stdout(Stdio::piped())
    .stderr(Stdio::null());

#[cfg(windows)]
command.creation_flags(CREATE_NO_WINDOW);

let mut child = command.spawn()?;

An equivalent STARTF_USESHOWWINDOW + SW_HIDE setup would also work, but CREATE_NO_WINDOW is the simplest fit for a non-interactive helper process.

Reproducer

  1. On Windows 11, install @openai/codex@0.122.0.
  2. From a parent process, spawn the native bundled codex.exe with hidden-window semantics. For example, Node child_process.spawn(..., { windowsHide: true }).
  3. Run several Codex tasks that trigger shell command-safety checks.
  4. Observe that pwsh.exe -NoLogo -NoProfile -NonInteractive -EncodedCommand <...> children appear in the process tree and briefly flash visible console windows.

Expected: the parser pwsh.exe children still run, but no visible console window appears, even briefly.

Actual: a visible PowerShell console flashes for the parser child despite the parent being hidden.

Notes

This is not a request to change the npm wrapper. The wrapper has already been bypassed in the reproducer. The requested fix is in the Rust/native binary's PowerShell parser spawn path.

View original on GitHub ↗

9 Comments

github-actions[bot] contributor · 4 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #17208

Powered by Codex Action

11suixing11 · 2 months ago

I'm also affected by this issue on Windows 11 with Codex Desktop (v26.601.2237.0).

Every time Codex executes a shell command, a PowerShell console window briefly flashes on screen (appears and disappears within a second). This is very disruptive during work.

Environment:

  • OS: Windows 11 (26100.8497)
  • Codex Desktop: 26.601.2237.0
  • PowerShell: 5.1.26100.8497

The pwsh.exe child processes are spawned with -NoProfile -NonInteractive but without CREATE_NO_WINDOW, causing the visible console flash.

Would appreciate if this could be prioritized as it significantly impacts the user experience on Windows.

ryanquadrel · 1 month ago

Reproduced on Codex Desktop for Windows (Store package 26.707.3563.0). I prepared the minimal upstream fix on a public fork: https://github.com/ryanquadrel/codex/commit/acc2ab3b6c58b5c3d07ccd096d42dfb181d00283 . It applies CREATE_NO_WINDOW to the non-interactive PowerShell parser child while preserving piped stdio. Cross-fork PR creation is currently rejected by the repository API, so this links the ready-to-cherry-pick commit directly.

BlindsidedGames · 1 month ago

Reproduced on a newer Codex Desktop for Windows build, with the persistent-window variant shown in this issue.

Environment:

  • Codex Desktop package: OpenAI.Codex_26.707.9564.0_x64__2p2nqsd0c76g0
  • OS: Microsoft Windows NT 10.0.26200.0 x64
  • Observed: 2026-07-14

Live process inspection showed this chain:

ChatGPT.exe (packaged Codex desktop host)
  -> codex.exe -c features.code_mode_host=true app-server --analytics-default-enabled
     -> powershell.exe -NoLogo -NoProfile -NonInteractive -EncodedCommand ...

Decoding the PowerShell payload confirms that it begins:

Long-lived PowerShell AST parser used by the Rust command-safety layer on Windows.

The PowerShell child remains alive rather than being a short transient probe, matching the duration of the user-visible symptom. Correction/clarification: the visible surface is not a conventional black console window. As shown in the screenshots below, it is a completely blank dark-grey window with rounded corners, no title bar, no terminal text, and no visible minimize/maximize/close controls. It remains on the desktop until the associated process ends.

A conhost.exe child is also present in the packaged app-server process tree. The process evidence strongly associates the behavior with this Codex helper path, but the exact HWND owner was not captured while the blank window was present, so the visible surface should not be overclassified as a standard console window.

This is still reproducible on 26.707.9564.0, newer than the 26.707.3563.0 confirmation above. The linked CREATE_NO_WINDOW change still appears directly applicable to this long-lived parser path.

I also observed the separate short-lived Desktop process-snapshot PowerShell commands (Get-CimInstance Win32_Process / Win32_PerfFormattedData_PerfProc_Process), which are tracked more directly in #26613.

<img width="739" height="478" alt="Blank dark-grey rounded window behind Codex" src="https://github.com/user-attachments/assets/92c27b27-5585-4602-be59-34a9c41b45c6" />

<img width="420" height="319" alt="Close-up of blank dark-grey rounded window without controls" src="https://github.com/user-attachments/assets/3b46b880-2ff5-465e-852c-3c7786c57271" />

rwang23 · 1 month ago

The packaged Windows desktop topology is still relevant on newer builds: local inspection of 26.707.12708.0 showed the ChatGPT.exe -> codex.exe backend path with long-lived PowerShell/conhost helpers. That is compatible with the persistent blank-window variant described here, although a local guard cannot prove the exact HWND owner after the fact.

For users who need a reversible desktop-side mitigation while waiting for the native fix, I maintain:

https://github.com/rwang23/codex-windows-console-guard

Its latest guard recognizes the packaged Codex backend and known console helpers beneath ChatGPT.exe, in addition to the Git/CMD/PowerShell paths. It hides only matched windows and writes a bounded diagnostic log; it does not change the underlying parser process or claim to fix its lifecycle.

The proposed upstream CREATE_NO_WINDOW change remains the correct root fix for this non-interactive parser path. A window-hiding guard is only a compatibility fallback for already shipped desktop builds.

kivikdigitalgroup · 21 days ago

Confirmation / forensic update (2026-08-06)

Still reproducing on current Windows ChatGPT/Codex desktop app-server.

Environment

  • Package: OpenAI.Codex Microsoft Store / WindowsApps
  • Identity version: 26.730.7989.0
  • Binary: C:\Program Files\WindowsApps\OpenAI.Codex_...\app\resources\codex.exe
  • Host: Windows 10 (build 19045-class), x64
  • Also present: npm @openai/codex 0.146.0 vendor codex.exe (same AST payload string; also lacks CREATE_NO_WINDOW string)

Process tree (live)

codex.exe  -c features.code_mode_host=true app-server --analytics-default-enabled
  └── powershell.exe -NoLogo -NoProfile -NonInteractive -EncodedCommand <...>

Decoded payload header (exact):

# Long-lived PowerShell AST parser used by the Rust command-safety layer on Windows.
# The caller starts one child process per PowerShell executable variant and then sends
# newline-delimited JSON requests over stdin:

Binary inspection

Scanned installed codex.exe (Store 26.730.7989.0, ~347 MB):

  • Contains: Long-lived PowerShell AST parser..., command-safety, powershell.exe, -WindowStyle / Hidden (appears only in agent guidance text, not as process spawn flags)
  • Does NOT contain: CREATE_NO_WINDOW, SW_HIDE, STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE string markers

So the child is still being spawned without Win32 no-window creation flags. -WindowStyle Hidden is not applied to this long-lived AST helper (or is insufficient alone when the parent is a console-capable process).

Symptom for users

Visible PowerShell console open/close flashes while Codex app-server is running in the background — even when the user is typing in a different app (e.g. Hermes CLI). It is easy to mis-attribute to keystrokes; the correlation is Codex tool/command-safety activity / helper lifetime, not the other app's input.

Requested fix

Spawn the AST helper with:

  • CREATE_NO_WINDOW (0x08000000), and/or
  • STARTF_USESHOWWINDOW + SW_HIDE, and/or
  • powershell.exe -WindowStyle Hidden on the argv

plus keep stdin/stdout redirected as today. Do not disable command-safety — only hide the console host.

Happy to retest a preview build against 26.730.7989.0.

tranhieu204-web · 6 days ago

Controlled measurement + a second window source the parser-only fix won't cover

Reproduced on Windows 11 Pro 26200, Store package OpenAI.Codex_26.818.3698.0, runtime bundle 26.819.11345 (PowerShell 7.6.4).

Not repeating the root cause — @ryanquadrel's commit and @kivikdigitalgroup's binary inspection already establish it. Three additions.

1. Controlled A/B on the creation flag

Spawning the bundled pwsh.exe from a true GUI-subsystem parent (pythonw.exe, no console), using Codex's exact argv shape (piped stdin/stdout, null stderr):

no flag            -> conhost +2,  visible windows +2
                      one of class CASCADIA_HOSTING_WINDOW_CLASS,
                      titled with the codex-runtimes pwsh path
CREATE_NO_WINDOW   -> conhost +1,  visible windows +0

Confirms the proposed fix works, and costs only a hidden conhost.

2. Console inheritance — why parent-side windowsHide is topology-dependent

parent WITH a hidden console, child spawned with NO flag
   -> conhost +0, windows +0     (child inherits; allocates nothing)

GUI parent (pythonw launched from a hidden-console shell)
   -> "has console at all: False"

A CUI child inherits a parent's hidden console and allocates nothing. But a GUI parent holds no console to pass down, so every CUI descendant allocates its own. That is exactly the desktop topology:

explorer.exe -> ChatGPT.exe (GUI) -> codex.exe (CUI) -> pwsh.exe (CUI)

This may explain why the original report's windowsHide: true on codex.exe did not stop the descendant flash, while other topologies appear unaffected.

3. codex.exe allocates its own console too

conhost 1832   parent 35428   codex.exe -c features.code_mode_host=true app-server

Under ChatGPT.exe this is a separate allocation from the parser's. Patching PowershellParserProcess::spawn() alone is necessary but may not be sufficient for the desktop variant — ChatGPT.exe's spawn of codex.exe needs suppression too, or that console remains. This is a plausible explanation for the persistent blank window variant @BlindsidedGames reported, as distinct from the parser flash.

Note for affected desktop users

The desktop app runs codex.exe from inside the signed MSIX package (C:\Program Files\WindowsApps\...), which is not user-replaceable. The writable standalone install at %LOCALAPPDATA%\Programs\OpenAI\Codex\bin is a different copy the desktop app does not use — so users cannot self-patch the desktop case. Flipping the PE subsystem of the cached helpers is also not a safe workaround: it invalidates the Authenticode signature (verified: Valid → broken → Valid after restore) and misses the other CUI executables.

Only an upstream build fixes the desktop path.

tranhieu204-web · 6 days ago

Correction to my previous comment — point 3 was wrong.

I claimed ChatGPT.exe's spawn of codex.exe also needs console suppression. That is incorrect, and I withdraw it.

app.asar does set windowsHide: true on the CLI spawn, and I verified on the live process that the resulting console is not visible:

conhost 1832  parent 35428  codex.exe ... app-server
EnumWindows -> no visible window owned by pid 1832 or 35428  (console is HIDDEN)

So the Desktop side is already doing the right thing, and PowershellParserProcess::spawn() remains the correct single fix target. Apologies for the noise.

Points 1 and 2 stand as measured, and point 2 now sharpens into an open question worth flagging:

  • A CUI child launched from a parent that already has a hidden console inherits it and allocates nothing (measured: conhost +0, windows +0).
  • codex.exe does have a hidden console here, courtesy of windowsHide: true.
  • Yet the pwsh.exe parser still produces a visible CASCADIA_HOSTING_WINDOW_CLASS window.

So inheritance is not happening for that child. That points at the parser spawn requesting its own console rather than inheriting the parent's — consistent with @kivikdigitalgroup's finding that the binary contains no CREATE_NO_WINDOW / STARTF_USESHOWWINDOW markers, and consistent with the original report that parent-side windowsHide: true did not stop the descendant flash.

If that reading is right, CREATE_NO_WINDOW on the parser spawn (as in @ryanquadrel's commit) is both necessary and sufficient, and no Desktop-side change is required.

The user-facing note in my previous comment is unaffected: desktop users cannot self-patch, because the app runs codex.exe from the signed MSIX package while the writable standalone install at %LOCALAPPDATA%\Programs\OpenAI\Codex\bin is a different copy the app does not use.

jimmylee-cell · 4 days ago

I prepared and Windows-compiled the minimal fix at https://github.com/jimmylee-cell/codex/commit/0122876924 : apply CommandExt::creation_flags(CREATE_NO_WINDOW) to PowershellParserProcess::spawn. rustfmt --check and cargo check -p codex-shell-command pass on Windows. Cross-fork PR creation is currently rejected for this account, so the public commit is available for cherry-pick/review.