Windows/pwsh: apply_patch.bat breaks multiline patch arguments; direct codex.exe --codex-run-as-apply-patch succeeds with the same patch

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

What version of Codex CLI is running?

codex-cli 0.111.0

What subscription do you have?

plus

Which model were you using?

gpt-4.5

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

What terminal emulator and version are you using (if applicable)?

PowerShell 7.5.4

What issue are you seeing?

On Windows with PowerShell, apply_patch fails for valid multiline patch strings when invoked through
apply_patch.bat. The exact same patch succeeds when passed directly to codex.exe --codex-run-as-apply-patch, which
suggests the Windows wrapper is corrupting or truncating multiline arguments during forwarding. The observed error is:
Invalid patch: The last line of the patch must be '*** End Patch'.

What steps can reproduce the bug?

  1. Run Codex CLI on Windows in PowerShell.
  2. Check which executable is actually being used for apply_patch:

``powershell
Get-Command apply_patch
Get-Content -Raw (Get-Command apply_patch).Path
``

On my machine this resolves to a temporary wrapper like:

``text
C:\Users\xxx\.codex\tmp\arg0\codex-arg0ARnQri\apply_patch.bat
``

and the wrapper contains:

``bat
@echo off
"...\codex.exe" --codex-run-as-apply-patch %*
``

  1. Prepare a multiline patch string in PowerShell:

``powershell
$patch = @"
*** Begin Patch
*** Add File: hello.txt
+hello
*** End Patch
"@
``

  1. Invoke the wrapper entrypoint:

``powershell
apply_patch $patch
``

On my machine this fails with:

``text
Invalid patch: The last line of the patch must be '*** End Patch'
``

  1. Invoke the underlying executable directly with the exact same $patch value:

``powershell
$codexExe = "...path extracted from the wrapper..."
& $codexExe --codex-run-as-apply-patch $patch
``

On my machine this succeeds and creates hello.txt.

What is the expected behavior?

apply_patch should be a reliable Windows entrypoint for multiline patch content.

If Codex uses a Windows shim or wrapper, it should preserve the patch argument exactly, including embedded newlines. Agents and workers that are instructed to edit files via apply_patch should not be blocked by shell-wrapper behavior.

What do you see instead?

A valid-looking multiline patch fails when sent through apply_patch.bat, but the identical patch succeeds when passed directly to codex.exe --codex-run-as-apply-patch.

That makes this look like a Windows wrapper / argument-forwarding bug, not a patch-format bug in the payload itself.

Additional information

I verified this locally on the same machine using the same patch content and saw different results depending only on the entrypoint:

  • apply_patch $patch failed
  • codex.exe --codex-run-as-apply-patch $patch succeeded

That isolates the behavior difference to the Windows wrapper path.

This matters because Codex agents are often instructed to edit files via apply_patch. On Windows/PowerShell, that becomes brittle if the wrapper forwards multiline arguments via %* and does not preserve them losslessly.

Potential fix directions:

  • Bypass the .bat wrapper and expose a native executable entrypoint for apply_patch on Windows.
  • Pass patch content via stdin, a temp file, or another transport that does not depend on %* preserving multiline payloads.
  • Change the Windows shim implementation so multiline arguments survive forwarding intact.

Additional information

Related issues:

View original on GitHub ↗

4 Comments

github-actions[bot] contributor · 5 months ago

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

  • #12350
  • #13574
  • #13773
  • #13721

Powered by Codex Action

doraemonkeys · 5 months ago

I reviewed the suggested issues and do not think this report is a duplicate of them.

  • #12350 is an Access is denied failure on mapped/UNC Windows worktrees.
  • #13574 is a Codex App default-permission / sandbox refusal issue.
  • #13773 is a model-specific reliability report for built-in edit/patch actions.
  • #13721 is a Codex App / Windows-WSL targeted patch workflow inconsistency report.

This issue is narrower: on Windows PowerShell, apply_patch resolves to apply_patch.bat, and the same multiline
patch fails via that wrapper but succeeds when passed directly to codex.exe --codex-run-as-apply-patch. That points
to a Windows wrapper / argument-forwarding problem rather than the issues above, so I am keeping this issue open.

Geekmemz · 5 months ago

I am experiencing the same underlying issue, but specifically within the Codex Desktop UWP App.

For additional context on why this bites users:

  1. Unstable UI Interception: The Desktop App is supposed to intercept ^Gpply_patch when requested via shell_command (to display the native UI Diff viewer). However, this interception is hit-or-miss. When it fails, the command "leaks" down to the shell wrapper.
  2. Forced PowerShell: Despite configuring Git Bash in the app settings, the sandbox ^[nvironment_context is hard-locked to <shell>powershell</shell>.

Because AI agents often prefer bash heredoc syntax (^Gpply_patch <<'PATCH'), when the UI interception fails, powershell receives bash syntax and crashes/timeouts. Even when the agent is instructed to use pipeline syntax (@'...'@ | apply_patch), the .bat wrapper mentioned in this issue destroys the multiline formatting.

Our current workaround:
We entirely replaced the .bat wrapper in our PATH with an ^Gpply_patch.ps1 script that correctly parses PowerShell Here-Strings ( | Out-String) and directly invokes codex.exe --codex-run-as-apply-patch. This proves that if the wrapper correctly forwarded multiline arguments, the underlying binary works perfectly.

yihao5un · 2 months ago

Independently reproduced this on the non-Store CLI build (codex-cli 0.142.0-alpha.6 / Codex CLI v0.141.0) on Windows 11, PowerShell 7.6.2.

Calling the generated shim:

$patch = @'
*** Begin Patch
*** Update File: C:\path\verify.txt
@@
-hello world
+hello apply_patch ok
*** End Patch
'@
apply_patch $patch
# -> Invalid patch: The last line of the patch must be '*** End Patch'

Bypassing the .bat and calling codex.exe directly with the same $patch works:

& "C:\Users\<me>\AppData\Roaming\npm\node_modules\@openai\codex\node_modules\@openai\codex-win32-x64\vendor\x86_64-pc-windows-msvc\bin\codex.exe" --codex-run-as-apply-patch $patch
# -> Success. Updated the following files: M C:\path\verify.txt

Root cause as I see it: the shim is

@echo off
"...\codex.exe" --codex-run-as-apply-patch %*

cmd.exe's %* expansion collapses an argv that contains real \n into a single physical line — the trailing *** End Patch (and intermediate lines) are dropped. This is structural to cmd.exe argument passing; switching the caller shell doesn't help (PowerShell, cmd, double-click all hit the same .bat → cmd → codex.exe argv[] path).

Workarounds that worked for me:

  • PowerShell $PROFILE wrapper that calls codex.exe --codex-run-as-apply-patch $patch directly, exported as Set-Alias apply_patch ....
  • Or have the agent emit codex.exe ... directly and never go through the .bat.

Suggested fixes for the shim (any one):

  1. Have it read the patch from stdin instead of %*.
  2. Have it write %* to a temp file and pass the temp file path to codex.exe.
  3. Replace the .bat with a small PowerShell .ps1 wrapper that calls codex.exe with the patch as a single argv string (PowerShell preserves the argv boundary correctly).