Skip to content

[BUG] RTK Windows PowerShell Compatibility Gaps #1248

Open

Description

@Omzig

[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-Command in this environment reports ls, dir, and echo as aliases, not executables.
  • Get-Command wc fails because there is no standard Windows wc executable.
  • rtk find -name package.json succeeded in this environment, so find is 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 ls executable on PATH
  • PowerShell's ls alias to Get-ChildItem is 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.json

Observed behavior:

  • RTK fails because wc is not a standard Windows executable on PATH

Expected behavior:

  • RTK should either avoid advertising wc as generally usable on Windows or emit a Windows-specific fallback/help message

rtk discover fails without Claude history

Repro:

rtk discover

Observed 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 session

Observed 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 hello

Observed behavior:

  • rtk proxy dir fails because dir is a PowerShell alias, not an executable
  • rtk proxy git status works
  • rtk proxy echo hello fails because echo is a shell built-in, not an executable

Expected behavior:

  • RTK should explicitly document that proxy requires 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.com

Observed 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 ls and wc failures

Expected behavior:

  • RTK docs should call out that curl behavior on Windows may depend on local TLS and certificate policy

rtk init -g falls back and succeeds on Windows

Repro:

rtk init -g

Exact 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.md and .github/hooks/rtk-rewrite.json kept the same size and LastWriteTime before 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 -g as a successful --claude-md fallback 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 --copilot succeeds
  • It installs repo-local artifacts instead of behaving like a pure global install
  • It overwrites .github/copilot-instructions.md

Why this is surprising:

  • --global implies user-wide setup
  • --copilot currently appears able to write repository-scoped integration files even when --global is present

Expected behavior:

  • rtk init -g should remain global-only
  • If --copilot requires repo-local writes, RTK should either reject the flag combination or state clearly that --copilot changes scope to repository-local integration

Suspected Root Causes

  1. RTK resolves native executables on PATH and does not understand PowerShell aliases or built-ins.
  2. The concrete counterpart-gap cases identified here are ls, dir, echo, and wc.
  3. Some meta commands assume local Claude session history exists.
  4. rtk init Windows semantics are underdocumented, especially the --global fallback to --claude-md and the unclear --global plus --copilot interaction.

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 -g should clearly document its Windows fallback behavior.
  • --global should not silently lead to repo-local writes when combined with --copilot.

Actual Behavior

  • PowerShell aliases like ls are treated as missing commands.
  • PowerShell aliases like dir and echo also fail when routed through rtk proxy.
  • Unix-only tools like wc fail without a Windows-aware fallback.
  • discover and session fail when local Claude history is absent.
  • On Windows, rtk init -g warns, falls back to --claude-md, and exits 0 without changing repo-local files in this run.
  • The user-reported global Copilot install path is still confusing because --copilot may be able to write repo-local files.

Suggested Fixes

  1. Add Windows-aware fallback messages for commands like ls and wc.
  2. Document that PowerShell aliases and built-ins are not equivalent to executables for RTK command resolution.
  3. Clearly mark discover and session as conditional commands that require local Claude history.
  4. Document that rtk init -g falls back to --claude-md on Windows.
  5. Clarify or change rtk init semantics so --global and --copilot cannot produce surprising repo-local writes.
  6. 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 -g

Running 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

  1. added
    bugSomething isn't working
    documentationImprovements or additions to documentation
    effort-largePlusieurs jours, nouveau module
    enhancementNew feature or request
    on Apr 12, 2026
  2. pszymkowiak commented on Apr 12, 2026

    @pszymkowiak
    Collaborator

    wshm · Automated triage by AI

    🔍 Automated Triage

    🐛 Category bug
    🟠 Priority high
    🎯 Confidence 86%

    Summary

    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.

  3. Omzig commented on Apr 17, 2026

    @Omzig
    Author

    FYI, not sure why i see [ok] in failures:

    Recent Failures (last 10)
    ────────────────────────────────────────────────────────────
      2026-04-13T01:29 [ok] node --test --import tsx test\rendere...
      2026-04-12T13:25 [FAIL] grep
      2026-04-12T13:20 [FAIL] dir
      2026-04-10T14:24 [FAIL] uninstall
      2026-04-10T14:21 [FAIL] dir
      2026-04-10T14:12 [ok] git --version
    
  4. zakblacki commented on May 6, 2026

    @zakblacki

    This is stil happening any workaround I noticed I had to first install ripgrep
    winget install BurntSushi.ripgrep.MSVC
    In some cases could be windefender blocking need to whitlist

  5. tienthegainz commented on Jun 23, 2026

    @tienthegainz

    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

  6. bharvey42 commented on Jul 19, 2026

    @bharvey42

    Summary

    rtk has no powershell subcommand at all in its CLI surface, so any hook-rewritten invocation whose first token is powershell fails to parse with error: 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 inside rtk 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

    • OS: Windows 11
    • Shell: PowerShell 5.1, invoked from Claude Code hook-based rewrite
    • rtk versions observed: 0.40.0, 0.42.3, 0.43.0 (current) — bug present in all three

    Evidence (from local telemetry)

    We run rtk's own <data-dir>/history.db through a downstream monitoring tool (HiveMind) that tails the parse_failures table. Over ~7 weeks (2026-05-31 → 2026-07-19):

    • 3,728 of 8,544 total parse failures (43.6%) are powershell -Command ... / powershell -NoProfile -Command ... / powershell -File ... invocations
    • Error is consistently: error: unrecognized subcommand 'powershell' with the clap usage banner
    • We upgraded rtk 0.42.3 → 0.43.0 on 2026-07-18. In the 36 hours since, powershell failures continued at the same rate (447 of 531 total post-upgrade failures = 84%) — completely unaffected by the upgrade, confirming this isn't a regression that got fixed elsewhere, it's a standing gap.
    • Fallback to raw execution succeeds ~99.7% of the time, so nothing breaks functionally — but every one of these calls gets zero token-savings filtering where a working PowerShell path would normally save meaningful tokens (comparable rtk ls-style listing calls in the same dataset save ~60% / ~700 tokens on average per call).

    Repro

    powershell -Command "Get-ChildItem -LiteralPath 'C:\some\path' -Filter '*.ext' | Select-Object Name,Length,LastWriteTime"

    Hook rewrites this to something like rtk powershell -Command "...", which errors:

    error: unrecognized subcommand 'powershell'
    
    Usage: rtk.exe [OPTIONS] <COMMAND>
    
    For more information, try '--help'.
    

    Expected behavior

    A powershell (and ideally pwsh) subcommand/passthrough should exist so the hook rewrite has something to dispatch to — even a minimal implementation that strips boilerplate from -Command/-File output would close the largest single category of parse failures we see on Windows.

    Suggested fix

    Add a powershell/pwsh subcommand to the CLI (mirroring the existing Aws/Kubectl/Docker-style compact-output wrappers), so the hook's auto-rewrite has a valid target instead of erroring out on every invocation.

  7. dd-haff commented on Aug 12, 2026

    @dd-haff

    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 ...

  8. KuSh commented on Oct 12, 2026

    @KuSh
    Collaborator

    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 powershell tool (it maps it to tool_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:

    • bash's type git and dir must not be rewritten (type git became rtk read git: exit 0 with the path → exit 1);
    • an explicit C:\...\pwsh.exe or /opt/.../pwsh must keep running that binary (the rewrite reduced it to rtk 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" f finds a -v b in PowerShell; forwarded without a separator it became the -v flag;
    • Select-String on one file prints path:line:text and exits 0 on no match; rtk grep -n prints line:text and exits 1;
    • Get-ChildItem -Depth N lists N+1 levels below the path; tree -L N shows N;
    • passthrough spawn of the real shell should use ChildArgExt::child_args (powershell_cmd.rs:84 uses .args);
    • a new top-level command also needs categorize_command and RUST_HANDLED_COMMANDS entries, and a measured savings_pct (the new rules inherit 60 from RtkRule::DEFAULT for what is a passthrough).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions