Skip to content

Python versions

Butler manages Python versions through uv, the same way it manages Node through fnm. Versions are prebuilt downloads — no compiler, no waiting on a source build.

Python support comes from the uv component. Install it once, then install the versions you want:

Terminal window
butler install uv
butler uv python install 3.13
butler uv python install 3.11

List what you have, and see which one applies where you are:

Terminal window
butler uv python list
butler uv python find

The Python tab in the menu bar app does the same things with a picker, and only appears once uv is installed.

After shell integration, python, python3, pip, pip3 and venv are on your PATH and resolve the version for the directory you’re in:

Terminal window
python --version
pip install httpx
venv .venv

Resolution follows uv’s own rules — an activated virtualenv first, then a .venv in the project, then .python-version, then your default. Nothing is installed as a side effect of asking: if a project pins a version you don’t have, you’ll be told rather than made to wait for a download.

You can always reach uv directly for anything not covered by a shim:

Terminal window
butler uv run script.py
butler uv sync
butler uv pip list

This is the part that usually bites. A version manager’s shell integration only runs in an interactive shell, so an editor, a build script, a Makefile, a git hook or a scheduled job quietly gets whatever system Python it finds — which is how you end up debugging a “works in my terminal” failure for an hour.

Butler installs real files on PATH rather than shell functions, so anything that inherits your environment resolves the same interpreter your terminal does. Nothing needs to source a profile first.

If you’d rather call python, pip, node and php directly, without the butler prefix:

Terminal window
butler shell install

Open a new terminal, then check what’s actually resolving:

Terminal window
butler doctor

butler doctor reports each shim and the interpreter it resolves to, and says plainly when something earlier on your PATH is shadowing Butler’s — which is the usual cause of “I installed 3.13 but I’m still on 3.9”.

Butler points uv at its own directory, so the interpreters it downloads sit under Butler’s state (~/Library/Application Support/Butler/Data/uv) and butler reset reaches them.

If you already had uv with Pythons installed, those stay exactly where they are and keep working — Butler does not move or adopt them.