Repository navigation
Conversation
…ng on PATH Plain Windows PowerShell (no Git Bash/WSL, no ripgrep installed) has neither grep nor rg on PATH, so `rtk grep`/`rtk rg` hard-failed instead of running. engine_capture now checks tool_exists(engine.bin()) and, only when the requested binary is absent, walks paths with the already-vendored `ignore` crate and matches lines with the already-vendored `regex` crate. This never substitutes one engine for the other — grep still only falls back when grep itself is missing, same for rg. Output is emitted in the exact file\0line:content shape parse_match_line already expects, so grouping/ truncation/display code is untouched. Context lines (-A/-B/-C) are not supported in fallback mode; only -i/--ignore-case is honored from extra_args. Forward-ports unreleased fork-local work (originally against the pre-refactor grep_cmd.rs) onto develop's search.rs/Engine design. Not tied to a GitHub issue; staged for maintainer discussion before submission.
…shell-native-compat Port the native fallbacks onto develop: compact_ls now returns (entries, parsed, truncated, filtered) and plan() no longer exposes the positional paths, so run_native takes them from child_args and appends the standard hidden-entries hint.
… nested ifs
The develop guard no_tracked_label_is_a_space_join rejects labels built
with join(" "), and clippy on edition 2024 asks for let-chains.
On stock Windows the native listing stands in for Get-ChildItem (ls and dir are its aliases), which hides Hidden/System entries and lists dotfiles. Hiding by a leading dot dropped .gitignore and showed files marked hidden. Also print no "(empty)" placeholder after the errors when every target fails.
…Select-String -TotalCount (and its -Head/-First aliases) is an exact head window, but --max-lines is a smart truncation: Get-Content -TotalCount 2 printed one line and a "[3 more lines]" marker. Map it to --head-lines. Select-String always prints path:line:text; pass -n so the line number survives, including for a single file.
gci -Recurse rewrites to rtk tree, so the native tree must hide by the Windows Hidden/System attributes too, not by a leading dot.
Parsing the full clap command graph in an unoptimized Windows build needs more than the 2 MiB a spawned test thread gets by default: develop sits just under it, and adding the powershell/pwsh subcommands pushed the Cli parse tests over, aborting the whole unit-test binary with STATUS_STACK_OVERFLOW. Measured on Windows MSVC: test_bun_build overflows at 2 MiB and passes at 4 MiB. Match the /STACK size build.rs sets for the main thread.
…-spawning rtk rtk powershell -Command <cmdlet> re-executed current_exe() with the rewritten argv, which semgrep's dynamic-command-execution rule blocks and which paid a second process start. Split the command dispatch out of run_cli and run the rewritten argv through it directly; anything that does not rewrite still goes to the real shell unchanged.
KuSh
left a comment
There was a problem hiding this comment.
Round 1 — CHANGES REQUESTED
Claim: rtk ls|tree|wc|grep|rg keep working on a host without the Unix tools through native Rust fallbacks, rtk powershell|pwsh plus bare-cmdlet rewrites route PowerShell file cmdlets through rtk, and the Windows build links with non-MSVC linkers.
Scope: accept if narrowed to "native ls/tree/wc/grep/rg fallbacks that fail loudly on anything they do not implement". Two parts leave the PR. The build.rs linker hunk is the one #3613 already carries (it also keys off the target, and #3613 is the open survivor of #3239), so it lands there. The PowerShell wrappers, cmdlet rewrites and their rules become a follow-up (#1248): they need a shell-aware rewrite, not a mapping table, and the evidence below is for that follow-up. Related open work: #2875 (its commits are carried here; it closes once this lands), #2355 and #2728 (same area); #4401 (flag grammars as data, which is what the fallbacks need to reject what they do not implement) and #4103 (child argument encoding) should land first.
Ran: merge of 3e97f69 onto develop 311ebcb (d5e72aa7c), debug binaries built from separate target dirs (md5 differ). Real tools: GNU ls/wc/tree/grep, ripgrep, PowerShell 7.4.2 (mcr.microsoft.com/powershell). Native paths run with an empty PATH and diffed against the real-tool path: ls 27 shapes, wc 25, tree 26, grep/rg 37 plus 11 confirmation rows; rewrite corpus of 40 commands on both binaries and through rtk hook claude; 14 cmdlet rows against real pwsh. Invariants: non-default targets (symlink, dangling link, dir with space, missing path), over-cap listing with the recall hint, stdin pipe for wc, under the hook, every decision of the new rewrite arm. Savings: ls 5987→775 B, tree 240→85 B against the 20% floor. Merged gate: fmt, clippy, cargo test --all (4091 unit tests) all exit 0; wincheck (windows-gnu) clean; CI 11/11 green on the PR head.
Pins: 143 mutations, 44 killed, 98 survived (11 of them equivalent or unreachable; 87 observable from the CLI).
Matrix: executed this round; pin check: executed this round
CI @3e97f6927: all green
Blocks merge (3, frozen)
src/cmds/system/{ls,wc_cmd,tree,search}.rs— native fallback answers wheredevelopfailed loudly (4 sites; all must change). Each fallback drops what it does not implement and prints a plausible result with exit 0 (or 1):ls(ls.rs:309): entries ordered by the synthesized line, so by size text (a_one 1B,c_hundred,b_twenty,d_three); with the display cap the 0 B files show andCargo.toml,README.md,big.txtfall behind it.-d,-t,-S,-r,--ignore=are ignored;-I zdirtreatszdiras a path (exit 2);ls -- -dash.txtlists the cwd (exit 0).wc(wc_cmd.rs:163):wc -L fprints2L 3W 19B(real:11),--bytesprints all three counts,--max-line-lengthis wrong,--total=ignored,wc -l -- -dash.txtreads stdin and prints0.tree(tree.rs:71):tree src docsprints onlysrc;-I deepis consumed and not applied;-P '*.txt' srcmakes*.txtthe root;tree nosuchexits 0 (real: exit 2,[error opening dir]);--level=1and-L 0are accepted.- search (
search.rs:429,:603):-w,-F,-S,-A/-B/-Cignored (grep -w TODmatchesTODO;grep -F .matches every line); BREa\|breaches Rust regex and matches nothing; non-UTF-8 and UTF-16 files are skipped silently; a missing path exits 1 with no message, or 0 beside a good path;.gitignoreand hidden files are honoured under the grep engine, sogrep -rn ignored .finds nothing where grep finds two lines. - dispatch (
tree.rs:21):cfg!(windows) || !tool_exists("tree")sends every Windows user to the reduced walker, including those with a realtreeon PATH (Git for Windows, scoop), who lose-P,-I,-sand the rest. On Linux and macOS the real binary is used whenever present. The native path should engage only when thetreeon PATH is not the Unix one (or none exists), not on the platform alone.
Evidence: transcripts for each row, native vs real tool. Test: a differential test per fallback over the forms it claims, and for every flag or operand it does not implement an assertion that stdout stays empty and exit is non-zero with a message. The corpus must show 0 differing rows on the supported forms.
src/discover/registry.rs:1707,powershell_cmd.rs:115— PowerShell routing in the shared rewrite engine (cut by the narrowing; otherwise all must change). Regressions againstdevelop:type git→rtk read git(alsoecho hi && type git,FOO=1 type git), throughrtk rewriteandrtk hook claude: bash'stypeexits 0 with the path, the rewritten form exits 1, or prints a file that happens to be namedgit.dir/dir src→rtk lslikewise. Copilot CLI hands itspowershelltool to the same engine asBash, so the engine cannot tell the shells apart./x/explicit/pwsh -File b.ps1→rtk pwsh -File b.ps1runs thepwshfound on PATH, not the binary named.
Cmdlet mapping unfaithful against pwsh 7.4.2:Select-String -Pattern 'one|bar'matches lines 2 and 3, the rewrite isrtk grep -n -i 'one|bar'(BRE): exit 1, no output;-Pattern "-v"becomes the flag-v: exit 1, no output where PowerShell printsa -v b; single file prints1:textwithout the path; no-match exits 1 where PowerShell exits 0;Get-ChildItem -Depth N→tree -L Nis one level short (-Depth 1 .listssrc/main.rs,tree -L 1does not; the test pins the wrong mapping).
- Unpinned behaviour (both areas). Native fallbacks: 45 of 66 mutations survive, including the four dispatch conditions (
!tool_exists("ls"|"wc"|"tree"|engine.bin())inverted: all tests pass), every exit-code mapping (ls.rs:4102→1,:4202→0,wc_cmd.rs:1951→0), the walker options (git_ignore/git_global/git_excludeoff), the default path,tree's multi-root and--all,wc's total line. PowerShell: 53 of 77 survive, includingrun_powershellnever rewriting (main.rs:2166), the verbose andis_operational_commandarms, the exit-code propagation ofrun()(→ 0), the redirect suffix, theNormal-context guard, the case-insensitivity and.exeof both rules, and thegc/type/dir/ls/gcialiases. The test the fix needs: for each, the input and the output that decides it (report: pin-A and pin-B tables); each mutation must turn it red. Held until the blockers above are settled, because the fix to 1 and 2 changes what the tests must assert.
Optional — will not hold merge; threads resolved by me
src/cmds/system/README.mdnamesnative_grep(the code hasfallback_capture), says-TotalCount→--max-lines(code:--head-lines) and omits the always-added-n.search.rs:421cites#Windows-no-binary, which is not an issue.- The fallback covers the grouped search form only:
-l,-c,-o,--files,--helpand the piped-stdin branch still fail withFailed to execute, which is loud and safe, but the PR text reads wider. - Native
ls -lprints 644/755 on Unix too, wherePermissionsExthas the real mode.
Filed as follow-ups
- Shell-aware PowerShell routing (wrappers, cmdlet rewrites, rules with measured
savings_pctinstead of the inherited 60,categorize_commandandRUST_HANDLED_COMMANDSentries, andChildArgExt::child_argsinstead of.args(args)atpowershell_cmd.rs:84for the passthrough spawn): comment on #1248 with the rows above — outside the narrowed claim. Not filed yet.
Checked and correct — no need to re-verify
- Merge with
developis clean; fmt, clippy, tests and wincheck pass on the merge. tree src,-a,-L 2andtree sizesequal the real tool after glyph normalisation;grep/rg-v,-i,-e,--max-countequal;wcdefault,-l -w -c -m -lw, several files and piped stdin equal;lsof a file, an empty dir and a dotfile equal.Get-Content -TotalCount N/-Tail N,Select-String -NotMatchequal pwsh on the same files; unsupported cmdlet options, pipes,$and;all pass through unchanged.- The recall hint works on the native
lslisting. build.rstarget-env check type-checks for windows-gnu (wincheck); the hunk itself is #3613's.
Your questions
None.
Next
Narrow to the native fallbacks and the linker plumbing; make each fallback refuse what it does not implement (exit 2, message, empty stdout) and error on a missing target; move the PowerShell part to its own PR after #4401. Pin each fallback decision with a test that fails when mutated.
Threads: 0 open, 0 resolved this round.
Summary
developbranchls,tree,wc, and file-basedgrep/rgwhen Unix binaries are unavailablepowershellandpwshwrappers plus safe, case-insensitive routing forGet-Content,Get-ChildItem, andSelect-String(including aliases)-File, and-EncodedCommandby passing them through unchanged/STACKflag-v/--invert-matchin the native search fallback soSelect-String -NotMatchremains correctContext and attribution
This branch deliberately preserves the original commits/authorship from @tienthegainz's #2547 and @sresam89's #2875, then adds the PowerShell/pwsh routing and current-
developintegration work on top.Addresses #1248.
Supersedes #2547.
Includes the fallback work from #2875.
Safety model
Only simple, statically tokenizable cmdlet invocations are routed through RTK. Compound PowerShell syntax and dynamic forms are left to the requested PowerShell executable, avoiding semantic changes to pipelines or scripts.
Validation
cargo fmt --all --checkcargo clippy --all-targets -- -D warningspowershell, nativels,tree,wc, and search fallback)powershell -Command, native listing/count/tree, and search withrgremoved fromPATHGitHub's existing Windows MSVC job provides the authoritative full-suite check for this draft.
AI disclosure
The integration, tests, and PowerShell routing were developed with Codex assistance and manually validated on Windows.