uv-pack
Bundle a locked uv environment into a self-contained, offline-installable directory.
The output includes pinned requirements, third-party wheels, locally built wheels,
and a portable Python interpreter.
What it does
- Exports locked requirements from your
uvlock file. - Downloads third-party wheels into
pack/wheels/. - Builds local workspace packages into
pack/vendor/. - Downloads a python-build-standalone archive into
pack/python/(unless you skip thepythonstep). - Writes
unpack.sh,unpack.ps1, andunpack.cmdto unpack the resulting venv offline.
Install
Install uv-pack as a dev-dependency.
Once installed, run using:
You can also use uv-pack as a tool.
# specify the python version! uv tool run --python 3.12 uv-pack --help # or using uvx (equivalent) uvx --python 3.12 uv-pack --help
CLI
Options:
STEPS: subset of pipeline steps (default:clean export download build python)-s, --skip: skip a pipeline step (can be supplied multiple times)-o, --output-directory: path to output directory (default:./pack)-v, --verbose: show more detailed pack progress logging--uv-build: extra args passed touv build--uv-export: extra args passed touv export--pip-download: extra args passed topip download
Notes:
- The CLI is structured into five pipeline steps, see description below.
- Extra args are split on whitespace (for example:
--uv-export "--dev --all-extras").
Pipeline steps:
clean: remove the output directoryexport: writerequirements.txtfiles for third-party and local packagesdownload: download third-party wheelsbuild: build local wheels and compile the combined requirements filepython: download a python-build-standalone archive for the current Python version and platform
Example
# run the entire pipeline (default) with verbose outputs uv-pack --verbose # only clean and export the requirements uv-pack clean export
Output layout
pack/
requirements.txt
wheels/
requirements.txt
vendor/
requirements.txt
python/ # (omitted when the python step is skipped)
unpack.sh
unpack.ps1
unpack.cmd
.gitignore
README.md
Unpack and install offline
POSIX (sh/bash/zsh):
PowerShell:
Windows cmd:
All scripts also accept VENV_DIR, PY_DEST and BASE_PY environment variables.
Use BASE_PY when you skipped the python step during packing to provide a system
python interpreter. VENV_DIR (default = .venv) and PY_DEST (default = .python)
can be used to customize the target python and venv directory.
Configuration
UV_PYTHON_INSTALL_MIRROR can override the GitHub API endpoint to retrieve the
Python releases, default is:
https://api.github.com/repos/astral-sh/python-build-standalone/releases/latest.
GITHUB_TOKEN can be used to authenticate requests to the GitHub API to
prevent possible rate-limiting.
Limitations
- The pack process must happen in the
pyproject.tomloruv.tomldirectory, typically the repository root, becauseuvexports relative paths to the project root. - The build platform is expected to equal the usage platform; it is currently not possible to pack an environment for a different platform.
- The project Python version is ignored when running
uv-packas a tool (uv tool runoruvx) and should be specified usinguv tool run --python 3.11 uv-packoruvx --python 3.11 uv-pack, see uv#uv5951 and uv#8206. - The download process can be slow because
pip downloadis used as there is no native (parallel) uv download option available for wheels, see uv#3163.
FAQ
How do I pass extra options to uv export or another command?
Use --uv-export to forward arguments, for example:
uv-pack --uv-export "--package $MY_PACKAGE"to export only a specific workspace packageuv-pack --uv-export "--locked --dev"to include dev-deps and ensure an up-to-date lock fileuv-pack --uv-export "--all-extras"to include all extra dependencies
The same is true for --uv-build and --pip-download arguments.
How do I specify index-urls and extra-index-urls?
The index urls set in pyproject.toml and uv.toml are not configured by default for the wheel
download (pip download), you can specify them as:
uv-pack --pip-download "--index-url $MY_INDEX --extra-index-url $MY_EXTRA_INDEX"
How do I skip bundling Python?
Skip the python step: uv-pack --skip python. When unpacking, set BASE_PY to a system Python path.
How do I rerun without deleting the existing pack directory?
Skip the clean step: uv-pack --skip clean. Note that this automatically re-uses downloaded wheels
and the downloaded Python interpreter.
How do I only re-build my package if my pack is already complete?
Run only uv-pack build.