Skip to content

/flags/uv/uv-sync-no-dev

uv sync --no-dev: install a project without its dev dependencies

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
command
uv sync
flag
--no-dev, --only-dev, --group, --no-group, --all-groups
default
the dev dependency group is included

uv sync --no-dev installs the project's runtime dependencies from uv.lock and leaves out the dev dependency group (test runners, linters, type checkers). Because uv sync is exact, packages from the dev group that are already in .venv are removed. It is the usual command for production images and deploys; add --locked so the build fails when uv.lock is out of date. uv run --no-dev applies the same selection to a single run.

Full sync and --no-dev

six is a runtime dependency, humanize a dev dependency:

bash
cat > pyproject.toml <<'EOF'
[project]
name = "demo"
version = "0.1.0"
requires-python = ">=3.9"
dependencies = ["six==1.16.0"]

[dependency-groups]
dev = ["humanize==4.11.0"]
EOF
uv sync -q
echo "--- uv sync"
uv pip list -q --format=freeze
uv sync -q --no-dev --locked
echo "--- uv sync --no-dev --locked"
uv pip list -q --format=freeze

Output

--- uv sync
humanize==4.11.0
six==1.16.0
--- uv sync --no-dev --locked
six==1.16.0

The second sync removed humanize from .venv and kept six. uv.lock still contains both, so the same lockfile serves development and production.

Group selection

OptionInstalls
(none)Project dependencies plus the dev group
--no-devProject dependencies only
--only-devOnly the dev group, not the project dependencies
--group lintAdditionally the lint group
--no-group devSame as --no-dev
--only-group docsOnly the docs group
--all-groupsEvery dependency group
--no-install-projectDependencies without the project itself (Docker layer caching)

Dockerfile

dockerfile
FROM python:3.13-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --locked --no-dev --no-install-project
COPY . .
RUN uv sync --locked --no-dev
CMD ["uv", "run", "--no-sync", "python", "-m", "app"]

The first sync installs only third-party dependencies, so the layer is cached until the lockfile changes. --no-sync stops uv run from re-checking the environment at start-up.

Pitfalls

  • --locked is the check that uv.lock matches pyproject.toml; without it a stale lock is silently updated during the build. The error it raises is explained in The lockfile needs to be updated.
  • A package the app imports at runtime but declared with uv add --dev works locally and fails in production with ModuleNotFoundError. Move it with uv add pkg and uv remove --dev pkg.
  • Old projects that list dev tools under [tool.uv] dev-dependencies are treated as the dev group as well; the newer [dependency-groups] table (PEP 735) is preferred.
  • uv run without --no-dev re-syncs the dev group back into .venv; in production containers use --no-dev or --no-sync on every uv run.

FAQ

Does uv sync --no-dev remove dev packages that are already installed?

Yes. uv sync is exact by default: packages that are not part of the requested set are removed from .venv. Add --inexact to keep extra packages.

How do I skip dev dependencies for every uv sync?

Set default-groups = [] under [tool.uv] in pyproject.toml, so no group is installed unless requested with --group, or keep --no-dev in the Dockerfile and deploy scripts.

What about other dependency groups such as lint or docs?

Only the dev group is synced by default. Other groups are installed with --group NAME or --all-groups, and --only-group NAME installs a single group without the project's main dependencies.

Sources