uv is fantastic, but its package management UX is a mess
- title
- uv is fantastic, but its package management UX is a mess
- type
- summary
- summary
- Kevin Renskers' May 2026 case that uv's day-to-day project maintenance (outdated, upgrade, default version bounds) is behind Poetry and pnpm
- tags
- python, uv, astral, package-management, developer-experience
- sources
- loopwerk-uv-ux-mess
- created
- 2026-05-22
- updated
- 2026-05-22
Kevin Renskers writing at loopwerk.io on May 21, 2026: uv (the Rust-Python toolchain from Astral) has unambiguously won on speed and on collapsing the venv/pip/pyenv/pip-tools/poetry stack into one binary, but the routine project-maintenance commands โ what you run weekly, not on day one โ are weaker than what Poetry and pnpm shipped years ago. Three concrete UX gaps and one design default carry the argument.
No dedicated outdated command
The closest equivalent of pnpm outdated is:
$ uv tree --outdated --depth 1
Which prints the entire dependency tree rather than filtering to outdated rows. A real uv outdated is the asked-for fix.
Open-ended default version constraints
uv add pydantic writes "pydantic>=2.13.4" โ no upper bound. A subsequent uv lock --upgrade is then free to land pydantic 3.x or higher. pnpm defaults to ^1.23.4; Poetry to >=1.23.4,<2.0.0. Both at least pin a major-version line.
This is the same family of decision as Cargo's caret default and npm's ^ โ and most ecosystems sit on the side of "respect SemVer at the upper bound by default." Renskers reads uv's default as the riskier one to ship with, given how many projects don't routinely audit their lockfile diffs. See default-version-bound-constraints for the broader concept.
A preview --bounds major flag exists:
$ uv add pydantic --bounds major
which produces pydantic>=2.13.4,<3.0.0. Still opt-in, still preview-flagged.
Inconsistent upgrade verb
To upgrade everything:
$ uv lock --upgrade
Two complaints. First, the obvious verb at the top level would be uv update or uv upgrade. Second, the CLI is internally inconsistent: uv add and uv remove are top-level commands, but there is no symmetric uv lock --add or uv lock --remove, so why does upgrade live under uv lock?
Verbose per-package upgrades
$ uv lock --upgrade-package pydantic --upgrade-package httpx --upgrade-package uvicorn
Compare:
$ pnpm update pydantic httpx uvicorn
The flag repetition adds up across a half-dozen targeted upgrades.
Where this lands
The author isn't asking anyone to switch off uv โ speed and the unified toolchain are too valuable. The argument is narrower: uv is the new default for new projects but its maintenance commands haven't caught up to the prior generation, and the open-bound default in particular is the kind of decision that will quietly produce broken builds over years if it isn't addressed before uv's user base finishes consolidating on it.
It's worth reading alongside open-source-security-astral, which documents Astral's strong supply-chain practices for their own releases โ the contrast (rigorous for our releases, loose default for our downstream users' dependency constraints) is part of what makes this post stand out.
See also
- loopwerk-blog โ the source blog
- default-version-bound-constraints โ the concept of upper-bound version defaults across npm/Cargo/Poetry/uv
- open-source-security-astral โ Astral's own supply-chain posture; mentions uv's built-in cooldown support
- if-ai-writes-your-code-why-use-python โ Mitchem's piece notes the OpenAI/Astral acquisition (March 2026) and uv saving Codex ~1M minutes of compute per week โ context for why uv adoption is consolidating fast