Open source · written in Rust

One Python. Every environment.

A lightweight Python version & virtual environment manager written in Rust. Shared envs, hardlinked deduplication, single 2.6 MB binary — Anaconda's ergonomics, without the bloat.

~/projects · zsh
$pvm python install 3.12
↓ Downloaded Python 3.12.4 · 12.4 MB
$pvm env create web 3.12
✓ Created environment web
$pvm env activate web
(web) $pip install pandas numpy
✓ Installed 12 packages · deduplicated 9 · saved 287 MB

At a glance

How pvm compares

Featurepvmuv / miseAnaconda
Shared environments
Package deduplication
No external dependencies
Single binary2.6 MB
Fast

Built for real workflows

Fast where it matters. Boring where it should be.

pvm keeps Python out of your way: shared environments, deduplicated packages, and a single binary you can drop into any machine.

data-science
web
ml-prod
scratch

Shared environments, used everywhere

Create an environment once and reuse it across any project. No more .venv per repo.

~287 MB

Hardlink deduplication

Identical packages stored once, hardlinked into every env. Pandas, NumPy, PyTorch — paid for once.

2.6 MB binary

No Python needed to install. No Conda runtime. Just one Rust binary.

Drop-in pip

`pip install` is auto-wrapped while activated — deduplicates without changing your habits.

Instant activation

No JIT, no Conda init. Activation is a shell function.

py 3.8py 3.9py 3.10py 3.11py 3.12py 3.13py 3.14

Standalone Python builds

Powered by python-build-standalone — the same prebuilt Pythons used by uv. Reproducible across machines.

Under the hood

How it works

  1. 01

    Download standalone Python

    Prebuilt Python from python-build-standalone — the same source uv uses.

  2. 02

    Create environments centrally

    Environments live under ~/.pvm/envs and can be activated from any directory.

  3. 03

    Pip installs go through dedup

    A pip wrapper hardlinks identical packages from a global content-addressable store.

  4. 04

    Activate with a shell function

    No subprocess, no init step — activation is just sourcing the env script.

Get started

One line. Then you're done.

Installs to ~/.local/bin/pvm and stores state in ~/.pvm/.

curl -fsSL https://pvm.sungjin.dev/install.sh | bash

Then enable shell integration

echo 'eval "$(pvm init zsh)"' >> ~/.zshrc && eval "$(pvm init zsh)"

Ready to thin out your .venv graveyard?

Install pvm in 30 seconds and reclaim a few gigabytes of disk you didn't know you were spending.