uv pip compile: requirements.in to requirements.txt (tested)

uv pip compile requirements.in -o requirements.txt pins everything. Re-running keeps the versions already in requirements.txt: add -U to upgrade all, or -P name for one package. Install with uv pip sync requirements.txt.

uv pip compile is uv's drop-in for pip-tools' pip-compile: it turns loose requirements (requirements.in) into a fully pinned requirements.txt. Measured with uv 0.13.5 on Python 3.13.5 (Linux); each transcript ran in order in one fresh directory and is unedited.

1. requirements.in to requirements.txt

Transcript:

$ printf 'requests<2.33\nsix\n' > requirements.in && cat requirements.in
requests<2.33
six
$ uv pip compile requirements.in -o requirements.txt -q && cat requirements.txt
# This file was autogenerated by uv via the following command:
#    uv pip compile requirements.in -o requirements.txt
certifi==2026.10.23
    # via requests
charset-normalizer==3.5.2
    # via requests
idna==3.20
    # via requests
requests==2.32.5
    # via -r requirements.in
six==1.17.0
    # via -r requirements.in
urllib3==2.8.0
    # via requests

Every package, including transitive ones, is pinned with ==, and the # via comments show who pulled it in. Without -o the result goes to stdout only.

2. Existing pins are kept: --upgrade / --upgrade-package

Transcript:

$ uv pip compile requirements.in -q --upgrade-package six | grep -E '^(six|requests)=='
requests==2.32.5
six==1.17.0
$ printf 'requests\nsix\n' > requirements.in && uv pip compile requirements.in -o requirements.txt -q && grep -E '^requests==' requirements.txt
requests==2.32.5
$ uv pip compile requirements.in -o requirements.txt -q -U && grep -E '^requests==' requirements.txt
requests==2.34.2

This is the surprise: after removing the <2.33 limit, re-running with -o requirements.txt still produced requests==2.32.5, because uv reuses the versions already pinned in the output file. Only -U / --upgrade moved it to 2.34.2. Use --upgrade-package NAME (-P) to bump one package and leave the rest alone.

3. --generate-hashes and --universal

Transcript:

$ uv pip compile requirements.in -q --generate-hashes | sed -n '1,8p'
# This file was autogenerated by uv via the following command:
#    uv pip compile requirements.in --generate-hashes
certifi==2026.10.23 \
    --hash=sha256:a9895e6e2758b371e0545e321a3a8fd1fcfd9829ada8824a936dfb16aaaf36cd \
    --hash=sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1
    # via requests
charset-normalizer==3.5.2 \
    --hash=sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e \
$ printf 'colorama ; sys_platform == "win32"\nsix\n' > win.in && uv pip compile win.in -q --no-header
six==1.17.0
    # via -r win.in
$ uv pip compile win.in -q --no-header --universal
colorama==0.4.6 ; sys_platform == 'win32'
    # via -r win.in
six==1.17.0
    # via -r win.in

--generate-hashes adds --hash=sha256:... lines for pip install --require-hashes. By default the file is resolved for the current platform only, so a Windows-only dependency was dropped entirely on Linux. --universal keeps it with its environment marker, which you need if the same file is installed on Windows, macOS and Linux.

4. Install it: uv pip sync (and conflicts)

Transcript:

$ uv pip sync requirements.txt 2>&1 | tail -2
error: No virtual environment found; run `uv venv` to create an environment, or pass `--system` to install into a non-virtual environment
$ uv venv -q && uv pip install six==1.16.0 -q && uv pip sync requirements.txt
Resolved 6 packages in 2ms
Uninstalled 1 package in 0.27ms
Installed 6 packages in 4ms
 + certifi==2026.10.23
 + charset-normalizer==3.5.2
 + idna==3.20
 + requests==2.34.2
 - six==1.16.0
 + six==1.17.0
 + urllib3==2.8.0
$ printf 'six==1.17.0\nsix==1.16.0\n' > bad.in && uv pip compile bad.in -q
error: No solution found when resolving dependencies
  cause: Because you require six==1.17.0 and six==1.16.0, we can conclude that your requirements are unsatisfiable.
[exit 1]

uv pip sync requirements.txt makes the venv match the file exactly: it installed the pins and replaced the stray six==1.16.0. Like other uv pip commands it needs a venv (uv venv) or --system. Conflicting pins fail with No solution found when resolving dependencies and a readable explanation. In a pyproject.toml project, uv lock / uv sync replace this workflow (see uv pip install vs uv add).

Related: uv pip install -r requirements.txt, uv pip install vs uv add, uv ignore SSL errors, pip error: externally-managed-environment.

Frequently asked questions

Why doesn't uv pip compile upgrade my packages?

With -o it reuses the pins already in the output file. Pass --upgrade (-U) or --upgrade-package NAME (-P).

How do I generate hashes with uv pip compile?

uv pip compile requirements.in --generate-hashes -o requirements.txt.

Why is a Windows-only package missing from uv pip compile output?

It resolves for the current platform by default. Use --universal to keep platform-specific packages with their markers.

Written with AI assistance. Measured on 2026-10-23 with uv 0.13.5 and CPython 3.13.5 on Linux. Each transcript was produced by running the commands verbatim in one fresh directory. PlainHeaders is our extension; uv is free.