Plugin bin/ PATH injection not extended to PowerShell tool subprocess (only Bash tool gets it)
Summary
v2.1.91 added plugin/bin/ to the Bash tool subprocess's PATH, letting plugins ship executables invokable as bare commands. The PowerShell tool subprocess (a separate spawn path) never received the same injection, so bare plugin commands fail when the PowerShell tool is the active shell.
How the injection currently works
When Claude Code spawns the persistent Git Bash subprocess it appends the plugin bin/ directory in POSIX colon-separated format:
PATH=...;C:\Program Files\Git\mingw64\bin:/c/Users/<user>/.claude/plugins/cache/<plugin>/<ver>/bin
The PowerShell subprocess is spawned separately with a clean Windows-style PATH. The plugin bin/ append never happens for it.
This is documented — the plugins-reference table says explicitly:
Executables |bin/| Executables added to the Bash tool'sPATH. Files here are invokable as bare commands in any Bash tool call while the plugin is enabled.
The PowerShell tool is not mentioned anywhere in this context.
Reproduction
- Install a plugin that ships an executable in
bin/(e.g.claude-dx-doneshipsbin/dx-done) - On Windows, either set
CLAUDE_CODE_USE_POWERSHELL_TOOL=1or remove Git Bash fromPATHso the PowerShell tool is the active shell - In a skill, run the bare command
dx-done --version - Expected: resolves from plugin
bin/, prints version - Actual:
dx-done: command not found(PowerShell has no knowledge of pluginbin/)
The same bare command works fine in a Bash tool call (Git Bash present) because the Bash subprocess gets the POSIX-format append.
Why .cmd/.ps1 launchers don't save you
Plugins can ship dx-done.cmd and dx-done.ps1 alongside dx-done in bin/, and Windows PATHEXT would resolve them as bare dx-done — if bin/ were on PowerShell's PATH. But since the injection never happens for the PowerShell subprocess, PATHEXT never gets a chance to fire.
Proposed fix
When spawning the PowerShell tool subprocess, also prepend <plugin>/bin to PATH using Windows-style semicolon-separated format:
// pseudocode — mirrors the existing Bash spawn injection
const pluginBin = path.join(pluginRoot, 'bin');
const env = {
...process.env,
PATH: pluginBin + ';' + process.env.PATH,
};
spawn('pwsh.exe', args, { env });
With this change, dx-done.cmd in bin/ resolves as bare dx-done via PATHEXT (.CMD is in PATHEXT by default on Windows), matching the Bash tool behavior.
Related
- #65883 — reveals the exact POSIX-format PATH append mechanism used for the Bash subprocess respawn
- #68396 — related:
uv_spawncan't execute.cmdwrappers (MCP/LSP spawn path, separate issue) - #62537 — PowerShell tool absent from schema when Git Bash present (detection issue, separate)
- Docs: plugins-reference § File locations — explicitly scopes
bin/to Bash tool only
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗