mrkeyoor.com_
Sat 08 Aug 20:59 UTC
PyPICLI & Toolingupdated 08 Aug 2026

hatch

Hatch is PyPA's all-in-one command-line project manager for Python packages. It creates and runs isolated environments, executes pytest and coverage across interpreter matrices, builds wheels and source distributions through Hatchling, updates project versions, manages Python installations, and publishes artifacts to package indexes. Most behavior is declared in pyproject.toml, so local commands and CI can share the same environments and scripts.

Verdict

Hatch is an excellent package-maintainer workbench when environment matrices and publishing are real needs. For a small application that mainly needs install, lock, and run, uv is usually easier to explain and operate.

API stability4/5Hatch keeps project configuration in namespaced tool.hatch tables and uses Python packaging standards for metadata and build-system declarations. Core commands such as run, env, build, version, and publish are established, but 1.17 adds substantial newer behavior around test orchestration and PEP 751 lockers. Plugin points offer compatibility at the cost of a wider configuration surface that can evolve.
Docs5/5The official site separates tutorials, how-to guides, configuration reference, plugin contracts, and a complete CLI reference. Current pages document lazy environment creation, editable installs, test matrices, coverage merging, publishing authentication, reproducible builds, and the exact pip and UV lock behavior. Cross-links are strong, though the number of concepts means a new user still has plenty to read.
Maintenance5/5Version 1.17.1 was uploaded in July 2026, the repository was pushed in August 2026, and CI covers Hatch, Hatchling, documentation, and releases. The project sits under the Python Packaging Authority and continues to add standards such as PEP 751. Its 422 open issues and pull requests are a real triage load, but the release and commit cadence show active ownership.
Ecosystem4/5Hatch works with standard pyproject metadata, uses Hatchling as a widely adopted build backend, supports pip and UV installers, and exposes plugins for builders, environments, metadata, version sources, lockers, and publishers. IDE and CI integration usually means running the same Hatch commands rather than special adapters. Conda and some specialized workflows still depend on third-party plugins.

Use it if

  • You publish Python packages and want environments, tests, builds, versioning, and releases configured in one pyproject.toml
  • You test several Python versions or feature combinations and want a declarative environment matrix
  • You already use Hatchling as the build backend and want its matching project CLI
  • You value reproducible builds and current PEP 751 environment lockfiles without stitching several tools together
Skip it if

Setup reality

Install Hatch as a standalone tool, not inside each project's runtime environment. A tool installer such as uv tool install hatch or pipx keeps Hatch's large dependency set away from your application; version 1.17.1 requires Python 3.10 or newer and pulls in Hatchling, virtualenv, uv, keyring, rich, HTTP tooling, and platform helpers. Hatch reads standard project metadata plus tool.hatch tables from pyproject.toml. Running hatch run or hatch test can create an environment on demand, resolve dependencies, and install your project in editable mode, so the first invocation is slower and may expose packaging mistakes before the command even starts. Interpreter matrices require the requested Python versions to be discoverable or installed through Hatch. Environments are cached outside the repository by default, which is convenient locally but easy to overlook when disk usage or stale state causes odd behavior; hatch env find, hatch env prune, and hatch env remove are the escape hatches. Current PEP 751 lockfiles are opt-in with locked = true. The default pip locker needs pip 25.1 or newer, while UV-backed environments use uv pip compile and sync. Publishing needs an index token through supported credentials or keyring and should consume artifacts you already inspected. Plugins make Hatch flexible, but each non-core environment or metadata hook becomes another piece your CI must install and trust.

Patterns

Create a packaged projectcreate-project

hatch new acme-widget
cd acme-widget
hatch run python -c "import acme_widget"

The first hatch run creates the default environment and installs the project in editable mode.

Define a test environmentdefine-task-environment

[tool.hatch.envs.test]
dependencies = [
  "pytest>=8",
  "pytest-cov",
]

[tool.hatch.envs.test.scripts]
run = "pytest {args:tests}"

Environment dependencies are separate from the package's runtime dependencies.

Run a named environment scriptrun-environment-script

hatch run test:run
hatch run test:run tests/test_api.py -q

Arguments after the script name populate the {args:...} placeholder from the pyproject script.

Run the built-in test command with coveragetest-with-coverage

hatch test --cover
hatch test --cover-xml --cover-xml-output coverage.xml

The test command uses pytest with selected plugins; coverage data files are created in the project root.

Test across Python versionstest-python-matrix

[[tool.hatch.envs.hatch-test.matrix]]
python = ["3.10", "3.11", "3.12", "3.13"]

# Run every compatible matrix environment
# hatch test --all

Requested interpreters must be discoverable. Without --all, Hatch selects one compatible test environment.

Generate a PEP 751 lockfilelock-environment

[tool.hatch.envs.test]
locked = true
dependencies = ["pytest>=8"]

# hatch env lock test
# hatch env lock test --check
# hatch -e test dep sync

The default pip locker needs pip 25.1 or newer; UV environments use UV's compile and sync path.

Build wheel and source distributionbuild-distributions

hatch build
python -m zipfile -l dist/acme_widget-1.2.0-py3-none-any.whl

Inspect file selection before publishing; Hatchling's wheel target decides what enters editable installs too.

Select a src-layout package explicitlyselect-wheel-package

[tool.hatch.build.targets.wheel]
packages = ["src/acme_widget"]

Explicit package selection prevents unrelated repository files from entering the wheel.

Read and bump a file-based versionbump-version

[project]
dynamic = ["version"]

[tool.hatch.version]
path = "src/acme_widget/__about__.py"

# hatch version
# hatch version minor

The default regex source expects a __version__ or VERSION string unless you configure a custom named version pattern.

Publish already-built artifactspublish-artifacts

hatch build
hatch publish dist/*

Only wheel and tar.gz artifacts are accepted. Configure the target repository and token before automating this command.

Alternatives

PackageRegistryPick it when
uvPyPIYou want very fast project environments and locking with fewer project-manager concepts
poetryPyPIYou want a strongly guided application and packaging workflow centered on a single lockfile
pdmPyPIYou want standards-focused dependency management, scripts, builds, and lockfiles in one project tool