Skip to content

fix(core): quote child arguments so MSYS children receive them intact - #3728

Open
esidorenko-sl wants to merge 1 commit into
rtk-ai:developfrom
esidorenko-sl:fix/windows-msys-child-arg-quoting
Open

fix(core): quote child arguments so MSYS children receive them intact#3728
esidorenko-sl wants to merge 1 commit into
rtk-ai:developfrom
esidorenko-sl:fix/windows-msys-child-arg-quoting

Conversation

@esidorenko-sl

@esidorenko-sl esidorenko-sl commented Aug 27, 2026

Copy link
Copy Markdown

Summary

On Windows std::process::Command wraps an argument in quotes only when it holds a space or a tab, so a"b reaches the raw command line bare, as a\"b. MSVCRT/UCRT children parse that back correctly; Cygwin/MSYS children read the \" as a backslash and glue the surrounding arguments together. Since which resolves grep, find, ls, wc and the rest of usr/bin to the MSYS binaries Git for Windows ships, rtk grep -c '"type"' file reported 0 matches and exit 1 while the native rtk rg was unaffected (#3727).

quote_arg_for_child in src/core/utils.rs emits the encoding libuv's quote_cmd_arg uses — the form both parsers agree on — and a ChildArgExt trait (child_arg/child_args) puts it in front of the child's command line. std already produces those same bytes for every other argument, so only an argument that actually contains a " leaves the Command::arg path; everything else is encoded exactly as before. .bat/.cmd programs stay on std's path unconditionally, since cmd.exe parses by its own rules and raw_arg would bypass the escaping std applies for them.

Converted call sites: rtk grep/rtk rg (structural, passthrough and --version/--help), rtk find, rtk ls, rtk wc, rtk proxy, runner::run_passthrough and the unknown-command fallback in main.rs. That is every place where an argument from rtk's own command line reaches a child resolved through PATH, so sed, awk, sort, tr and friends are covered too when they arrive through the fallback.

Out of scope

rtk err, rtk run and rtk summary hand a whole string to cmd /C instead of an argument vector, which is a separate problem (#2985, #2389, #3704). MSYS2's own POSIX-path conversion of arguments (MSYS2_ARG_CONV_EXCL) sits above the command line and is left alone.

Test plan

  • cargo fmt --all -- --check (0), cargo clippy --all-targets -- -D warnings (0), cargo test — 2647 unit tests and every integration binary pass.
  • 9 new unit tests in src/core/utils.rs for the libuv rules and the .bat guard; the encoder itself compiles and is tested on every platform.
  • New tests/windows_child_quoting_test.rs (#![cfg(windows)], silently skipped when no MSYS grep.exe is around) drives rtk grep -c '"type"' q.jsonl at the Git-for-Windows grep. With the fix disabled it fails with rtk grep exited Some(1), expected 0; with it, green.
  • By hand against the MSYS binaries: rtk grep -c '"type"' q.jsonl1 (was 0, exit 1), and rtk printf '<%s> ' 'a"b' 'c d' '"type"'<a"b> <c d> <"type">. rtk find, rtk ls and rtk wc unchanged on ordinary arguments.

Built and tested on both stable-x86_64-pc-windows-gnu and stable-x86_64-pc-windows-msvc. On both, core::stream::tests::test_read_lines_lossy_preserves_lines_after_invalid_utf8 and hooks::hook_cmd::tests::test_claude_pipeline_rewrites_only_safe_final_stage fail on unmodified develop (322db4d) here as well, so those two are pre-existing.

Fixes #3727

@CLAassistant

CLAassistant commented Aug 27, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@esidorenko-sl
esidorenko-sl force-pushed the fix/windows-msys-child-arg-quoting branch from 629f8be to d176798 Compare August 27, 2026 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: arguments containing a double quote are corrupted when rtk spawns MSYS/Cygwin children (rtk grep, rtk proxy)

2 participants