pvm is a cross-platform CLI tool for installing and managing multiple PHP versions on Linux, macOS, and Windows.
The commands below always fetch the latest release from GitHub Releases — no version number to update. On Linux and macOS pvm goes into ~/.pvm/bin, a directory you own next to its php shim: no sudo to install it, and pvm self-upgrade / pvm self-remove never need it either.
mkdir -p ~/.pvm/bin
curl -fsSL https://github.com/rejmann/pvm/releases/latest/download/pvm-linux-amd64.tar.gz \
| tar -xz -C ~/.pvm/bin pvm
export PATH="$HOME/.pvm/bin:$PATH" # add this line to ~/.bashrc / ~/.zshrc toomkdir -p ~/.pvm/bin
curl -fsSL https://github.com/rejmann/pvm/releases/latest/download/pvm-darwin-arm64.tar.gz \
| tar -xz -C ~/.pvm/bin pvm
export PATH="$HOME/.pvm/bin:$PATH" # add this line to ~/.zshrc tooIf
PVM_HOMEis set, use$PVM_HOME/bininstead of~/.pvm/bin. Upgrading from an install in/usr/local/bin? Install as above, thensudo rm /usr/local/bin/pvmonce.
Installs pvm.exe to %LOCALAPPDATA%\Programs\pvm and adds it to your user PATH (no admin rights needed):
$dir = "$env:LOCALAPPDATA\Programs\pvm"
$zip = "$env:TEMP\pvm.zip"
New-Item -ItemType Directory -Force -Path $dir | Out-Null
Invoke-WebRequest -Uri "https://github.com/rejmann/pvm/releases/latest/download/pvm-windows-amd64.zip" -OutFile $zip
Expand-Archive -Path $zip -DestinationPath $dir -Force
Remove-Item $zip
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($userPath -notlike "*$dir*") {
[Environment]::SetEnvironmentVariable("Path", "$dir;$userPath", "User")
}
$env:Path = "$dir;$env:Path"The last line makes pvm available in the current session; other terminals that were already open need to be restarted to pick up the updated PATH.
Replace latest/download with download/<tag> in any of the commands above. For example, on Linux:
VERSION=v1.0.1
curl -fsSL "https://github.com/rejmann/pvm/releases/download/${VERSION}/pvm-linux-amd64.tar.gz" \
| tar -xz -C ~/.pvm/bin pvmOn Windows, set the URL in the PowerShell snippet to:
$version = "v1.0.1"
Invoke-WebRequest -Uri "https://github.com/rejmann/pvm/releases/download/$version/pvm-windows-amd64.zip" -OutFile $zipAll available tags are listed on the releases page.
pvm --helpPrebuilt binaries are published for Linux (x86_64, arm64), macOS (Apple Silicon, Intel) and Windows x86_64 — on Linux arm64 or an Intel Mac, swap
amd64/arm64in the archive name (pvm-linux-arm64.tar.gz,pvm-darwin-amd64.tar.gz). On other platforms, see Build.
# List available PHP versions from php.net
pvm available # alias: a
# Install the current LTS branch
pvm install lts # alias: i
pvm install 8.3
# List installed versions
pvm list # alias: ls
# Show the currently active version
pvm current # alias: cur
# Switch to an installed version
pvm use 8.3 # alias: u
pvm use lts
# Remove an installed version
pvm remove 8.3 # alias: rm
# Manage PHP extensions of the version in use (or -v <version>)
pvm ext add redis intl
pvm ext disable xdebug
pvm ext list
# Run Composer with the PHP version in use (composer.phar is downloaded on first use)
pvm composer install
# Upgrade pvm itself to the latest release
pvm self-upgrade
# Uninstall pvm
pvm self-remove| OS | Requirement |
|---|---|
| Linux (Debian/Ubuntu) | apt-get, sudo. Extra PHP branches (e.g. 7.4) need the ondrej/php PPA — pvm adds it automatically. |
| Linux (Fedora) | dnf, sudo. Extra branches need the Remi repo — pvm adds it automatically. |
| Linux (RHEL/CentOS) | yum, sudo. Extra branches need the Remi repo — pvm adds it automatically. |
| Linux (Arch) | pacman, sudo. Only the version available in the official repos can be installed. |
| Linux (openSUSE) | zypper, sudo. |
| macOS | Homebrew |
| Windows | No external dependency — PHP is downloaded directly from windows.php.net and pvm writes its php.ini |
pvm detects the package manager automatically on Linux — no configuration needed. pvm install also adds the base extensions zip, xml, mbstring and curl (and on Windows enables openssl), so pvm composer needs nothing else on the machine — no unzip, 7z or global Composer. Any other extension is one pvm ext add away, and pvm composer offers the ones a project requires before running. On Linux, only installing or removing PHP and its extensions goes through the package manager, so install, remove and ext add/remove/enable/disable ask for your sudo password once per command; everything else, pvm use included, runs without root.
The pvm directory on your PATH holds both pvm and the php shim, so one entry covers them (on Linux and macOS it is the one from the installation above):
| OS | Directory | Shell config |
|---|---|---|
| Linux | ~/.pvm/bin |
export PATH="$HOME/.pvm/bin:$PATH" in ~/.bashrc / ~/.zshrc |
| macOS | ~/.pvm/bin |
export PATH="$HOME/.pvm/bin:$PATH" in ~/.zshrc (older pvm used ~/.pvm/shims: replace it) |
| Windows | %LOCALAPPDATA%\pvm\shims |
setx PATH "%LOCALAPPDATA%\pvm\shims;%PATH%" |
pvm useprints the exact command if the directory is not yet in your PATH.
pvm self-remove # asks before removing anything
pvm self-remove --php # also remove the PHP versions installed through pvmIt removes the pvm binary and its data directory and, on Windows, the pvm entries in the user PATH and the PowerShell profile. On Windows the PHP versions live in the data directory and are always removed; on Linux and macOS they are system/Homebrew packages and are kept unless you pass --php. Run it without sudo — if the binary is in a root-owned directory, it prints the sudo rm command to finish. See docs/commands.md for details.
Requires only make and Docker Compose — Go runs inside containers, never on your machine:
make setup # build the Docker images
make build # dist/pvm for your OS/arch
make build-all # all platforms, e.g. dist/pvm-windows-amd64.exe
make testDeveloping pvm? Use
make pvm <command>— it runs pvm inside a Docker container, never on your machine, so your real pvm and system PHP stay untouched. See docs/development.md.
| Doc | Description |
|---|---|
| docs/flow.md | End-to-end flow: lifecycle, state files, version resolution, Composer, per-OS differences |
| docs/architecture.md | Package layout and data flow |
| docs/commands.md | CLI command reference |
| docs/development.md | Adding commands and installers |