Small, reversible workaround for Windows users of the ChatGPT Codex desktop app who see git.exe, powershell.exe, cmd.exe, conhost.exe, or blank Windows Terminal windows flash while Codex is working.
The canonical launcher is scripts\start-codex-with-windows-guard.ps1. The former console-named launcher and scripts\start-codex-with-git-wrapper.ps1 remain compatibility forwarders for existing setups.
The wrapper deliberately keeps Codex's powershell.exe compatibility path on the configured Windows PowerShell executable. It does not silently replace that executable with pwsh.exe; use a separate PowerShell 7 terminal for work that explicitly needs PowerShell 7.
This is a Windows-only compatibility tool. It supports both current
ChatGPT.exedesktop packages and olderCodex.exepackages; it is not a macOS or Linux Git wrapper.
ChatGPT Codex Windows, Codex Desktop Windows, Codex Git popup, git.exe flashing, PowerShell popup, cmd.exe flicker, conhost.exe flash, blank Windows Terminal, focus-stealing Terminal, CASCADIA_HOSTING_WINDOW_CLASS, and Codex console window.
For nearby but separate reports such as Codex high CPU, repeated shell/process activity, MCP process growth, or desktop crashes, treat them as upstream diagnostic problems rather than evidence that this guard will fix CPU or crash defects.
Start here. Give an agent this instruction before asking it to read the rest of the repository:
I am on Windows and ChatGPT Codex Desktop is flashing Git, PowerShell, CMD, conhost, or blank Terminal windows.
Use https://github.com/rwang23/codex-windows-guard as a reversible, Windows-only compatibility workaround.
Execution order:
1. Clone to a user-chosen local folder. Do not assume an existing absolute path.
2. Run scripts\install.ps1 and scripts\status.ps1. Report the detected package, wrapper state, default-terminal mode, and any recent guard-log rule.
3. If the symptom is a blank or focus-stealing `Terminal` / `CASCADIA_HOSTING_WINDOW_CLASS` window and status reports Automatic or Windows Terminal, explain the Console Host mitigation and apply it only with explicit user approval.
4. If no matching guard-log rule exists, capture the owner/process symptom before broadening the workaround. Never hide all terminals or all console windows.
Hard safety rules:
- Do not replace, rename, patch, or manually copy the real Git executable.
- Do not modify system PATH, user PATH, user TEMP/TMP, or machine TEMP/TMP.
- Change the two per-user default-terminal delegation values only with explicit approval; preserve the generated backup and state the restore command.
- A dedicated TEMP directory must remain wrapper-scoped, reversible, and leave its files in place when disabled.
- Use scripts\setup-and-start.ps1 only when the user explicitly approves a Codex restart.
- Never run a `-Force` launcher command from inside an active Codex task.
- Before finishing, provide the external-PowerShell launch command and the scripts\remove.ps1 rollback command.
An agent may install and verify the files. A user should run the final -Force restart command from an external PowerShell window so no active task is interrupted.
This repository originally focused on Git and shell wrapper windows. A separate symptom class is caused by Automatic default-terminal delegation: Windows can broker otherwise-unbound console UI through WindowsTerminal.exe / OpenConsole.exe, whose top-level CASCADIA_HOSTING_WINDOW_CLASS windows are service-owned rather than descendants of Codex. A process-ancestry guard cannot safely hide those windows without risking a user's legitimate terminal.
In the Windows setup used to validate this project, explicitly selecting Windows Console Host stopped the observed brokered Terminal flashes. This is a targeted, reversible mitigation for that symptom class—not a claim to fix every Codex subprocess, CPU, MCP, or crash problem.
Check the current mode first:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"
& (Join-Path $repo "scripts\configure-default-terminal.ps1") -Mode StatusIf the reported mode is Automatic or Windows Terminal and the symptom matches, apply the change from an external PowerShell window:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"
& (Join-Path $repo "scripts\configure-default-terminal.ps1") -Mode ConsoleHostOnly the current user's HKCU\Console\%%Startup delegation values change. Windows Terminal remains available when opened manually. Restore the exact saved values with -Mode Restore.
On some Windows installations, the Codex desktop app starts Git or PowerShell from a GUI process. Git for Windows is normally a console application, so a console window can briefly appear. Some recent Microsoft Store / MSIX builds can also launch through Windows in a way that bypasses the launcher's process-local PATH.
When Windows chooses Windows Terminal as the default terminal application, those launches can be delegated to brokered WindowsTerminal.exe / OpenConsole.exe processes. Their top-level CASCADIA_HOSTING_WINDOW_CLASS windows are parented by Windows services rather than Codex, so a process-ancestry guard cannot safely distinguish them from a terminal the user opened intentionally. They can flash, steal focus, or remain as blank Terminal windows.
The upstream fix belongs in Codex: its Windows subprocesses should be created without a visible console window. This repository is a local mitigation while that behavior is being fixed upstream.
Related upstream discussion:
- Git root metadata probes / high Git startup activity
- PowerShell and conhost flashing on Windows
- Visible PowerShell/conhost probe stealing focus
- Long-lived PowerShell parser / blank-window variant
- Git/conhost orphan behavior
- Duplicate MCP/app child processes
- Current Windows Git process storm
| Area | Supported behavior |
|---|---|
| Operating system | Windows only |
| Desktop package names | Current ChatGPT.exe and legacy Codex.exe MSIX packages |
| Git | Git for Windows; the installer prefers the direct mingw64\bin\git.exe executable when available |
| PowerShell | Windows PowerShell wrapper for Codex-launched commands; PowerShell 5.1 or newer to run the scripts |
| Native compiler | Optional, but needed to build the console-window guard. The process-local wrappers still work without it. |
This project deliberately does not:
- Replace, rename, patch, or otherwise modify your installed Git executable.
- Modify the system or user
PATHor the package installation. - Modify the registry by default. The explicit
-UseWindowsConsoleHostmode changes only the current user's two default-terminal delegation values underHKCU\Console\%%Startup, after saving their original state for restoration. - Hide arbitrary application windows. The guard evaluates the exact window-owning process graph. It covers targeted Git/CMD/PowerShell processes beneath ChatGPT/Codex, the packaged
codex.exebackend and known console helpers beneathChatGPT.exe, and the Chrome-parentedcmd.exebridge used by the bundled Chrome native host. It does not hide unrelated terminals or arbitrary GUI descendants. - Reduce Codex's underlying Git polling frequency, deduplicate MCP process pools, or fix every possible CPU/crash issue.
The default install location is %LOCALAPPDATA%\OpenAI\Codex\wrapper-bin, outside .codex, because recent Codex builds can apply restrictive ACLs below .codex.
scripts\install.ps1builds small GUI wrappers namedgit.exe,powershell.exe, andcmd.exein the wrapper directory. They forward arguments, standard streams, and exit codes to the real executables without creating a console window.scripts\start-codex-with-windows-guard.ps1starts Codex with that directory at the front of its process-localPATH.- When a native C++ compiler is available, the installer also builds
codex-console-window-guard.exe. The guard covers MSIX activation paths that bypass the localPATH: it observes new top-level windows and uses a sparse startup/30-second rescan so process-ancestry races and persistent blank helper windows are not missed. A rescan reads the process graph only after it finds a visible candidate window, avoiding idle process-table polling. - For systems where Windows Terminal delegation creates blank brokered windows, the explicit
-UseWindowsConsoleHostswitch selects the OS-supported legacy console host for unbound console launches. In the captured brokered-window symptom class, this avoids the Windows Terminal/OpenConsole delegation path without globally hidingWindowsTerminal.exe, which could also hide legitimate user terminals. The two GUID values follow Microsoft's documented Default terminal application policy. - The launcher reads the installed MSIX manifest rather than hard-coding the executable name. It therefore handles current
app\ChatGPT.exeand olderapp\Codex.exelayouts. - The guard records each window it actually hides in
%LOCALAPPDATA%\OpenAI\Codex\wrapper-bin\codex-console-window-guard.log. The log contains only a timestamp, PID, executable name, window class, and matching rule; it does not record command lines or window text. - The optional Codex temporary-directory configuration is stored in the wrapper installation directory. Each wrapper child reads it and sets its own
TEMPandTMP; it does not change the user-level or machine-level environment variables.
The guard is intentionally an observation-and-hide fallback. It never turns the real Git executable into a GUI executable, because that would make ordinary PowerShell Git commands behave asynchronously.
- Windows with Git for Windows installed and available on
PATH. - PowerShell 5.1 or later.
- The ChatGPT Codex desktop app installed from the Microsoft Store/MSIX channel.
- Optional: Visual Studio Build Tools or another native C++ compiler if you want the console-window guard. If it is unavailable, installation succeeds with the process-local wrappers only.
Clone the repository anywhere you prefer, then run the installer. This example uses a generic directory under your user profile, not a machine-specific project path:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"
git clone https://github.com/rwang23/codex-windows-guard.git $repo
& (Join-Path $repo "scripts\install.ps1")If Git is in a nonstandard location, find it first:
Get-Command git -AllThen provide the real executable explicitly:
& (Join-Path $repo "scripts\install.ps1") -RealGit "C:\Path\To\Git\mingw64\bin\git.exe"The installer records the real Git, PowerShell, and Command Prompt paths inside its own wrapper directory. It does not alter persistent environment variables.
After the first install, use this command from an external PowerShell window. It starts the existing wrappers and Windows Guard; it does not pull the repository or rebuild anything.
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"; & (Join-Path $repo "scripts\start-codex-with-windows-guard.ps1") -DisableShellSnapshot -SuppressProcessSampling -Force-Force closes a running ChatGPT/Codex desktop process before restarting it. Save your work first, and never run this command from an active Codex task, because it will terminate that task.
If Codex is already closed, you can omit -Force:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"; & (Join-Path $repo "scripts\start-codex-with-windows-guard.ps1") -DisableShellSnapshot -SuppressProcessSamplingUse this when the normal %TEMP% folder has accumulated many files and shell-based Codex operations feel slow. Put the directory on an SSD/NVMe volume; for example:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"
& (Join-Path $repo "scripts\configure-codex-temp.ps1") -Mode Enable -TempDir "C:\CodexTemp"This creates the directory if needed and makes only Codex wrapper children (git.exe, powershell.exe, and cmd.exe) use it. It leaves the Windows user/system TEMP and TMP values unchanged. New wrapper children read the setting immediately; after a wrapper refresh and Codex relaunch, the launcher also offers that directory to any direct launch path that inherits its process environment.
The one-shell snippet commonly shared for codex -C ... is useful for the standalone CLI, but it affects only that CLI process tree. Microsoft Store / MSIX desktop activation can bypass a parent shell's process-local environment, so this project keeps the setting beside the wrappers instead of claiming a global desktop-app override.
You can configure the directory while starting from an external PowerShell window:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"
& (Join-Path $repo "scripts\setup-and-start.ps1") -TempDir "C:\CodexTemp" -DisableShellSnapshot -SuppressProcessSampling -UseWindowsConsoleHost -ForceTo stop using the dedicated directory without deleting its files:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"
& (Join-Path $repo "scripts\configure-codex-temp.ps1") -Mode Disable| Switch | When to use it | Trade-off |
|---|---|---|
-Force |
Restart Codex when it is already running. Run only from external PowerShell. | Terminates current desktop tasks. |
-DisableShellSnapshot |
Codex is repeatedly starting PowerShell/conhost for shell/process snapshots. Requires the codex CLI to be available. |
Disables the background shell_snapshot feature in Codex user configuration. |
-SuppressProcessSampling |
Desktop process sampling is creating high CPU or repeated PowerShell/CIM activity. | Process CPU/metadata views in the desktop app can be incomplete while enabled. |
-UseWindowsConsoleHost |
Blank Windows Terminal windows titled Terminal appear or steal focus. |
Changes the current user's default terminal host for otherwise-unbound console apps; Windows Terminal can still be opened normally. Original values are backed up. |
-TempDir "C:\CodexTemp" |
The normal TEMP directory is crowded and wrapper-launched commands are slow. | Creates/uses a dedicated temp directory only for Codex wrapper children; does not globally move Windows TEMP/TMP. |
The optional switches address different symptoms. The console guard is for Codex-launched Git, Command Prompt, and PowerShell console flashes; the snapshot and sampling switches are for separate PowerShell/process-telemetry activity.
Do not run git pull every time you launch Codex. Update only when you want a newer workaround version or need to repair the installed wrapper:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"
git -C $repo pull --ff-only
& (Join-Path $repo "scripts\setup-and-start.ps1") -DisableShellSnapshot -SuppressProcessSampling -UseWindowsConsoleHost -ForceFor a first-time clone-or-update from any directory, use:
powershell -NoProfile -ExecutionPolicy Bypass -Command "$repo = Join-Path $env:USERPROFILE 'codex-windows-guard'; if (-not (Test-Path -LiteralPath $repo)) { git clone https://github.com/rwang23/codex-windows-guard.git $repo } else { git -C $repo pull --ff-only }; & (Join-Path $repo 'scripts\setup-and-start.ps1') -Force"Again, run a -Force command only from outside Codex.
Status:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"; & (Join-Path $repo "scripts\status.ps1")The status report includes the detected app package, wrapper install path, real Git path, current default-terminal mode, dedicated-wrapper TEMP status, console-guard presence/running state, recent guard-log matches, current Git resolution, persistent PATH checks, and running Codex processes.
Use the separate health snapshot when Codex feels slow or its stdio/MCP process count appears to grow:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"; & (Join-Path $repo "scripts\health-snapshot.ps1")For machine-readable output:
& .\scripts\health-snapshot.ps1 -AsJsonThe snapshot groups service roots beneath each Codex app-server, aggregates their process counts and memory, reports detached service candidates, and checks BB Browser daemon registration plus listener ownership. It is deliberately observation-only: it does not start, stop, suspend, or modify processes, files, services, configuration, or the registry. Command lines and the BB Browser daemon token are never included in its output. Generic plugin entrypoints are reported as plugin-mcp-cjs or plugin-mcp-mjs; the script does not guess a plugin identity that Windows cannot prove from the process surface.
Rollback is simple. Close Codex, then run:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"
& (Join-Path $repo "scripts\configure-default-terminal.ps1") -Mode Restore
& (Join-Path $repo "scripts\configure-codex-temp.ps1") -Mode Disable
& (Join-Path $repo "scripts\remove.ps1")Run the restore command only if -UseWindowsConsoleHost created a backup; otherwise it will report that no backup exists. No Git installation files need to be restored, because this project never changes them. You can also close Codex and launch it normally from the Start menu; the wrappers apply only to Codex launched by this project.
status.ps1 will report whether codex-console-window-guard.exe was built. If it is missing, install Visual Studio Build Tools/C++ (or another supported native compiler), then run scripts\install.ps1 again. The standard process-local wrappers can still help when the guard is unavailable.
Newer MSIX packages can deny ordinary file-read checks under WindowsApps even though Windows can launch the app. The launcher intentionally reads the app manifest and attempts the declared executable; it falls back to the registered AppsFolder entry if direct MSIX launch is denied. This warning does not mean the wrapper itself is corrupted.
Run status.ps1 first. Check whether the guard is present and running, whether the installed app package is detected, and whether the recent log contains one of these rules:
codex-shell: Git, CMD, PowerShell, or pwsh beneath ChatGPT/Codex.codex-backend: the packaged Codex backend or a known console helper beneathChatGPT.exe.chrome-native-host: thecmd.exebridge launched by Chrome for the bundled Codex Chrome native host.
No matching log entry means the remaining window has a different owner/process graph and should be captured before broadening the guard again. Do not work around that by globally hiding cmd.exe, PowerShell, Windows Terminal, or all console windows.
This is a different symptom class from a guard-log match: Automatic default-terminal delegation can broker the visible UI through WindowsTerminal.exe / OpenConsole.exe, beyond a safe Codex process-ancestry match. Run status.ps1 and check Default terminal application. If the mode is Automatic or Windows Terminal, and the unwanted window is titled Terminal with class CASCADIA_HOSTING_WINDOW_CLASS, apply the reversible compatibility mode from an external PowerShell window:
$repo = Join-Path $env:USERPROFILE "codex-windows-guard"; & (Join-Path $repo "scripts\configure-default-terminal.ps1") -Mode ConsoleHostThis changes only the current user's default host for otherwise-unbound console processes. It does not uninstall or disable Windows Terminal, and manually opening Windows Terminal still works. Restore the original values with -Mode Restore.
Run status.ps1 and check Codex wrapper temporary directory. If it is disabled, enable an SSD-backed path such as C:\CodexTemp with configure-codex-temp.ps1. The setting affects new child processes launched through the wrappers; it does not make the desktop app's own MSIX activation inherit a temporary directory when Windows starts it through an AppX broker.
If the issue started after a Codex desktop update, capture the app package version and status.ps1 output (with any private paths removed) and open or update an upstream issue. The project will keep tracking Windows package behavior, but it cannot replace a native upstream process-launch fix.
That is not part of the normal flow. It can occur when a managed wrapper cannot load its runtime. Run the installer again, check status.ps1, and then launch Codex through the standard launcher. Current native-wrapper builds avoid the known working-directory trigger.
The repository includes focused Windows regression checks. From a clone, run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\tests\install-regression.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\tests\launcher-regression.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\tests\console-window-guard-regression.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\tests\default-terminal-regression.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\tests\codex-temp-regression.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\tests\health-snapshot-regression.ps1The native-guard test simulates both ChatGPT.exe and legacy Codex.exe launching a Git console process, verifies diagnostic logging, and asserts process-graph rules for shell launchers, the packaged Codex backend, and the Chrome native-host bridge. It skips only when no native compiler is available.
Please report the desktop package version, the exact visible process/window symptom, and the redacted status.ps1 output. Do not include personal paths, account data, or tokens.
- Do not manually copy, rename, or replace
git.exe. - Do not add the wrapper directory to persistent user or machine
PATH. - Prefer the smallest workaround needed for your symptom.
- Remove this workaround after Codex fixes the Windows Git process-launch behavior upstream.