Windows: codex-code-mode-host opens a visible Windows Terminal window

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

What version of Codex CLI is running?

@openai/codex 0.147.0 (current npm latest at the time of filing).

Also observed while Codex Desktop 26.803.5235.0 was installed, but the visible window captured in this report identified the global npm package path, not the protected WindowsApps package path.

Subscription and model

This appears independent of subscription and model. It occurs when a local Code Mode tool call causes the standalone host process to be spawned.

Platform

  • Windows 11 x64
  • Version 10.0.26200, build 26200
  • Windows Terminal configured as the default terminal application

What issue are you seeing?

When the standalone Code Mode host is started from the Windows npm package, Windows Terminal opens a visible window whose command is the packaged console executable:

%APPDATA%\npm\node_modules\@openai\codex\node_modules\@openai\codex-win32-x64\vendor\x86_64-pc-windows-msvc\bin\codex-code-mode-host.exe

The window can remain open and requires manual closing. A live process/window capture correlated the following components in the same creation-time cluster:

codex.exe
  -> codex-code-mode-host.exe
     -> conhost.exe

OpenConsole.exe / WindowsTerminal.exe -> visible terminal window

The packaged codex-code-mode-host.exe is PE subsystem 3 (IMAGE_SUBSYSTEM_WINDOWS_CUI).

The current source starts the host in codex-rs/code-mode/src/remote_session/connection.rs, Connection::spawn():

https://github.com/openai/codex/blob/3aae5d885bac39c1262491aa3fd100dfd8b3919f/codex-rs/code-mode/src/remote_session/connection.rs#L213-L224

The command configures Unix process groups, stdio pipes, and kill_on_drop, but has no Windows creation flag before .spawn():

let mut command = Command::new(host_program);
#[cfg(unix)]
command.process_group(0);
let mut child = command
    .stdin(Stdio::piped())
    .stdout(Stdio::piped())
    .stderr(Stdio::piped())
    .kill_on_drop(true)
    .spawn()?;

Because the parent is a GUI/headless process and the child is a Windows console-subsystem executable, Windows can allocate the configured default terminal for it.

Steps to reproduce

  1. Install @openai/codex@0.147.0 globally on Windows.
  2. Configure Windows Terminal as the default terminal application.
  3. Start a Codex session that uses local Code Mode.
  4. Invoke a local Code Mode tool so the standalone host is created.
  5. Observe a visible Windows Terminal window whose command is codex-code-mode-host.exe.

This may be easier to reproduce after terminating an existing long-lived host so the next tool call must create a fresh one.

Expected behavior

codex-code-mode-host.exe should run as an internal background helper without creating a visible terminal window or stealing focus. Its stdin/stdout/stderr protocol and exit behavior must remain unchanged.

Root-cause hypothesis and validated mitigation

A local proof of concept placed a Windows GUI-subsystem shim at the expected host path and retained the signed vendor binary as codex-code-mode-host.real.exe. The shim:

  • forwards all arguments;
  • inherits stdin, stdout, and stderr;
  • starts the real host with CREATE_NO_WINDOW;
  • waits for it and returns the same exit code.

Validation results:

shim -> codex-code-mode-host.real.exe: confirmed
stdin/stdout round trip: passed
exit-code propagation: passed
real host startup and EOF shutdown: passed
visible host Terminal windows: 0

Before the mitigation, the visible Terminal window identified codex-code-mode-host.exe. After forcing a fresh host start through the shim, no matching visible window was created.

The binary-replacement shim is only a diagnostic mitigation and is not proposed as the product fix. It is update-fragile and changes the packaged executable identity.

Suggested product fix

In Connection::spawn(), apply CREATE_NO_WINDOW (or the equivalent supported Tokio/Windows process option) to the host command on Windows before .spawn(), while preserving the existing pipe and lifecycle behavior.

Conceptually:

let mut command = Command::new(host_program);

#[cfg(unix)]
command.process_group(0);

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

A Windows regression test should verify both protocol behavior and absence of an allocated visible console for a freshly spawned host.

Related but not duplicate

  • #18984 tracks the command-safety PowerShell parser console flash.
  • #20510 tracks the long-lived PowerShell helper spawned by background codex exec.
  • #33254 tracks the Computer Use turn-ended notifier console window.

Those issues involve different child executables. This report is specifically about the standalone codex-code-mode-host.exe spawn boundary.

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 19 days ago

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

  • #37153
  • #36560

Powered by Codex Action

wstczyw · 19 days ago

Thanks for the duplicate check. I reviewed both candidates; this appears related, but not a duplicate.

  • #36560 is specifically the long-lived powershell.exe AST safety parser spawned from the command-safety layer. This report concerns the separate codex-code-mode-host.exe process, spawned by Connection::spawn() in codex-rs/code-mode/src/remote_session/connection.rs.
  • #37153 reports the broader symptom of transient console windows from desktop command runners, but it does not identify codex-code-mode-host.exe or this spawn site.

The executable, lifetime/protocol, and source boundary are different. A fix limited to the PowerShell parser spawn in #36560 would not affect the Code Mode host spawn. Conversely, the proposed CREATE_NO_WINDOW change here belongs on the standalone host Command in Connection::spawn().

I am therefore leaving #37599 open as the precise Code Mode host case. It can be cross-linked with #37153 as one concrete cause of that broader symptom.

wstczyw · 18 days ago

Corrected follow-up: below is the final acceptance evidence for the Codex Desktop-version-matched CLI build used to reproduce and mitigate #37599.

Exact version and source provenance

  • Codex Desktop: 26.803.5235.0
  • CLI bundled by that Desktop package: codex-cli 0.147.0-alpha.6.5
  • Local patched CLI: codex-cli 0.147.0-alpha.6.5
  • Exact upstream source: annotated tag rust-v0.147.0-alpha.6.5, resolving to commit 618b8e9

The patch's three preimage blob IDs match that tag exactly:

  • codex-rs/code-mode/src/remote_session/connection.rs: d08c8fbbc448...
  • codex-rs/shell-command/src/command_safety/powershell_parser.rs: 00b18af6f053...
  • codex-rs/shell-command/src/powershell.rs: 9730439bea31...

#37599-specific patch

The relevant Code Mode Host change is:

 let mut command = Command::new(host_program);
 #[cfg(unix)]
 command.process_group(0);
+#[cfg(windows)]
+command.creation_flags(0x08000000); // CREATE_NO_WINDOW
 let mut child = command
     .stdin(Stdio::piped())
     .stdout(Stdio::piped())
     .stderr(Stdio::piped())
     .kill_on_drop(true)
     .spawn()?;

The end-to-end validation patch also routes the long-lived PowerShell parser and PowerShell discovery probes through the existing Windows no-console helper. Those companion changes remove separate PowerShell popup surfaces; they are not being presented as the root fix for #37599.

The build was installed in an external versioned directory and selected through the supported CODEX_CLI_PATH override. No file under the signed/protected WindowsApps package was modified. The deployed codex-code-mode-host.exe is byte-for-byte identical to the Desktop-packaged host:

patched codex.exe SHA-256:
9447A8C9833C4402379B98A6434B779F618137DB69369196D3247BEC37894DD5

packaged and deployed codex-code-mode-host.exe SHA-256:
E1DD9FA70FEE2BAD00671EB9EF0089CF86CD1A9765CB9A4160082514D7399B95

Validation

The original build/acceptance run passed the focused Rust tests for the affected Code Mode and PowerShell launch paths, the release build, an App Server handshake, and five bounded top-level Windows Terminal observations.

After a full Desktop restart, I repeated the runtime read-back:

  • the running process chain is the external patched codex.exe -> codex-code-mode-host.exe;
  • the patched CLI still reports the exact Desktop-matched version;
  • the App Server initialize handshake returned successfully, exited 0, and produced no stderr;
  • a 30-second observation at 100 ms sampling recorded 223 samples, 0 visible window events, and 0 newly observed processes with a visible main window.

This is a validated local mitigation, not a claim that upstream is fixed. As of current main commit 355ee6c, Connection::spawn() still has no Windows creation flag, so #37599 should remain open.