Repository navigation
[BUG] RTK Windows PowerShell Compatibility Gaps #1248
Description
[BUG] RTK Windows PowerShell Compatibility Gaps
Summary
RTK exposes several commands that appear generally available, but some of them are not compatible with a standard Windows PowerShell environment because RTK resolves real executables on PATH, not PowerShell aliases or shell built-ins. Windows setup behavior for rtk init -g is also surprising: in this environment it does not error, but it warns that hook-based mode requires Unix, falls back to --claude-md, and exits successfully. The user-reported rtk init -g --copilot repo-write behavior remains unverified in this pass.
Environment
- OS: Windows
- Shell: PowerShell
- Repository: TestBot3000
- RTK integration artifact present:
.github/hooks/rtk-rewrite.json - Copilot instructions file affected:
.github/copilot-instructions.md
Full List Of PowerShell Counterpart Gaps
Based on the full rtk --help command surface plus direct PowerShell resolution checks in this environment, the complete currently identified set of commands or operations that fail for Windows PowerShell command-resolution reasons, while a Windows-native counterpart exists, is:
| Operation | Failing RTK path | Why it fails in PowerShell | Working Windows/PowerShell counterpart |
|---|---|---|---|
ls |
rtk ls . |
ls is a PowerShell alias, not an executable on PATH |
Get-ChildItem, dir, or rtk tree . |
dir |
rtk proxy dir |
dir is also a PowerShell alias, not an executable on PATH |
Get-ChildItem |
echo |
rtk proxy echo hello |
echo is a PowerShell alias or shell built-in, not an executable on PATH |
Write-Output "hello" |
wc |
rtk wc package.json |
wc is not available as a standard Windows executable |
`Get-Content package.json |
Additional scope notes:
Get-Commandin this environment reportsls,dir, andechoas aliases, not executables.Get-Command wcfails because there is no standard Windowswcexecutable.rtk find -name package.jsonsucceeded in this environment, sofindis not on this unsupported-counterpart list.
Verified In This Environment
rtk ls . fails on PowerShell
Repro:
rtk ls .Observed behavior:
- RTK fails because it expects a real
lsexecutable onPATH - PowerShell's
lsalias toGet-ChildItemis not treated as an executable
Expected behavior:
- RTK should either support a Windows-safe fallback or emit a targeted message explaining that PowerShell aliases are not supported and suggesting an alternative such as
rtk tree .
rtk wc package.json fails on PowerShell
Repro:
rtk wc package.jsonObserved behavior:
- RTK fails because
wcis not a standard Windows executable onPATH
Expected behavior:
- RTK should either avoid advertising
wcas generally usable on Windows or emit a Windows-specific fallback/help message
rtk discover fails without Claude history
Repro:
rtk discoverObserved behavior:
- RTK fails because it expects Claude Code history under
~/.claude/projects
Expected behavior:
- RTK should fail gracefully with a message that this command requires local Claude history and is not universally available
rtk session fails for the same missing-history assumption
Repro:
rtk sessionObserved behavior:
- RTK fails because the same Claude history directory expectation is not met
Expected behavior:
- RTK should fail gracefully and document the prerequisite
rtk proxy only works with real executables
Repro:
rtk proxy dir
rtk proxy git status
rtk proxy echo helloObserved behavior:
rtk proxy dirfails becausediris a PowerShell alias, not an executablertk proxy git statusworksrtk proxy echo hellofails becauseechois a shell built-in, not an executable
Expected behavior:
- RTK should explicitly document that
proxyrequires real executables and does not resolve PowerShell aliases/built-ins
rtk curl https://example.com fails in this Windows environment
Repro:
rtk curl https://example.comObserved behavior:
- RTK fails here due to Windows TLS or revocation behavior in the local environment
- This appears environment-sensitive and is weaker evidence than the
lsandwcfailures
Expected behavior:
- RTK docs should call out that
curlbehavior on Windows may depend on local TLS and certificate policy
rtk init -g falls back and succeeds on Windows
Repro:
rtk init -gExact output from the plain command:
[warn] Hook-based mode requires Unix (macOS/Linux).
Windows: use --claude-md mode for full injection.
Falling back to --claude-md mode.
[ok] C:\Users\username\.claude\CLAUDE.md already contains up-to-date rtk instructions
Observed behavior:
- The command does not prompt for input
- The command does not error
- A follow-up exit-code capture returned
0 - RTK reports a Windows-specific fallback from hook-based mode to
--claude-md - No additional repo-local writes were observed in this run
.github/copilot-instructions.mdand.github/hooks/rtk-rewrite.jsonkept the same size andLastWriteTimebefore and after the run- The repository changed-file set did not gain any new repo-local entries after the run
Expected behavior:
- If this Windows fallback is intentional, RTK should document
rtk init -gas a successful--claude-mdfallback instead of implying hook installation works everywhere - If this fallback is not intended, RTK should make the scope change explicit before continuing
User-Reported But Not Re-Run In This Turn
rtk init -g --copilot installs locally and overwrites repo files
Observed by user:
rtk init -g --copilotsucceeds- It installs repo-local artifacts instead of behaving like a pure global install
- It overwrites
.github/copilot-instructions.md
Why this is surprising:
--globalimplies user-wide setup--copilotcurrently appears able to write repository-scoped integration files even when--globalis present
Expected behavior:
rtk init -gshould remain global-only- If
--copilotrequires repo-local writes, RTK should either reject the flag combination or state clearly that--copilotchanges scope to repository-local integration
Suspected Root Causes
- RTK resolves native executables on
PATHand does not understand PowerShell aliases or built-ins. - The concrete counterpart-gap cases identified here are
ls,dir,echo, andwc. - Some meta commands assume local Claude session history exists.
rtk initWindows semantics are underdocumented, especially the--globalfallback to--claude-mdand the unclear--globalplus--copilotinteraction.
Expected Behavior
- Commands presented as generally available should either work in standard PowerShell or clearly declare their Windows limitations.
- RTK should differentiate between executable resolution and PowerShell alias resolution in its error messages.
- Windows-incompatible commands should offer actionable fallback suggestions.
rtk init -gshould clearly document its Windows fallback behavior.--globalshould not silently lead to repo-local writes when combined with--copilot.
Actual Behavior
- PowerShell aliases like
lsare treated as missing commands. - PowerShell aliases like
dirandechoalso fail when routed throughrtk proxy. - Unix-only tools like
wcfail without a Windows-aware fallback. discoverandsessionfail when local Claude history is absent.- On Windows,
rtk init -gwarns, falls back to--claude-md, and exits0without changing repo-local files in this run. - The user-reported global Copilot install path is still confusing because
--copilotmay be able to write repo-local files.
Suggested Fixes
- Add Windows-aware fallback messages for commands like
lsandwc. - Document that PowerShell aliases and built-ins are not equivalent to executables for RTK command resolution.
- Clearly mark
discoverandsessionas conditional commands that require local Claude history. - Document that
rtk init -gfalls back to--claude-mdon Windows. - Clarify or change
rtk initsemantics so--globaland--copilotcannot produce surprising repo-local writes. - If mixed global/local behavior is intentional, print an explicit warning before modifying repository files.
Minimal Repro Set
rtk ls .
rtk wc package.json
rtk proxy dir
rtk proxy echo hello
rtk discover
rtk session
rtk curl https://example.com
rtk init -gRunning commands outputs the hook warning
PS C:\Source\TestBot3000> rtk git log -10
[rtk] /!\ No hook installed — run `rtk init -g` for automatic token savings
53577ba ver update (12 hours ago) <username>
c5295bb feat(renderer): add updates rail for desktop updates (#40) (12 hours ago) <username>
Move the shared desktop update surface into a dedicated
Updates rail panel and keep Debug focused on diagnostics.
Hide the titlebar update control unless an update can be
[+2 lines omitted]
5669b93 feat(installer): implement Velopack update URL persistence for packaged Windows installs (21 hours ago) <username>
d5bd609 fix(desktop): correct runtime wiring for installed builds (#39) (21 hours ago) <username>
Bridge explicit source, packaged, and installed runtime metadata\nfrom the Electron main process into the renderer so...
6a98b21 fix(desktop): expand update monitoring and release wiring (#32) (24 hours ago) <username>
74718cc chore(release): bump version to 0.1.1 (3 days ago) <username>
.........
Activity
pszymkowiak commentedon Apr 12, 2026
🔍 Automated Triage
bughighSummary
RTK fails on Windows PowerShell because it resolves real executables on PATH rather than PowerShell aliases/built-ins; affects ls, dir, echo, wc, proxy, discover, session, and init -g—fix requires Windows-aware resolution and better error messaging.
Triaged automatically by wshm · This is an automated analysis, not a human review.
Omzig commentedon Apr 17, 2026
FYI, not sure why i see [ok] in failures:
fix(hooks): windows use 'rtk hook claude' no fallback
zakblacki commentedon May 6, 2026
This is stil happening any workaround I noticed I had to first install ripgrep
winget install BurntSushi.ripgrep.MSVCIn some cases could be windefender blocking need to whitlist
fix(hooks): windows use 'rtk hook claude' no fallback
fix(hooks): windows use 'rtk hook claude' no fallback
tienthegainz commentedon Jun 23, 2026
I noticed the same thing when trying out rtk with my agent on Windows. One of the most used command was Get-ChildItem. I created a PR to bridge the gap for those common Powershell cmds to have them rewrite as rtk alias. Please help to take a look if you have a change @pszymkowiak
#2547
bharvey42 commentedon Jul 19, 2026
Summary
rtk has no
powershellsubcommand at all in its CLI surface, so any hook-rewritten invocation whose first token ispowershellfails to parse witherror: unrecognized subcommand 'powershell'and falls back to the raw, unfiltered command — 100% of the time, on every version tested (0.40.0 through the current 0.43.0). This is distinct from #1248/#1130, which cover alias-resolution issues insidertk proxy/rtk proxy powershell— here, rtk never gets that far; the top-level subcommand itself doesn't exist, so the hook's rewrite attempt (rtk powershell ...) errors immediately.Environment
Evidence (from local telemetry)
We run rtk's own
<data-dir>/history.dbthrough a downstream monitoring tool (HiveMind) that tails theparse_failurestable. Over ~7 weeks (2026-05-31 → 2026-07-19):powershell -Command .../powershell -NoProfile -Command .../powershell -File ...invocationserror: unrecognized subcommand 'powershell'with the clap usage bannerrtk ls-style listing calls in the same dataset save ~60% / ~700 tokens on average per call).Repro
Hook rewrites this to something like
rtk powershell -Command "...", which errors:Expected behavior
A
powershell(and ideallypwsh) subcommand/passthrough should exist so the hook rewrite has something to dispatch to — even a minimal implementation that strips boilerplate from-Command/-Fileoutput would close the largest single category of parse failures we see on Windows.Suggested fix
Add a
powershell/pwshsubcommand to the CLI (mirroring the existingAws/Kubectl/Docker-style compact-output wrappers), so the hook's auto-rewrite has a valid target instead of erroring out on every invocation.fix(windows): add PowerShell compatibility fallbacks for ls, wc, prox…
dd-haff commentedon Aug 12, 2026
https://github.com/microsoft/coreutils exists, I wonder if it would be a reasonable shortcut to instruct devs who use Windows/PowerShell to install coreutils for easier access to rtk's benefits ...
fix(windows): add PowerShell compatibility fallbacks for ls, wc, prox…
KuSh commentedon Oct 12, 2026
Evidence for the PowerShell routing in #3301, which the review there proposes to split out of that PR. Everything below was run against the PR head merged onto develop 311ebcb and, for the PowerShell side, against pwsh 7.4.2 (
mcr.microsoft.com/powershell).The rewrite engine receives PowerShell commands from Copilot CLI's
powershelltool (it maps it totool_name: "Bash"), so it cannot tell the two shells apart. That is the constraint a design has to start from.Rows a shell-aware version has to satisfy:
type gitanddirmust not be rewritten (type gitbecamertk read git: exit 0 with the path → exit 1);C:\...\pwsh.exeor/opt/.../pwshmust keep running that binary (the rewrite reduced it tortk pwsh, which resolves PATH);Select-String -Pattern 'one|bar'matches lines 2 and 3 in PowerShell; mapped to the grep engine it is a BRE and matches nothing;Select-String -Pattern "-v" ffindsa -v bin PowerShell; forwarded without a separator it became the-vflag;Select-Stringon one file printspath:line:textand exits 0 on no match;rtk grep -nprintsline:textand exits 1;Get-ChildItem -Depth Nlists N+1 levels below the path;tree -L Nshows N;ChildArgExt::child_args(powershell_cmd.rs:84uses.args);categorize_commandandRUST_HANDLED_COMMANDSentries, and a measuredsavings_pct(the new rules inherit 60 fromRtkRule::DEFAULTfor what is a passthrough).