Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for PowerShell (pwsh) integration, including documentation updates, CLI help text modifications, and a new Pwsh shell implementation. The review feedback highlights several critical improvements for the PowerShell implementation: correcting environment variable syntax to support non-alphanumeric keys, fixing the escaping logic for single-quoted literals where backticks are not valid escape characters, ensuring the original shell prompt is restored upon deactivation, and using -LiteralPath for robust environment variable removal.
Greptile SummaryThis PR adds PowerShell ( Confidence Score: 5/5Safe to merge; all findings are P2 style suggestions that do not affect correctness for typical installation paths. The implementation is well-structured, tested on three platforms, and the previously flagged deactivate cleanup issue has been resolved. All remaining comments are minor style or defensive-coding suggestions with no present runtime defects. src/shell/pwsh.rs — minor issues with exe path quoting and Invoke-Expression error suppression worth reviewing before the next major release. Important Files Changed
Sequence DiagramsequenceDiagram
participant PS as PowerShell prompt
participant FnoxFn as fnox() wrapper
participant FnoxBin as fnox binary
participant Hook as _fnox_hook()
Note over PS: User sources activate script
PS->>FnoxBin: fnox activate pwsh
FnoxBin-->>PS: Sets $env:FNOX_SHELL, defines fnox(), _fnox_hook(), patches prompt
Note over PS: Each prompt render
PS->>Hook: global:prompt() calls _fnox_hook
Hook->>FnoxBin: hook-env -s pwsh
FnoxBin-->>Hook: PowerShell env-set code + optional __fnox_print_changes fn
Hook->>Hook: Invoke-Expression (sets env vars)
Hook->>Hook: __fnox_print_changes() calls Write-Host diff
Hook->>Hook: Remove-Item Function:\__fnox_print_changes
Note over PS: User runs: fnox deactivate
PS->>FnoxFn: fnox deactivate
FnoxFn->>FnoxBin: fnox deactivate (passthrough)
FnoxBin-->>FnoxFn: PowerShell cleanup code
FnoxFn->>FnoxFn: Invoke-Expression (restores prompt, removes functions/env vars)
Reviews (3): Last reviewed commit: "Fix formatting for bats test" | Re-trigger Greptile |
…er '-LiteralPath' for invoking 'Remove-Item', simplify escape function since it only escapes values, use instead of and
### 🚀 Features - Powershell integration by [@nbfritch](https://github.com/nbfritch) in [#421](#421) ### 🐛 Bug Fixes - **(Windows)** Nushell integration by [@john-trieu-nguyen](https://github.com/john-trieu-nguyen) in [#425](#425) - **(Windows)** Command resolution for executables by [@john-trieu-nguyen](https://github.com/john-trieu-nguyen) in [#427](#427) ### 📚 Documentation - add releases nav and aube lock by [@jdx](https://github.com/jdx) in [#422](#422) - include linux native packages in aube lock by [@jdx](https://github.com/jdx) in [#423](#423) ### 🔍 Other Changes - Use published `clap-sort` crate instead of inlined module by [@jdx](https://github.com/jdx) in [#409](#409) - add communique 1.0.1 by [@jdx](https://github.com/jdx) in [#424](#424) ### 📦️ Dependency Updates - lock file maintenance by [@renovate[bot]](https://github.com/renovate[bot]) in [#381](#381) - update taiki-e/upload-rust-binary-action digest to 10c1cf6 by [@renovate[bot]](https://github.com/renovate[bot]) in [#383](#383) - update rust crate tokio to v1.51.1 by [@renovate[bot]](https://github.com/renovate[bot]) in [#384](#384) - update rust crate indexmap to v2.14.0 by [@renovate[bot]](https://github.com/renovate[bot]) in [#385](#385) - update rust crate rmcp to v1.4.0 by [@renovate[bot]](https://github.com/renovate[bot]) in [#389](#389) - update rust crate strum to 0.28 by [@renovate[bot]](https://github.com/renovate[bot]) in [#395](#395) - update rust crate toml_edit to 0.25 by [@renovate[bot]](https://github.com/renovate[bot]) in [#396](#396) - update rust crate miniz_oxide to 0.9 by [@renovate[bot]](https://github.com/renovate[bot]) in [#390](#390) - update rust crate ratatui to 0.30 by [@renovate[bot]](https://github.com/renovate[bot]) in [#392](#392) - update actions/checkout action to v6 by [@renovate[bot]](https://github.com/renovate[bot]) in [#397](#397) - update actions/deploy-pages action to v5 by [@renovate[bot]](https://github.com/renovate[bot]) in [#399](#399) - update actions/configure-pages action to v6 by [@renovate[bot]](https://github.com/renovate[bot]) in [#398](#398) - update actions/setup-node action to v6 by [@renovate[bot]](https://github.com/renovate[bot]) in [#400](#400) - update actions/upload-pages-artifact action to v4 by [@renovate[bot]](https://github.com/renovate[bot]) in [#401](#401) - update dependency node to v24 by [@renovate[bot]](https://github.com/renovate[bot]) in [#403](#403) - update apple-actions/import-codesign-certs action to v6 by [@renovate[bot]](https://github.com/renovate[bot]) in [#402](#402) - update nick-fields/retry action to v4 by [@renovate[bot]](https://github.com/renovate[bot]) in [#406](#406) - update github artifact actions (major) by [@renovate[bot]](https://github.com/renovate[bot]) in [#404](#404) - update jdx/mise-action action to v4 by [@renovate[bot]](https://github.com/renovate[bot]) in [#405](#405) - update rust crate which to v8 by [@renovate[bot]](https://github.com/renovate[bot]) in [#408](#408) - update rust crate usage-lib to v3 by [@renovate[bot]](https://github.com/renovate[bot]) in [#407](#407) - bump rustcrypto stack (aes-gcm, sha2, hkdf) together by [@jdx](https://github.com/jdx) in [#410](#410) - update rust crate reqwest to 0.13 by [@renovate[bot]](https://github.com/renovate[bot]) in [#393](#393) - update rust crate libloading to 0.9 by [@renovate[bot]](https://github.com/renovate[bot]) in [#388](#388) - update rust crate keepass to 0.10 by [@renovate[bot]](https://github.com/renovate[bot]) in [#387](#387) - update rust crate rand to 0.10 by [@renovate[bot]](https://github.com/renovate[bot]) in [#391](#391) - lock file maintenance by [@renovate[bot]](https://github.com/renovate[bot]) in [#411](#411) - update rust crate google-cloud-secretmanager-v1 to v1.8.0 by [@renovate[bot]](https://github.com/renovate[bot]) in [#415](#415) - update actions/upload-pages-artifact action to v5 by [@renovate[bot]](https://github.com/renovate[bot]) in [#418](#418) - update rust crate rmcp to v1.5.0 by [@renovate[bot]](https://github.com/renovate[bot]) in [#416](#416) - update rust crate clap to v4.6.1 by [@renovate[bot]](https://github.com/renovate[bot]) in [#413](#413) - update rust crate tokio to v1.52.1 by [@renovate[bot]](https://github.com/renovate[bot]) in [#417](#417) - update rust crate keepass to v0.10.6 by [@renovate[bot]](https://github.com/renovate[bot]) in [#414](#414) - update taiki-e/upload-rust-binary-action digest to f0d45ae by [@renovate[bot]](https://github.com/renovate[bot]) in [#419](#419) - update rust crate aws-sdk-sts to v1.102.0 by [@renovate[bot]](https://github.com/renovate[bot]) in [#420](#420) ### New Contributors - @john-trieu-nguyen made their first contribution in [#427](#427) - @nbfritch made their first contribution in [#421](#421)
See earlier discussion: #412
This PR adds Powershell support for the
activate/deactivate/hook-envcommands, allowing support for auto loading like all the existing shells.Copilot was used to generate a starting point by referencing the
src/shell/bash.rsfile from fnox and thesrc/shell/pwsh.rsfile from mise. From there, I cleaned up the escaping and added support for displaying the env diff (fnox: +1 FOO/fnox: -1 FOO).There are 2 possible names for the powershell binary,
powershellandpwsh. I elected to usepwshin the help, in order to avoid lines wrapping around on smaller terminal windows.For bash/zsh/fish the flow is: eval the output of the activate command, which sets up a hook, which evaluates the output of the hook-env command, which generates code to both set the env variables and also print the env diff. I wanted the powershell to stick to this general flow. However, due to the way powershell evaluates code from the output of a command (
(& cmd) | Out-String | Invoke-Expression) the printed diff gets lost because printing in evaluated commands doesn't bubble up to the parent shell. To solve thishook-envcreates a function__fnox_print_changesthat contains theWrite-Hoststatements. The powershell code generated by theactivate/deactivatecommand then checks for the existence of that function, evaluates it if it exists, then deletes it.I tested the powershell integration on the following platforms:
Since powershell is different enough from the usual shells (bash,fish,zsh) I left it off the quick start page and lumped it in with nushell in pointing towards the Shell Integration page.
Thank you for your work on this great project!