@4fu/pi-pwsh
v0.5.2
Published
Route pi's shell, directory listing, and search tasks through PowerShell 7 on Windows
Downloads
948
Maintainers
Readme
pi-pwsh
Route pi's shell, directory listing, and search tasks through PowerShell 7 (pwsh) on Windows.
Why
- Windows has no reliable bash implementation (Git Bash hangs on background processes, path translation is flaky).
- A tool named
bashprimes the model to emit POSIX syntax (&&,grep,$VAR), which fails under PowerShell.
This extension disables bash, ls, find, and grep, then registers a pwsh tool instead.
What it does
- Registers a
pwshtool that reuses pi's built-in bash tool definition — tail truncation (last 2000 lines / 50KB), full output saved to a temp file, non-zero exit codes surfaced as tool errors, streaming preview, and the built-in renderer all come for free. Only the spawn layer is replaced. - Disables pi's built-in
ls,find, andgreptools so filesystem discovery and search are routed throughpwsh; prompt guidance prefers available cross-platform tools such asrgandfdand bounds native recursive cmdlets. - Spawns
pwsh -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command <cmd>. - Forces plain UTF-8 output without a BOM (non-ASCII output is not mangled, PowerShell formatting does not leak ANSI escapes, and piped native-command input is not prefixed with
EF BB BF). - Defaults Python subprocesses to
PYTHONIOENCODING=utf-8,PYTHONUTF8=1, andPYTHONUNBUFFERED=1so stdio and implicit text-file reads use UTF-8 and long-running logs stream promptly. Existing environment values are respected, and the defaults are scoped to processes launched by the tool. - Preserves real native exit codes:
pwsh -Commandwould otherwise flatten them to 0/1, which breaksrg(1 = no match vs 2 = error) andgit diff --quiet-style semantics. An exit-code epilogue restores them — identically for foreground commands and background jobs. - Auto-retries with
cmd /cwhen a command fails with "not a valid Win32 application" (npm/yarn/pnpm are.cmdbatch files on Windows). Skipped for commands rewritten to background jobs, where cmd's&semantics would be wrong. - Kills the whole process tree (
taskkill /T /F) on timeout or abort — no orphanednpm run devprocesses. - No default timeout; the model can pass
timeout(seconds) per call. - Probes Windows Sudo once per session; when available in inline mode, the tool description tells the model it can prefix a command with
sudoto run it as administrator (each call still requires the user to approve the UAC prompt).
Background jobs
Every pwsh tool call spawns a fresh pwsh process, so native PowerShell jobs (Start-Job, the & background operator) die when the tool call ends. This extension fixes that from inside the shell — no extra tools:
- Every call dot-sources
src/prelude.ps1, which overrides the job cmdlets (Start-Job,Get-Job,Receive-Job,Stop-Job,Remove-Job,Wait-Job) with implementations backed by real detached OS processes. Pipeline forms work:Get-Job | Stop-Job,Start-Job { npm run build } -Name build | Wait-Job | Receive-Job. - Jobs are launched detached via double-spawn: a short-lived launcher process starts the job and exits immediately, breaking the parent chain that
taskkill /Twalks — aborting or timing out the tool call that started a job does not kill it. Jobs inherit the calling session's full environment (PATH, proxies,VIRTUAL_ENV, ...) through the launcher;Start-Job -Environment @{ NAME = 'value' }overrides or adds variables (stored in the job's wrap script under%TEMP%\pi-pwsh-jobsuntilRemove-Job). - A trailing
&(npm run dev &) is rewritten toStart-Jobbefore execution, using PowerShell's own parser (src/background.ts) — strings, comments, the& { }call operator and&&are never mistaken for it. Only single-pipeline commands are rewritten; anything else runs as-is. - Job state lives in
%TEMP%\pi-pwsh-jobs\(one.meta.json+ log/exit/script files per job), so it survives/reloadand pi restarts and is inspectable by hand. Receive-Jobconsumes output like the native cmdlet (each read returns what arrived since the last one;-Keepre-reads,-Tail Npeeks). Exit codes are captured (Get-JobshowsCompleted/Failed+ExitCode);Stop-Jobkills the whole process tree (taskkill /T /F).Suspend-Job/Resume-Job/Debug-Jobthrow actionable guidance.Get-JobHelpprints the full reference in the shell.
Requirements
- PowerShell 7+ (
pwshonPATH). There is no fallback: ifpwshis not found, the extension shows an error notification and leaves the built-inbashtool active.
Installation
With pi:
pi install npm:@4fu/pi-pwshOr try it for a single run without installing:
pi -e npm:@4fu/pi-pwshFrom source
Symlink or copy into pi's extensions directory:
New-Item -ItemType Junction -Path "$HOME\.pi\agent\extensions\pi-pwsh" -Target "<this-repo>"Or add the path to ~/.pi/agent/settings.json:
{
"extensions": ["C:/path/to/pi-pwsh"]
}Run npm install once in this directory, then /reload in pi.
Development
npm install
npm run typecheckTests:
# Runtime defaults (UTF-8 without BOM, plain errors, Python environment)
node scripts/smoke-runtime.mjs
# Job prelude end-to-end (each case is a fresh pwsh process, like a real tool call)
pwsh -NoProfile -ExecutionPolicy Bypass -File scripts/smoke-jobs.ps1
# Trailing-& interception (PowerShell parser based)
node scripts/smoke-background.mjs
# Foreground exit-code fidelity (native codes survive the pwsh -Command flattening)
node scripts/smoke-exitcode.mjsLicense
MIT
