Automatic Python version and virtualenv manager — one command that just works
Project description
pyversion
One command. Any Python version. Zero configuration.
pyversion pip install requests
That's it. pyversion figures out which Python your project needs, installs it if missing, creates and validates the virtual environment, and runs pip — all automatically, every time.
The problem
You have three Python projects. Each needs a different Python version. Every time you switch between them, something breaks:
$ cd project-a
$ pip install -r requirements.txt
# Which pip is this? Which Python? Is my venv activated?
# Did I forget to source venv/bin/activate?
# Wait, this is installing into Python 3.13 but the project needs 3.11...
The actual workflow developers put up with today:
# project-a setup (Python 3.11)
python3.11 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# switch to project-b (Python 3.12)
deactivate
cd ../project-b
python3.12 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# forget to activate, install into wrong environment
# wonder why imports break
# start over
This is the state of Python development in 2025. It's a rite of passage — and it shouldn't be.
The solution
$ cd project-a
$ pyversion pip install -r requirements.txt
🔍 Detecting Python requirement...
→ Project requires Python 3.11 (from pyproject.toml)
🐍 Ensuring Python 3.11 is available...
✅ Python 3.11 already installed
📦 Setting up virtual environment...
✅ Virtual environment ready: ./.venv
✔️ Validating environment...
✅ Environment synced with Python 3.11.10
⚙️ Running pip install -r requirements.txt...
Collecting requests...
Successfully installed requests-2.31.0 urllib3-2.0.0 certifi-2023.7.22
✅ Command completed successfully
$ cd ../project-b
$ pyversion pip install -r requirements.txt
🔍 Detecting Python requirement...
→ Project requires Python 3.12 (from .python-version)
🐍 Ensuring Python 3.12 is available...
✅ Python 3.12 already installed
📦 Setting up virtual environment...
→ Creating .venv with Python 3.12...
✅ Virtual environment ready: ./.venv
✔️ Validating environment...
✅ Environment synced with Python 3.12.7
⚙️ Running pip install -r requirements.txt...
✅ Command completed successfully
No activation. No version flags. No thinking. Just cd and run.
Install
Homebrew (recommended)
brew install twinboi90/tap/pyversion
That's it. No cloning, no PATH setup, no configuration. Homebrew handles everything.
pip
pip install pyversion-cli
Then reload your shell (or open a new terminal window). The pyversion command will be available immediately.
Note: If
pyversionisn't found after install, runpyversion setup-pathto add it to your PATH automatically, thensource ~/.zshrc.
install.sh (no Homebrew, no pip)
git clone https://github.com/twinboi90/pyversion.git
cd pyversion
./install.sh
The installer:
- Detects your Python and installs pyversion
- Finds where pip put the script
- Adds it to your shell's PATH automatically (
~/.zshrc,~/.bash_profile, or~/.config/fish/config.fish) - Tells you exactly what it changed
Then reload your shell:
source ~/.zshrc # or ~/.bash_profile for bash
pip (manual)
git clone https://github.com/twinboi90/pyversion.git
cd pyversion
pip install -e .
pyversion setup-path # adds pyversion to your PATH
source ~/.zshrc
Verify
pyversion --version
# pyversion 0.1.0
Usage
The main command
pyversion pip <any pip args>
Every pip subcommand works exactly as you'd expect:
pyversion pip install requests
pyversion pip install -r requirements.txt
pyversion pip install --upgrade requests
pyversion pip uninstall requests
pyversion pip list
pyversion pip freeze
pyversion pip freeze > requirements.txt
pyversion pip show requests
pyversion pip install "django>=4.2,<5.0"
Project status
$ pyversion status
📊 pyversion status
Project dir: /Users/you/projects/myapp
Required Python: 3.11 (from project config)
Virtual env: ./.venv [✅ synced]
Venv Python: 3.11.10
Packages: 42 installed
Last used: 2025-04-20T18:30:00+00:00
Health check
$ pyversion check
🔎 pyversion check
✅ Python requirement: 3.11
✅ Python 3.11 available at /usr/local/bin/python3.11
✅ Virtual environment exists at ./.venv
✅ Venv synced with Python 3.11.10
✅ pip functional (pip 24.x)
✅ Everything looks good!
Manage Python versions
$ pyversion versions
🐍 Installed Python versions (pyversion-managed)
● Python 3.11 (3.11.10) ~/.pyversion/versions/3.11/bin/python3
● Python 3.12 (3.12.7) ~/.pyversion/versions/3.12/bin/python3
System Pythons (not managed by pyversion):
○ python3.13 → 3.13.0 (/usr/local/bin/python3.13)
○ python3 → 3.13.0 (/usr/local/bin/python3)
Clean up orphaned versions
$ pyversion cleanup
🧹 pyversion cleanup
Managed Python versions:
Python 3.11 [✅ active (2 projects)]
· /Users/you/projects/api-server
· /Users/you/projects/data-pipeline
Python 3.10 [⚠ orphaned (no registered projects)] (312 MB)
⚠ Found 1 version with no active projects:
· Python 3.10 (312 MB)
Remove these 1 version(s)? [y/N] y
✅ Removed Python 3.10 (312 MB freed)
✅ Done. 312 MB freed.
Use --dry-run to preview without deleting anything:
pyversion cleanup --dry-run
Initialize a new project
$ pyversion init
🚀 pyversion init
Which Python version should this project use?
1. Python 3.9
2. Python 3.10
3. Python 3.11
4. Python 3.12
5. Python 3.13
Enter number or version: 4
✅ Created .python-version → 3.12
Next: run pyversion pip install -r requirements.txt to set up your environment.
Fix PATH (if needed)
pyversion setup-path
How it works
Every time you run pyversion pip <args>, six things happen automatically:
1. DETECT Read .python-version or pyproject.toml
→ "This project needs Python 3.11"
2. ENSURE Check if Python 3.11 is installed
→ If not: download precompiled binary (~30 seconds)
→ If yes: skip
3. VALIDATE Check the virtual environment for 11 potential failure modes:
· Missing python or pip binaries
· Broken symlinks
· Version mismatch between venv and requirement
· pyvenv.cfg disagreement
· The Python that built the venv has since been deleted
· And more
4. REPAIR If anything is wrong, rebuild automatically
→ Saves your installed packages first
→ Rebuilds with the correct Python
→ Reinstalls packages
5. RUN Execute pip in the correct environment
→ .venv/bin/pip install requests
6. TRACK Register this project in ~/.pyversion/registry.json
→ Powers cleanup's orphan detection
Python version detection
pyversion reads from these files, in priority order:
| File | Format | Example |
|---|---|---|
.python-version |
Plain version string | 3.11 |
pyproject.toml |
requires-python field |
>=3.11 |
setup.cfg |
python_requires option |
>=3.11 |
setup.py |
python_requires keyword |
">=3.11" |
.tool-versions |
asdf/mise format | python 3.11.5 |
All common PEP 440 specifiers are supported: >=3.11, ~=3.11.0, ==3.11.*, ^3.11.
Python installation
When a required Python version isn't on your system, pyversion downloads a precompiled binary from python-build-standalone — the same source used by uv and rye.
- No compilation — prebuilt binaries, not source builds
- Fast — typically under 30 seconds
- Cached — subsequent installs of the same version skip the download
- Stored in
~/.pyversion/versions/<version>/
Supports macOS on both Intel (x86_64) and Apple Silicon (aarch64).
Venv sync detection
pyversion detects 11 ways a virtual environment can be broken or out of date:
| Issue | What it means |
|---|---|
venv_missing |
.venv directory doesn't exist |
python_missing |
bin/python binary is gone |
python_broken_link |
bin/python is a symlink pointing to a deleted file |
python_not_executable |
Binary exists but isn't executable |
pip_missing |
bin/pip is gone |
pyvenv_cfg_missing |
pyvenv.cfg is absent |
version_mismatch |
Venv Python ≠ project requirement |
cfg_version_mismatch |
pyvenv.cfg disagrees with the actual binary |
home_python_gone |
The Python that created the venv no longer exists |
pip_outdated |
pip version is below 22.0 |
metadata_missing |
pyversion's tracking file is absent |
When any of the first nine are detected, pyversion automatically rebuilds the venv — saving your installed packages, recreating with the correct Python, and reinstalling. You never have to diagnose these manually.
Real-world scenarios
New developer, fresh clone
$ git clone github.com/yourcompany/api-server
$ cd api-server
$ pyversion pip install -r requirements.txt
🔍 Detecting Python requirement...
→ Project requires Python 3.11 (from pyproject.toml)
🐍 Ensuring Python 3.11 is available...
→ Python 3.11 not found locally. Installing...
→ Downloading Python 3.11.10...
[████████████████████] 100%
→ Extracting to ~/.pyversion/versions/3.11...
→ Verified: Python 3.11.10
✅ Python 3.11 installed
📦 Setting up virtual environment...
→ Creating .venv with Python 3.11...
✅ Virtual environment ready: ./.venv
✔️ Validating environment...
✅ Environment synced with Python 3.11.10
⚙️ Running pip install -r requirements.txt...
Installing collected packages: django, requests, psycopg2...
Successfully installed django-4.2.7 requests-2.31.0 psycopg2-2.9.7
✅ Command completed successfully
First run: ~45 seconds (includes Python download). Every run after: under 2 seconds.
Version mismatch auto-fix
# Someone ran `python3.12 -m venv .venv` by mistake
# but pyproject.toml says requires-python = ">=3.11,<3.12"
$ pyversion pip install flask
📦 Setting up virtual environment...
⚠ Venv has issues — rebuilding:
· Venv Python version does not match project requirement
→ Saved 12 package(s) from old venv
→ Creating .venv with Python 3.11...
→ Reinstalling packages into new venv...
✅ Venv rebuilt with Python 3.11
✔️ Validating environment...
✅ Environment synced with Python 3.11.10
⚙️ Running pip install flask...
✅ Command completed successfully
Switching between projects
$ cd ~/projects/api-server # requires Python 3.11
$ pyversion pip list
✅ Environment synced with Python 3.11.10
...
$ cd ~/projects/ml-pipeline # requires Python 3.12
$ pyversion pip list
✅ Environment synced with Python 3.12.7
...
$ cd ~/projects/legacy-app # requires Python 3.9
$ pyversion pip install -r requirements.txt
✅ Environment synced with Python 3.9.20
...
Zero manual activation. Zero version flags. Just cd and work.
Why not just use...
pyenv + venv
pyenv is excellent at managing Python versions, but it doesn't manage virtual environments. You still have to create, activate, and maintain venvs manually. Forget to activate? Wrong packages. Switch projects? Re-activate. pyversion does all of this for you automatically.
Poetry
Poetry is a full dependency manager with its own lock file format, its own CLI, and its own way of thinking about projects. It's powerful but requires adopting its entire workflow. pyversion wraps pip — no new concepts, no lock files, no configuration. If you know pip, you know pyversion.
conda
conda is a complete package ecosystem designed for data science workloads. It's large, slow to solve environments, and installs a lot of infrastructure. pyversion is 500 lines of Python with zero dependencies beyond the stdlib.
uv
uv is extremely fast and excellent at what it does. pyversion and uv aren't really competing — uv is a pip replacement, pyversion is an orchestration layer. They can coexist. That said, pyversion's goal is maximum simplicity: one command, no new mental model.
Docker
Docker solves environment isolation across machines and teams. pyversion solves it on your local machine. Both have their place.
Project layout
pyversion/
├── pyversion/
│ ├── __init__.py
│ ├── __main__.py # CLI entry point and command orchestration
│ ├── version_manager.py # Python version detection and installation
│ ├── environment_manager.py # Virtual environment lifecycle
│ ├── pip_wrapper.py # Routes pip to the correct venv
│ ├── sync.py # SyncChecker — 11-issue venv health detection
│ └── registry.py # Project→Python version tracking
├── tests/
│ ├── conftest.py # Shared fixtures (fake_venv factory, etc.)
│ ├── test_sync.py # 30+ tests for SyncChecker
│ ├── test_registry.py # 24 tests for Registry
│ └── test_version_manager.py # 40 tests for version detection/parsing
├── install.sh # One-shot installer with PATH setup
└── pyproject.toml
Development
git clone https://github.com/twinboi90/pyversion.git
cd pyversion
pip install -e ".[dev]"
# Run tests
pytest
# Run tests with coverage
pytest --cov=pyversion --cov-report=term-missing
94 tests, zero external dependencies beyond the stdlib.
Roadmap
Phase 1 ✅ — Core
pyversion pipwith full auto-orchestration- Config file detection (5 formats)
- Precompiled Python installation
- Virtual environment management
- macOS support (Intel + Apple Silicon)
Phase 2 ✅ — Robustness
- 11-mode venv sync detection and auto-repair
- Project registry for cleanup intelligence
- Interactive
pyversion cleanupwith disk usage - 94-test suite
Phase 3 — Expansion (in progress)
- Windows PowerShell support
- Linux support
- IDE integration
pyversion initimprovements
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyversion_cli-0.1.1.tar.gz.
File metadata
- Download URL: pyversion_cli-0.1.1.tar.gz
- Upload date:
- Size: 33.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03b2b75a8410177074a6eb6316df5d11c4a7879750d10d14fba6fc77c0ccf78a
|
|
| MD5 |
bcd1ff9170eedf972fc0d88ba98a7231
|
|
| BLAKE2b-256 |
bcb67519fd64f1f28db6a44a87bd22bf0d332af6fffdbf37886d78afaac8c2eb
|
Provenance
The following attestation bundles were made for pyversion_cli-0.1.1.tar.gz:
Publisher:
publish.yml on twinboi90/pyversion
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyversion_cli-0.1.1.tar.gz -
Subject digest:
03b2b75a8410177074a6eb6316df5d11c4a7879750d10d14fba6fc77c0ccf78a - Sigstore transparency entry: 1346993420
- Sigstore integration time:
-
Permalink:
twinboi90/pyversion@88ea76995212976d7736bd3a2d6019d9ea482df4 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/twinboi90
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@88ea76995212976d7736bd3a2d6019d9ea482df4 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyversion_cli-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pyversion_cli-0.1.1-py3-none-any.whl
- Upload date:
- Size: 27.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
479b31a71de76b98c5a1aac636b023a30ce9ea69218ab467bc8f1cd9eee70324
|
|
| MD5 |
6ebf83090d2999e2757e1789c381baf9
|
|
| BLAKE2b-256 |
278fac14edc75fc7884cf4bfb0bd0dc83130fbefb0a5a5f88eb2b44e368e872f
|
Provenance
The following attestation bundles were made for pyversion_cli-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on twinboi90/pyversion
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyversion_cli-0.1.1-py3-none-any.whl -
Subject digest:
479b31a71de76b98c5a1aac636b023a30ce9ea69218ab467bc8f1cd9eee70324 - Sigstore transparency entry: 1346993486
- Sigstore integration time:
-
Permalink:
twinboi90/pyversion@88ea76995212976d7736bd3a2d6019d9ea482df4 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/twinboi90
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@88ea76995212976d7736bd3a2d6019d9ea482df4 -
Trigger Event:
release
-
Statement type: