Skip to content

/commands/uv/uv-python-pin

uv python pin 3.13: set the project's Python version (.python-version)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · uv 0.12.19 (bea138450 2026-09-24 aarch64-pc-windows-msvc)updated
tool
uv
versions
uv 0.4+
os
any

uv python pin 3.13 writes 3.13 to a .python-version file in the current directory. From then on, uv run, uv sync, uv venv and uv python find in that directory (and its subdirectories) use a Python 3.13 interpreter, downloading a managed build if none is installed. Commit .python-version so everyone on the project gets the same version.

Pin and check

bash
uv python pin 3.13
cat .python-version
echo "--- current pin"
uv python pin

Output

Pinned `.python-version` to `3.13`
3.13
--- current pin
3.13

uv python pin without an argument prints the version currently pinned for the directory.

Accepted formats

Command.python-version containsMatches
uv python pin 3.133.13Any 3.13.x
uv python pin 3.13.53.13.5Exactly that patch release
uv python pin pypy@3.10pypy@3.10PyPy implementing Python 3.10
uv python pin --rm(file removed)Back to requires-python or the default interpreter
uv python pin --resolved 3.13The interpreter pathExactly one installation on this machine (not portable)
uv python pin --global 3.133.13, in the user config directoryDefault for directories without their own pin

How it interacts with pyproject.toml

The pin must satisfy requires-python in pyproject.toml. uv checks it and refuses an incompatible pin (--no-project skips the check):

bash
cat > pyproject.toml <<'EOF'
[project]
name = "app"
version = "0.1.0"
requires-python = ">=3.12"
EOF
uv python pin 3.13 && cat .python-version
uv python pin 3.11

Output · exit 2

Pinned `.python-version` to `3.13`
3.13
error: The requested Python version `3.11` is incompatible with the project `requires-python` value of `>=3.12`.

Without a .python-version file, uv picks an interpreter that satisfies requires-python. Use the pin for "the version we develop on" and requires-python for "the versions we support".

How uv finds the pin

uv looks for .python-version in the working directory and then in each parent directory, but not beyond the boundary of the current project or workspace. If none is found it falls back to the global pin in the user configuration directory. --no-config turns off .python-version discovery for one command.

The file holds a version request, so any format uv accepts works, but plain version numbers keep it readable for other tools such as pyenv. When a command finds no installed interpreter that matches, uv downloads a managed CPython build, unless automatic downloads are disabled with the python-downloads setting or --no-python-downloads.

Typical workflow

  1. uv python pin 3.13 in the project root, then commit .python-version.
  2. uv sync (or uv venv) creates .venv with Python 3.13, downloading it if needed.
  3. To move the project to a new version, run uv python pin 3.14, then uv sync again: uv recreates the environment for the new interpreter.
  4. In CI, nothing extra is needed: the same file selects the same version.

Pitfalls

  • Pin outside requires-python. uv refuses it with the error shown above; widen requires-python first or pick a supported version.
  • Pinned version not available. With downloads disabled and no matching interpreter, uv run and uv sync stop with error: No interpreter found for Python 3.6 in ... followed by the places uv searched; install it with uv python install or enable downloads.
  • Old .venv after changing the pin. uv run and uv sync notice the mismatch and recreate the project environment, but a manually activated old .venv in your shell keeps the old interpreter until you activate it again.

FAQ

Does uv python pin install Python?

It can. When no matching interpreter is installed, current uv versions download a managed build while pinning. With downloads disabled, uv prints a warning that no interpreter was found and writes the pin anyway; uv python install with no argument installs the pinned version later.

Should I pin a minor version or an exact patch release?

A minor version such as 3.13 is the usual choice: everyone gets the same language version and patch updates still apply. Pin an exact release only when a bug or a binary dependency requires it.

Why does uv ignore the .python-version in my parent folder?

uv searches the working directory and its parents but stops at the project or workspace boundary, so a file above the project root is not used. Put the file in the project root.

Sources