changelogs/0.8.x.md
Since we released uv 0.7.0 in April, we've accumulated various changes that improve correctness and user experience, but could break some workflows. This release contains those changes; many have been marked as breaking out of an abundance of caution. We expect most users to be able to upgrade without making changes.
This release also includes the stabilization of a couple uv python install features, which have
been available under preview since late last year.
Install Python executables into a directory on the PATH
(#14626)
uv python install now installs a versioned Python executable (e.g., python3.13) into a
directory on the PATH (e.g., ~/.local/bin) by default. This behavior has been available under
the --preview flag since Oct 2024. This change
should not be breaking unless it shadows a Python executable elsewhere on the PATH.
To install unversioned executables, i.e., python3 and python, use the --default flag. The
--default flag has also been in preview, but is not stabilized in this release.
Note that these executables point to the base Python installation and only include the standard
library. That means they will not include dependencies from your current project (use
uv run python instead) and you cannot install packages into their environment (use
uvx --with <package> python instead).
As with tool installation, the target directory respects common variables like XDG_BIN_HOME and
can be overridden with a UV_PYTHON_BIN_DIR variable.
You can opt out of this behavior with uv python install --no-bin or UV_PYTHON_INSTALL_BIN=0.
See the documentation on installing Python executables for more details.
Register Python versions with the Windows Registry (#14625)
uv python install now registers the installed Python version with the Windows Registry as
specified by PEP 514. This allows using uv installed Python
versions via the py launcher. This behavior has been available under the --preview flag since
Jan 2025. This change should not be breaking, as
using the uv Python versions with py requires explicit opt in.
You can opt out of this behavior with uv python install --no-registry or
UV_PYTHON_INSTALL_REGISTRY=0.
Prompt before removing an existing directory in uv venv
(#14309)
Previously, uv venv would remove an existing virtual environment without confirmation. While
this is consistent with the behavior of project commands (e.g., uv sync), it's surprising to
users that are using imperative workflows (i.e., uv pip). Now, uv venv will prompt for
confirmation before removing an existing virtual environment. If not in an interactive context,
uv will still remove the virtual environment for backwards compatibility. However, this behavior
is likely to change in a future release.
The behavior for other commands (e.g., uv sync) is unchanged.
You can opt out of this behavior by setting UV_VENV_CLEAR=1 or passing the --clear flag.
Validate that discovered interpreters meet the Python preference (#7934)
uv allows opting out of its managed Python versions with the --no-managed-python and
python-preference options.
Previously, uv would not enforce this option for Python interpreters discovered on the PATH. For
example, if a symlink to a managed Python interpreter was created, uv would allow it to be used
even if --no-managed-python was provided. Now, uv ignores Python interpreters that do not match
the Python preference unless they are in an active virtual environment or are explicitly
requested, e.g., with --python /path/to/python3.13.
Similarly, uv would previously not invalidate existing project environments if they did not match the Python preference. Now, uv will invalidate and recreate project environments when the Python preference changes.
You can opt out of this behavior by providing the explicit path to the Python interpreter
providing --managed-python / --no-managed-python matching the interpreter you want.
Install dependencies without build systems when they are path sources
(#14413)
When working on a project, uv uses the presence of a build system to determine if it should be built and installed into the environment. However, when a project is a dependency of another project, it can be surprising for the dependency to be missing from the environment.
Previously, uv would not build and install dependencies with
path sources unless they
declared a build system or set tool.uv.package = true. Now, dependencies with path sources are
built and installed regardless of the presence of a build system. If a build system is not
present, the setuptools.build_meta:__legacy__ backend will be used (per
PEP 517).
You can opt out of this behavior by setting package = false in the source declaration, e.g.:
[tool.uv.sources]
foo = { path = "./foo", package = false }
Or, by setting tool.uv.package = false in the dependent pyproject.toml.
See the documentation on virtual dependencies for details.
Install dependencies without build systems when they are workspace members (#14663)
As described above for dependencies with path sources, uv previously would not build and install
workspace members that did not declare a build system. Now, uv will build and install workspace
members that are a dependency of another workspace member regardless of the presence of a build
system. The behavior is unchanged for workspace members that are not included in the
project.dependencies, project.optional-dependencies, or dependency-groups tables of another
workspace member.
You can opt out of this behavior by setting tool.uv.package = false in the workspace member's
pyproject.toml.
See the documentation on virtual dependencies for details.
Bump --python-platform linux to manylinux_2_28
(#14300)
uv allows performing
platform-specific resolution
for explicit targets and provides short aliases, e.g., linux, for common targets.
Previously, the default target for --python-platform linux was manylinux_2_17, which is
compatible with most Linux distributions from 2014 or newer. We now default to manylinux_2_28,
which is compatible with most Linux distributions from 2019 or newer. This change follows the lead
of other tools, such as cibuildwheel, which changed their default to manylinux_2_28 in
Mar 2025.
This change only affects users requesting a specific target platform. Otherwise, uv detects the
manylinux target from your local glibc version.
You can opt out of this behavior by using --python-platform x86_64-manylinux_2_17 instead.
Remove uv version fallback (#14161)
In Apr 2025, uv changed the uv version command to
an interface for viewing and updating the version of the current project. However, when outside a
project, uv version would continue to display uv's version for backwards compatibility. Now,
when used outside of a project, uv version will fail.
You cannot opt out of this behavior. Use uv self version instead.
Require --global for removal of the global Python pin
(#14169)
Previously, uv python pin --rm would allow you to remove the global Python pin without opt in.
Now, uv requires the --global flag to remove the global Python pin.
You cannot opt out of this behavior. Use the --global flag instead.
Support conflicting editable settings across groups (#14197)
Previously, uv would always treat a package as editable if any requirement requested it as
editable. However, this prevented users from declaring path sources that toggled the editable
setting across dependency groups. Now, uv allows declaring different editable values for
conflicting groups. However, if a project includes a path dependency twice, once with
editable = true and once without any editable annotation, those are now considered conflicting,
and uv will exit with an error.
You cannot opt out of this behavior. Use consistent editable settings or
mark groups as conflicting.
Make uv_build the default build backend in uv init
(#14661)
The uv build backend (uv_build) was
stabilized in uv 0.7.19. Now, it is the
default build backend for uv init --package and uv init --lib. Previously, hatchling was the
default build backend. A build backend is still not used without opt-in in uv init, but we
expect to change this in a future release.
You can opt out of this behavior with uv init --build-backend hatchling.
Set default UV_TOOL_BIN_DIR on Docker images
(#13391)
Previously, UV_TOOL_BIN_DIR was not set in Docker images which meant that uv tool install did
not install tools into a directory on the PATH without additional configuration. Now,
UV_TOOL_BIN_DIR is set to /usr/local/bin in all Docker derived images.
When the default image user is overridden (e.g. USER <UID>) with a less privileged user, this
may cause uv tool install to fail.
You can opt out of this behavior by setting an alternative UV_TOOL_BIN_DIR.
Update --check to return an exit code of 1
(#14167)
uv uses an exit code of 1 to indicate a "successful failure" and an exit code of 2 to indicate an "error".
Previously, uv lock --check and uv sync --check would exit with a code of 2 when the lockfile
or environment were outdated. Now, uv will exit with a code of 1.
You cannot opt out of this behavior.
Use an ephemeral environment for uv run --with invocations
(#14447)
When using uv run --with, uv layers the requirements requested using --with into another
virtual environment and caches it. Previously, uv would invoke the Python interpreter in this
layered environment. However, this allows poisoning the cached environment and introduces race
conditions for concurrent invocations. Now, uv will layer another empty virtual environment on
top of the cached environment and invoke the Python interpreter there. This should only cause
breakage in cases where the environment is being inspected at runtime.
You cannot opt out of this behavior.
Restructure the uv venv command output and exit codes
(#14546)
Previously, uv used miette to format the uv venv output. However, this was inconsistent with
most of the uv CLI. Now, the output is a little different and the exit code has switched from 1 to
2 for some error cases.
You cannot opt out of this behavior.
Default to --workspace when adding subdirectories
(#14529)
When using uv add to add a subdirectory in a workspace, uv now defaults to adding the target as
a workspace member.
You can opt out of this behavior by providing --no-workspace.
Add missing validations for disallowed uv.toml fields
(#14322)
uv does not allow some settings in the uv.toml. Previously, some settings were silently ignored
when present in the uv.toml. Now, uv will error.
You cannot opt out of this behavior. Use --no-config or remove the invalid settings.
HF_TOKEN (#14797)--config-settings-package to apply configuration settings at the package level
(#14573)python3.13t executables in uv venv
(#14764)python -m uv in interrupted with Ctrl-C on Windows
(#14715)--bounds formatting for uv_build bounds in uv init
(#14731)extras and dependency_groups markers in PEP 508 grammar
(#14753)extras and dependency_groups markers on uv pip install and uv pip sync
(#14755)uv self version when uv version cannot find a project
(#14738)[tool.uv] fields more precise
(#14325)uv sync with --quiet
(#14810)Cache-Control overrides to response, not request headers
(#14736)requires-python in pylock.toml (#14787)README variants in build backend
(#14762)pyvenv.cfg last
(#14808)dependency-metadata
(#14801)setup-uv after setup-python in Github Actions integration guide
(#14741)requires-python behavior are consistent with pip
(#14752)UV_INIT_BUILD_BACKEND (#14821)tls_built_in_root_certs for client (#14816)See the
python-build-standalone release notes
for more details.
--with versions over base environment versions
(#14863)uv_build reference documentation
(#14853)extra-build-dependencies
(#14735)exclude-newer dates via exclude-newer-package
(#14489)python vs python3
(#14970)environments and required-environments in uv.toml
(#14905)uv_build in projects documentation (#14968)UV_ prefix to installer environment variables
(#14964)uv from --build-backend options (#14939)uv run with a GitHub Gist (#15058)uv tool install
(#14014)extra-build-dependencies warnings for uv pip
(#15088)pylock warning
(#15089)python-preference = system when managed interpreters are on the PATH
(#15059)--system is used
(#15061)h2 upgrade (#15079)This release contains hardening measures to address differentials in behavior between uv and Python's built-in ZIP parser (CVE-2025-54368).
Prior to this release, attackers could construct ZIP files that would be extracted differently by pip, uv, and other tools. As a result, ZIPs could be constructed that would be considered harmless by (e.g.) scanners, but contain a malicious payload when extracted by uv. As of v0.8.6, uv now applies additional checks to reject such ZIPs.
Thanks to a triage effort with the Python Security Response Team and PyPI maintainers, we were able to determine that these differentials were not exploited via PyPI during the time they were present. The PyPI team has also implemented similar checks and now guards against these parsing differentials on upload.
Although the practical risk of exploitation is low, we take the hypothetical risk of parser differentials very seriously. Out of an abundance of caution, we have assigned this advisory a CVE identifier and have given it a "moderate" severity suggestion.
These changes have been validated against the top 15,000 PyPI packages; however, it's plausible that
a non-malicious ZIP could be falsely rejected with this additional hardening. As an escape hatch,
users who do encounter breaking changes can enable UV_INSECURE_NO_ZIP_VALIDATION to restore the
previous behavior. If you encounter such a rejection, please file an issue in uv and to the upstream
package.
For additional information, please refer to the following blog posts:
UV_HTTP_RETRIES in uv publish (#15106)UV_NO_EDITABLE where --no-editable is supported
(#15107)cargo-dist to add UV_INSTALLER_URL to PowerShell installer
(#15114)h2 again to avoid too_many_internal_resets errors
(#15111)pythonw when copying entry points in uv run
(#15134)tkagg backend (the default on Linux), Pillow's PIL.ImageTk library, and other
extension modules that need to use libtcl/libtk directly.See the
python-build-standalone release notes
for details.
uv.lock when using --isolated
(#15154)--prefix and --with installations in find_uv_bin
(#14184)find_uv_bin
(#14181)find_uv_bin (#14182)package-level conflicts in workspaces
(#14906)UV_DEV and UV_NO_DEV environment variables (for --dev and --no-dev)
(#15010)--require-hashes applied to build dependencies in uv pip install
(#15153)find_uv_bin
(#14191).) to list elements in Features docs page
(#15138)find_uv_bin compatibility with Python <3.10
(#15177)--reinstall flag to uv python upgrade
(#15194)uv python upgrade if they don't already exist
(#15192)aarch64
(#14399)extra-build-dependencies hint for any missing module on build failure
(#15252)reqwest clients to RegistryClient
(#15281)See the python-build-standalone release notes for details.
aarch64-pc-windows-msvc target for python-platform
(#15347)uv tool update-shell
(#15356)buildpack-deps:trixie, debian:trixie-slim, alpine:3.22
(#15351)match-runtime = true for dynamic packages
(#15292)uv cache clean instead of clear
(#15313)--no-install-* arguments to uv add (#15375)uv init
(#15377)uv format command (#15017)extra-build-dependencies if match-runtime is explicitly false
(#15420)triton to torch-backend manifest (#15405)uv_build wheel hashes (#15400)--upgrade-package on the command-line as overriding upgrade = false in configuration
(#15395)--python-platform to uv pip check (#15486)UV_ISOLATED
(#15428)--no-install-local option to uv sync, uv add and uv export
(#15328)uv pip CLI (#15453){version} on uv format failure
(#15527)uv format to prevent races
(#15551)--project in uv format (#15438)uv format in the project root (#15440)WHEEL and METADATA reads in installed distributions
(#15489)venv in current working directory
(#15537)uv publish checks
(#15545)uv venv
(#15538)CLICOLOR_FORCE=1 when calling build backends
(#15472)uvw.exe needs to be removed
(#15536)uv auth commands for credential management
(#15570)uv auth commands (#15636)uv tree --show-sizes to show package sizes
(#15531)--python-platform riscv64-unknown-linux
(#15630)--python-platform to uv run and uv tool
(#15515)uv publish --dry-run (#15638)extra-build-dependencies
(#15622)--editable to override editable = false annotations
(#15712)editable = false for workspace sources
(#15708)--with-requirements and --requirements
(#12763)match-runtime target is optional
(#15671)uv auth
(#15743)uv publish
(#15759)uv auth commands take a URL (#15664)Released on 2025-09-10.
PYX_API_URL when suggesting uv auth login on 401
(#15774)uv init --script
(#15747)Released on 2025-09-17.
uv init defaults for native build backend cache keys
(#15705)pyproject.toml target does not exist for dependency groups
(#15831)--no-clear to uv venv to disable removal prompts
(#15795)--only-group and --extra flags
(#15788)[project] to be missing from a pyproject.toml
(#14113)base and root as base environments
(#15682)uv_build is skipped
(#15898)_CONDA_ROOT to detect Conda base environments
(#15680)uv publish upload form
(#15794)uv sync
(#15881)tool.uv.dev-dependencies (#15469)native-auth feature
(#15872)uv sync --no-sources not switching from editable to registry installations
(#15234)@latest
(#15827)triton as a torch backend package (#15910)UV_INSECURE_NO_ZIP_VALIDATION=1 in duplicate header errors
(#15912)NO_PROXY support (#15816)requires-python
(#14282)Released on 2025-09-19.
See the python-build-standalone release notes for more details.
uv cache clean parallel process safe (#15888)platform_machine marker for win_arm64 platform tag
(#15921)Released on 2025-09-22.
--force flag for uv cache clean (#15992)freethreaded+debug Python downloads in uv python list
(#15985)uv run and uvx
(#15990)package level conflicts to the conflicting dependencies docs
(#15963)Released on 2025-09-23.
--refresh is provided
(#15994)Released on 2025-09-23.
astral-tokio-tar to 0.5.5 which
hardens tar archive extraction
(#16004)Released on 2025-10-03.
s390x on stable Rust compiler version
(#16082)UV_SKIP_WHEEL_FILENAME_CHECK to allow installing invalid wheels
(#16046)--no-sources
(#16094)--no-color on the CLI (#16044)uv pip tree output
(#16078)_CONDA_ROOT in reference (#16114)Released on 2025-10-06.
cache clean and prune when lock is held
(#16138)--force flag for uv cache prune (#16137)