ADR 016: Use Hatchling (build backend) and Hatch (project manager) together¶
Status¶
Accepted
Context¶
Python packaging involves two distinct concerns:
- Building distributions — creating sdist/wheel artifacts from source code.
- Managing the development workflow — creating environments, running tests, linting, formatting, publishing, etc.
These are separate tools that are often confused because they share a name:
| Tool | Role | Runs when |
|---|---|---|
| Hatchling | Build backend (like setuptools) | pip install ., python -m build, hatch build |
| Hatch | Project manager (like tox/nox + venv) | hatch run, hatch shell, hatch env, hatch build |
Key mental model¶
- Hatchling = "how to build the package"
- Hatch = "how to work on the project and trigger builds/tests/publishing"
Hatchling is declared in [build-system] and is used by any PEP 517 installer (pip, build, etc.) — it does not require Hatch to be installed. Hatch is a CLI tool that uses Hatchling under the hood for builds, but also manages environments, scripts, and version bumping.
Why use both¶
Using both gives you a single pyproject.toml that can define:
- Build backend (Hatchling) — via
[build-system] - What goes into distributions (include/exclude rules) — via
[tool.hatch.build.targets.*] - Version source/bumping rules — via
[tool.hatch.version] - Dev/test/lint environments and scripts (Hatch) — via
[tool.hatch.envs.*]
Alternatives Considered¶
| Option | Pros | Cons |
|---|---|---|
| setuptools + tox | Mature, widely known | Two config formats, verbose setup |
| setuptools + nox | Flexible (Python-based config) | Still two separate tools/configs |
| Hatchling + tox/nox | Hatchling for build, tox/nox for workflow | Mixes ecosystems unnecessarily |
| Flit | Simple, minimal config | No environment management, fewer features |
| PDM | PEP 582 support, lock files | Smaller community, different philosophy |
| Hatchling + Hatch | Single ecosystem, single config file | Less familiar to some developers |
Decision¶
Use Hatchling as the build backend and Hatch as the project manager. Both are configured in pyproject.toml:
# Build backend (Hatchling)
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# Build targets (Hatchling reads these)
# [tool.hatch.build.targets.sdist]
# [tool.hatch.build.targets.wheel]
# Project management (Hatch reads these)
[tool.hatch.envs.default]
[tool.hatch.envs.test]
Developers who don't want Hatch can still pip install -e ".[dev]" and run tools directly — Hatchling works with any PEP 517 installer.
Consequences¶
Positive¶
- One config file (
pyproject.toml) for both build and workflow configuration. - Hatch handles environment creation, dependency syncing, and script running.
- Test matrix support (
[[tool.hatch.envs.test.matrix]]) for multi-version testing. - No lock-in — Hatchling works independently of Hatch, so
pip install .always works.
Negative¶
- Developers must understand the Hatchling vs Hatch distinction.
- Hatch is less established than tox in some ecosystems.
Neutral¶
- The project also supports a manual
pip install -e ".[dev]"+ direct commands workflow for developers who prefer not to install Hatch.