Install and manage side-by-side PowerShell versions with aliases and native hosting.
Latest release bootstrap scripts:
curl -fsSL https://raw.githubusercontent.com/Devolutions/multi-pwsh/refs/heads/master/tools/install-multi-pwsh.sh | bashirm https://raw.githubusercontent.com/Devolutions/multi-pwsh/refs/heads/master/tools/install-multi-pwsh.ps1 | iexInstall a specific tag (example v0.6.0):
curl -fsSL https://raw.githubusercontent.com/Devolutions/multi-pwsh/refs/heads/master/tools/install-multi-pwsh.sh | bash -s -- v0.6.0& ([scriptblock]::Create((irm https://raw.githubusercontent.com/Devolutions/multi-pwsh/refs/heads/master/tools/install-multi-pwsh.ps1))) -Version v0.6.0Uninstall bootstrap scripts:
curl -fsSL https://raw.githubusercontent.com/Devolutions/multi-pwsh/refs/heads/master/tools/uninstall-multi-pwsh.sh | bashirm https://raw.githubusercontent.com/Devolutions/multi-pwsh/refs/heads/master/tools/uninstall-multi-pwsh.ps1 | iexmulti-pwsh install 7.4
multi-pwsh install 7.5Verify aliases:
pwsh-7 --version
pwsh-7.4 --version
pwsh-7.5 --versionmulti-pwsh install 7.4.x
multi-pwsh update 7.4
multi-pwsh update 7.5
multi-pwsh list
multi-pwsh list --available
multi-pwsh list --available --include-prerelease
multi-pwsh install 7.6 --include-prerelease
multi-pwsh install 7.6-preview6
multi-pwsh install 7.6-rc1
multi-pwsh install 7.6.0-rc.1
multi-pwsh update 7.6 --include-prerelease
multi-pwsh alias set 7.4 7.4.11
multi-pwsh alias unset 7.4
multi-pwsh venv create msgraph
multi-pwsh venv export msgraph msgraph.zip
multi-pwsh venv import msgraph-copy msgraph.zip
multi-pwsh venv delete msgraph
multi-pwsh venv list
multi-pwsh host 7.4 -venv msgraph -NoLogo -NoProfile -Command "$env:PSModulePath"
multi-pwsh doctor --repair-aliasesmulti-pwsh usage reference:
multi-pwsh install <version|major|major.minor|major.minor.x> [--arch <auto|x64|x86|arm64|arm32>] [--include-prerelease]
multi-pwsh update <major.minor> [--arch <auto|x64|x86|arm64|arm32>] [--include-prerelease]
multi-pwsh uninstall <version> [--force]
multi-pwsh list [--available] [--include-prerelease]
multi-pwsh venv create <name>
multi-pwsh venv delete <name>
multi-pwsh venv export <name> <archive.zip>
multi-pwsh venv import <name> <archive.zip>
multi-pwsh venv list
multi-pwsh alias set <major.minor> <version|latest>
multi-pwsh alias unset <major.minor>
multi-pwsh host <version|major|major.minor|pwsh-alias> [-VirtualEnvironment <name>|-venv <name>] [pwsh arguments...]
multi-pwsh doctor --repair-aliases
Use the local Pester harness to validate venv-sensitive cmdlet behavior across installed version aliases (pwsh-x.y.z).
Run all installed version aliases:
pwsh -NoLogo -NoProfile -NonInteractive -File .\tests\Invoke-VenvTestMatrix.ps1Run one alias only:
pwsh -NoLogo -NoProfile -NonInteractive -File .\tests\Invoke-VenvTestMatrix.ps1 -Aliases pwsh-7.4.13Include online install tests (Install-PSResource / Install-Module):
pwsh -NoLogo -NoProfile -NonInteractive -File .\tests\Invoke-VenvTestMatrix.ps1 -EnableOnlineTestsOnline mode details:
- The tests do not modify PSGallery trust policy.
Install-PSResourceuses-TrustRepository -QuietandInstall-Moduleuses-Force -AcceptLicense -Confirm:$falseto run non-interactively.- The install checks use
Yayamlto keep downloads and execution lightweight.
Notes:
- The runner creates a temporary venv per alias and deletes it by default.
- Use
-KeepVenvto keep those venvs for troubleshooting. - The runner stops on the first failed alias by default.
- Use
-ContinueOnFailureto keep running remaining aliases after a failure. - Pester must be available in the host PowerShell session.
Selector behavior:
7installs the latest available 7.x release for your platform.7.4installs the latest available 7.4.x release for your platform.7.4.xinstalls all available releases in that line for your platform.7.4.11installs that exact version.
multi-pwsh install 7.4.x installs every available patch release in that line for your current platform and creates per-version aliases such as pwsh-7.4.11.
The pwsh-7.4 alias tracks latest by default; pin it with multi-pwsh alias set 7.4 7.4.11 and unpin with multi-pwsh alias unset 7.4.
If a pinned target version is not installed, the pin remains in metadata and the alias stays unresolved until you install that version or unpin.
Native host mode:
multi-pwsh host <selector> ...runs PowerShell through native hosting (pwsh-hostcrate) instead of launching apwshsubprocess.<selector>supports7,7.4,7.4.13, or alias-form selectors such aspwsh-7.4.-VirtualEnvironment <name>and-venv <name>are consumed bymulti-pwshbefore handing control to PowerShell and setPSModulePathto the selected venv root for that launch.PSMODULE_VENV_PATHcan also be used as an explicit path-based venv selector for hosted launches. If it is already set in the environment,multi-pwsh hosttreats it as an intentional venv opt-in.- Alias lifecycle now maintains native host shims as hard links to
multi-pwshautomatically during install/update/doctor alias repair. - On Windows, host shims are
pwsh-*.exefiles alongside.cmdwrappers inMULTI_PWSH_BIN_DIR(default:~/.pwsh/bin). - On Linux/macOS, alias command paths (
pwsh-*) are hard links tomulti-pwsh. multi-pwsh doctor --repair-aliasesperforms a shim health check and re-links broken hard links automatically.- You can still manually copy/rename
multi-pwsh.exeunderMULTI_PWSH_BIN_DIR(default:~/.pwsh/bin) to an alias-like name (for examplepwsh-7.4.exe); it automatically enters host mode and resolves the target installation from that alias name. -NamedPipeCommand <pipeName>is supported in host mode (Windows only), matchingpwsh-hostbehavior.
multi-pwsh virtual environments provide isolated PowerShell module roots. They are conceptually similar to Python virtual environments, but in this first version the isolation is implemented by selecting a venv-specific PSModulePath root for hosted launches.
By default, venvs live under ~/.pwsh/venv/<name>. If MULTI_PWSH_VENV_DIR is set, they live under that directory instead.
Available commands:
multi-pwsh venv create <name>creates a named venv.multi-pwsh venv delete <name>removes a named venv.multi-pwsh venv export <name> <archive.zip>exports a named venv to a zip archive.multi-pwsh venv import <name> <archive.zip>imports a named venv from a zip archive.multi-pwsh venv listshows the configured venv root and all known venvs.
Create a venv and launch a hosted PowerShell session that uses it:
multi-pwsh venv create msgraph
multi-pwsh host 7.4 -venv msgraph -NoLogo -NoProfileYou can verify which module root is being used:
multi-pwsh host 7.4 -venv msgraph -NoLogo -NoProfile -Command "$env:PSModulePath"Both -venv <name> and -VirtualEnvironment <name> are supported.
You can also opt into a venv by path with PSMODULE_VENV_PATH:
$env:PSMODULE_VENV_PATH = Join-Path $HOME ".pwsh/venv/msgraph"
multi-pwsh host 7.4 -NoLogo -NoProfile-venv <name> and -VirtualEnvironment <name> accept a venv name and resolve it to a path before launch. PSMODULE_VENV_PATH is the lower-level path form of the same idea and is useful when a parent PowerShell session already knows which venv path should flow to child hosted sessions.
If both a venv flag and PSMODULE_VENV_PATH are present, the flag wins for that launch because multi-pwsh resolves the named venv and sets the effective path explicitly. If neither is present, no venv-specific startup-hook behavior is enabled.
Venvs are module discovery roots, so modules should live directly under <venv-root>/<ModuleName>.
For the current implementation, the safest way to place modules into a venv is to save them directly into that venv root:
$venvRoot = Join-Path $HOME ".pwsh/venv/msgraph"
Save-Module -Name Microsoft.Graph.Authentication -Repository PSGallery -Path $venvRoot -Force
Save-Module -Name Microsoft.Graph.Users -Repository PSGallery -Path $venvRoot -ForceThen use the venv when launching PowerShell:
multi-pwsh host 7.4 -venv msgraph -NoLogo -NoProfile -Command "Get-Module -ListAvailable Microsoft.Graph.Authentication"You can package a venv as a zip archive and recreate it elsewhere:
multi-pwsh venv export msgraph msgraph.zip
multi-pwsh venv import msgraph-copy msgraph.zip
multi-pwsh host 7.4 -venv msgraph-copy -NoLogo -NoProfileImport is intentionally conservative: importing into an existing destination venv is rejected instead of merging archive contents.
- Venv selection changes module discovery and import precedence for hosted launches.
- In this first version,
Install-Moduleis not automatically redirected into the venv just because-venvis used. - PowerShell may still include some built-in or default module paths in the effective
PSModulePath; the venv is intended to be the selected module root, not a perfect process-level sandbox. - The venv feature currently applies to
multi-pwsh host ...and implicit host shims such aspwsh-7.4.exe, not to arbitrary externalpwshprocesses.
Managed paths can be controlled with environment variables:
MULTI_PWSH_HOME: override the multi-pwsh home directory (default:~/.pwsh). Extracted PowerShell versions are stored underMULTI_PWSH_HOME/multi, virtual environments are stored underMULTI_PWSH_HOME/venvunlessMULTI_PWSH_VENV_DIRis set, and alias metadata is stored inMULTI_PWSH_HOME/aliases.json.MULTI_PWSH_BIN_DIR: override the shim and launcher directory (default:MULTI_PWSH_HOME/bin).MULTI_PWSH_CACHE_DIR: override archive cache directory (default:MULTI_PWSH_HOME/cache).MULTI_PWSH_VENV_DIR: override the virtual-environment root directory (default:MULTI_PWSH_HOME/venv).MULTI_PWSH_CACHE_KEEP: keep downloaded archives after extraction when set to a truthy value (1,true,yes, oron).
CI cache example:
$env:MULTI_PWSH_HOME = "$(Join-Path $HOME '.pwsh')"
$env:MULTI_PWSH_BIN_DIR = "$(Join-Path $env:MULTI_PWSH_HOME 'bin')"
$env:MULTI_PWSH_CACHE_DIR = "$(Join-Path $env:MULTI_PWSH_HOME 'cache')"
$env:MULTI_PWSH_VENV_DIR = "$(Join-Path $env:MULTI_PWSH_HOME 'venv')"
$env:MULTI_PWSH_CACHE_KEEP = "1"
multi-pwsh install 7.4.xWhen installed via bootstrap scripts, MULTI_PWSH_BIN_DIR (default: ~/.pwsh/bin) is added to PATH automatically if needed.
