Windows CLI launcher (agent.cmd) hardcodes PowerShell 5.1; `$args` strips `"` and can glue the next argument

Where does the bug appear (feature/product)?

Cursor CLI

Describe the Bug

This is not the IDE Agent Shell / --shell issue
(Agent CLI on Windows: No way to configure shell (hardcoded to PowerShell, no --shell flag or config option)
and
[Windows] Agent still uses PowerShell 5.1 despite PS7 default (still on Cursor 3.14.27)).

Those threads are about which shell the agent uses to run commands. This report is about the Windows CLI launcher corrupting the CLI’s own argv before index.js runs.

%LOCALAPPDATA%\cursor-agent\agent.cmd always starts Windows PowerShell 5.1:

%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%\cursor-agent.ps1" %*

cursor-agent.ps1 then does:

& "$nodePath" "...\index.js" $args

PowerShell 5.1’s legacy native argument passing drops embedded " when forwarding $args to a native process. A value that contains a double quote therefore does not reach the CLI intact. In at least one CRT-quoted case it also merges the following argv slot, so later flags shift.

This is not Cursor’s argument parser. It happens in the launcher, before the CLI sees argv.

Installing PowerShell 7 (pwsh) is not a workaround: that path is permanently 5.1; Microsoft never replaces it with 7; the launcher never calls pwsh. Patching agent.cmd would be overwritten on update, and the cmd → -File … %* hop is still PowerShell parsing, not CRT.

Related: the same agent.cmd starts with setlocal enabledelayedexpansion before %*, so cmd consumes every ! (a!bab; an undefined !NAME! can drop the argument and shift the next flag). That happens before PowerShell starts and is independent of 5.1 vs 7.

Steps to Reproduce

  1. On Windows, install the Cursor Agent CLI so %LOCALAPPDATA%\cursor-agent\agent.cmd and cursor-agent.ps1 are present. Confirm agent.cmd invokes %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -File …\cursor-agent.ps1 %*, and that the .ps1 ends with & "$nodePath" "...\index.js" $args.
  2. Build a replica of that launcher: a .cmd with setlocal enabledelayedexpansion that calls powershell.exe -File script.ps1 %*, and a .ps1 that runs & python argv-printer.py $args (print sys.argv[1:] as JSON).
  3. From Python (or any CreateProcess caller), launch without a shell, quoting arguments with Microsoft C-runtime rules. Example tail: --model + CRT-quoted has"quote + GO.
  4. Compare with an npm-style .cmd that forwards %* straight to the same Python printer (no PowerShell).

Observed through that replica:

Input value npm-style .cmd (exe %*, no PowerShell) Cursor-shaped launcher (cmd → PS 5.1 -File$args)
high high high
has"quote has"quote --model received hasquote GO (quote gone, next token glued)
quote'and"both intact double quote gone; following token glued

cmd forwarding %* to a native exe preserves the quote; the PowerShell $args hop does not.

I have not run this against a live agent -p session. The replica matches the installed launcher files on this machine. Inferred, not executed, that index.js therefore receives the stripped argv.

Expected Behavior

Quoted values in --model, prompts, and other CLI arguments should reach index.js byte-for-byte, the same way they do through an .exe or an npm-style .cmd that does not hop through PowerShell 5.1 $args.

A following argument must stay a separate argv slot (--model, has"quote, GO), not be glued into the previous one.

Installing PowerShell 7 should not be required — and today it would not even be used, because the 5.1 path is hardcoded. Prefer invoking node.exe / index.js without the 5.1 $args hop (or call pwsh only if that path is actually proven to preserve CRT-quoted argv).

! in arguments should also survive; enabledelayedexpansion in agent.cmd currently eats it before PowerShell starts.

Operating System

Windows 10/11

Version Information

  • OS: Windows 11 Home, 10.0.26200
  • Product: Cursor Agent CLI (Windows launcher), not the IDE Agent Shell
  • Install: %LOCALAPPDATA%\cursor-agent\
  • Launcher files: agent.cmd, cursor-agent.ps1 (the .cmd hardcodes C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe)
  • Windows PowerShell: 5.1 (the only engine the launcher calls)
  • PowerShell 7 / pwsh: not used by this launcher (and not required to reproduce)

Additional Information

It does stop me from trusting the Windows Agent CLI with real argument values. Anything that needs a faithful agent / CLI path — prompts or flags that may contain ", and on this launcher also ! — I will send to Claude’s CLI instead, which is a real .exe on Windows and does not go through this cmd → PS 5.1 $args chain.

Cursor the editor stays; Windows agent/cursor CLI work gets delegated to the tool that does not eat quotes. Happy to switch that work back the day the launcher stops doing it.

Does this stop you from using Cursor

Sometimes - I can sometimes use Cursor

Hey, thanks for such a detailed report. The breakdown with the repro and the comparison table for %* vs PowerShell $args really helps, and you were right to separate this from the --shell agent-shell threads.

What you’re seeing isn’t intended behavior, and it’s not something in your setup. Quoted values and ! should reach the CLI byte-for-byte. I passed this to the team along with your notes about the agent.cmd → Windows PowerShell 5.1 -File$args chain and about setlocal enabledelayedexpansion.

About a workaround, honestly a local patch to agent.cmd will get overwritten on update, and installing pwsh won’t help here because the path is hardcoded to 5.1, which you already correctly pointed out. So until we have a fix, delegating calls that include " or ! to another CLI is a reasonable temporary workaround.

I can’t share a timeline or ETA yet, but I’ll post back in this thread when I have an update.