Skip to content

Fix quoting of shell commands on Windows#5704

Open
stefanhaller wants to merge 4 commits into
masterfrom
fix-windows-cmd-quoting
Open

Fix quoting of shell commands on Windows#5704
stefanhaller wants to merge 4 commits into
masterfrom
fix-windows-cmd-quoting

Conversation

@stefanhaller

Copy link
Copy Markdown
Collaborator

Lazygit builds a shell command by interpolating Quote'd arguments into a template and running the result via cmd /c. Several things were wrong on Windows:

  • Quote emitted bash-style \"…\" quoting, which cmd.exe doesn't understand. Making it usable at all previously required a fragile round-trip through str.ToArgv and re-escaping.
  • The assembled command line was handed to cmd /c without /s, so cmd's default rules stripped the wrong quotes once the line contained more than two of them (e.g. a quoted editor path at a location with spaces, plus a quoted filename that also contains spaces).
  • Shell metacharacters were escaped with ^ (&^&, etc.), which neutralised command chaining, pipes, redirection and %VAR% expansion in custom commands.

Quote now emits the standard Windows convention directly, and NewShell hands cmd.exe the fully-assembled line verbatim via SysProcAttr.CmdLine, wrapped as cmd /s /c "<command>". The /s flag strips exactly the outer quote pair we add, leaving each argument's own quoting intact. With the ^ escaping gone, metacharacters in a custom command reach cmd as the author intended; this also removes the spurious ^ reported in #3092.

Fixes #5560
Fixes #2427
Fixes #4147

stefanhaller and others added 4 commits June 16, 2026 16:29
On Windows, Quote wraps arguments in bash-style `\"…\"` and rewrites
embedded double quotes as `"'"'"`. Neither convention is understood by
cmd.exe or CommandLineToArgvW, so commands built from quoted arguments
are mis-parsed once they contain quotes or spaces (#5560).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On Windows, NewShell escapes shell metacharacters (`&`, `|`, `<`, `>`,
`%`) with `^` and splits the command into separate arguments. The
operators in a custom command therefore never reach cmd as operators,
so command chaining (`&&`), pipes, redirection and `%VAR%` expansion all
silently break (#2427, #4147, #5113; the stray `^` is also what #3092
reports).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lazygit builds a shell command by interpolating Quote'd arguments into a
template and running the result via `cmd /c`. Several things were wrong
on Windows:

- Quote emitted bash-style `\"…\"` quoting, which cmd.exe doesn't
  understand. Making it usable at all previously required a fragile
  round-trip through str.ToArgv and re-escaping.
- The assembled command line was handed to `cmd /c` without `/s`, so
  cmd's default rules stripped the wrong quotes once the line contained
  more than two of them (e.g. a quoted editor path at a location with
  spaces, plus a quoted filename that also contains spaces).
- Shell metacharacters were escaped with `^` (`&` → `^&`, etc.), which
  neutralised command chaining, pipes, redirection and `%VAR%` expansion
  in custom commands.

Quote now emits the standard Windows convention directly, and NewShell
hands cmd.exe the fully-assembled line verbatim via SysProcAttr.CmdLine,
wrapped as `cmd /s /c "<command>"`. The /s flag strips exactly the outer
quote pair we add, leaving each argument's own quoting intact. With the
`^` escaping gone, metacharacters in a custom command reach cmd as the
author intended; this also removes the spurious `^` reported in #3092.

Fixes #5560
Fixes #2427
Fixes #4147

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The unit tests only assert the arguments lazygit constructs; they can't
catch cmd.exe's own quote-stripping, which is where #5560 actually
manifested. This test builds a small editor executable, places it and
the file it opens at paths containing spaces, runs it through real
cmd.exe via NewShell, and checks the editor received the intended args.
It runs only on Windows.

Co-Authored-By: Antoine Gaudreau Simard <a.simard@multidev.net>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@stefanhaller stefanhaller force-pushed the fix-windows-cmd-quoting branch from 1b32aba to 93d2c0b Compare June 16, 2026 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

os.editAtLineAndWait doesn't handle quotes correctly chaining custom command issue on Windows Custom command containing & does not work on windows

1 participant