How to configure workspace environments¶
Workspace environments allow you to manage multiple related packages within a single environment. This is useful for monorepos or projects with multiple interdependent packages.
Basic workspace configuration¶
Define workspace members in your environment configuration using the workspace.members option:
[tool.hatch.envs.default]
workspace.members = [
"packages/core",
"packages/utils",
"packages/cli"
]
[envs.default]
workspace.members = [
"packages/core",
"packages/utils",
"packages/cli"
]
Workspace members are automatically installed as editable packages in the environment.
Pattern matching¶
Use glob patterns to automatically discover workspace members:
[tool.hatch.envs.default]
workspace.members = ["packages/*"]
[envs.default]
workspace.members = ["packages/*"]
Excluding members¶
Exclude specific packages from workspace discovery:
[tool.hatch.envs.default]
workspace.members = ["packages/*"]
workspace.exclude = ["packages/experimental*"]
[envs.default]
workspace.members = ["packages/*"]
workspace.exclude = ["packages/experimental*"]
Member-specific features¶
Install specific optional dependencies for workspace members:
[tool.hatch.envs.default]
workspace.members = [
{path = "packages/core", features = ["dev"]},
{path = "packages/utils", features = ["test", "docs"]},
"packages/cli"
]
[envs.default]
workspace.members = [
{path = "packages/core", features = ["dev"]},
{path = "packages/utils", features = ["test", "docs"]},
"packages/cli"
]
Environment-specific workspaces¶
Different environments can include different workspace members:
[tool.hatch.envs.unit-tests]
workspace.members = ["packages/core", "packages/utils"]
scripts.test = "pytest tests/unit"
[tool.hatch.envs.integration-tests]
workspace.members = ["packages/*"]
scripts.test = "pytest tests/integration"
[tool.hatch.envs.docs]
workspace.members = [
{path = "packages/core", features = ["docs"]},
{path = "packages/utils", features = ["docs"]}
]
[envs.unit-tests]
workspace.members = ["packages/core", "packages/utils"]
scripts.test = "pytest tests/unit"
[envs.integration-tests]
workspace.members = ["packages/*"]
scripts.test = "pytest tests/integration"
[envs.docs]
workspace.members = [
{path = "packages/core", features = ["docs"]},
{path = "packages/utils", features = ["docs"]}
]
Building all members¶
Build an sdist and wheel for the workspace root and every workspace member with the build command's --all flag:
hatch build --all
The root project is built first and does not need to be listed as a member. If the top-level pyproject.toml does not define a project table and only serves as a container for workspace configuration, the root is skipped and only the members are built. Members are discovered from the selected environment's workspace.members option and artifacts are consolidated in the workspace root's dist directory by default, ready for e.g. twine upload dist/*. Pass a location argument to write artifacts elsewhere:
hatch build --all out/artifacts
Test matrices with workspaces¶
Combine workspace configuration with test matrices:
[[tool.hatch.envs.test.matrix]]
python = ["3.9", "3.10", "3.11", "3.12"]
[tool.hatch.envs.test]
workspace.members = ["packages/*"]
dependencies = ["pytest", "coverage"]
scripts.test = "pytest {args}"
[[tool.hatch.envs.test-core.matrix]]
python = ["3.9", "3.10", "3.11", "3.12"]
[tool.hatch.envs.test-core]
workspace.members = ["packages/core"]
dependencies = ["pytest", "coverage"]
scripts.test = "pytest packages/core/tests {args}"
[[envs.test.matrix]]
python = ["3.9", "3.10", "3.11", "3.12"]
[envs.test]
workspace.members = ["packages/*"]
dependencies = ["pytest", "coverage"]
scripts.test = "pytest {args}"
[[envs.test-core.matrix]]
python = ["3.9", "3.10", "3.11", "3.12"]
[envs.test-core]
workspace.members = ["packages/core"]
dependencies = ["pytest", "coverage"]
scripts.test = "pytest packages/core/tests {args}"
Performance optimization¶
Enable parallel dependency resolution for faster environment setup:
[tool.hatch.envs.default]
workspace.members = ["packages/*"]
workspace.parallel = true
[envs.default]
workspace.members = ["packages/*"]
workspace.parallel = true
Monorepo example¶
Complete configuration for a typical monorepo structure:
# Root pyproject.toml
[project]
name = "my-monorepo"
version = "1.0.0"
[tool.hatch.envs.default]
workspace.members = ["packages/*"]
workspace.exclude = ["packages/experimental*"]
workspace.parallel = true
dependencies = ["pytest", "black", "ruff"]
[tool.hatch.envs.test]
workspace.members = [
{path = "packages/core", features = ["test"]},
{path = "packages/utils", features = ["test"]},
"packages/cli"
]
dependencies = ["pytest", "coverage", "pytest-cov"]
scripts.test = "pytest --cov {args}"
[tool.hatch.envs.lint]
detached = true
workspace.members = ["packages/*"]
dependencies = ["ruff", "black", "mypy"]
scripts.check = ["ruff check .", "black --check .", "mypy ."]
scripts.fmt = ["ruff check --fix .", "black ."]
[[tool.hatch.envs.ci.matrix]]
python = ["3.9", "3.10", "3.11", "3.12"]
[tool.hatch.envs.ci]
template = "test"
workspace.parallel = false # Disable for CI stability
# Root pyproject.toml
[project]
name = "my-monorepo"
version = "1.0.0"
[envs.default]
workspace.members = ["packages/*"]
workspace.exclude = ["packages/experimental*"]
workspace.parallel = true
dependencies = ["pytest", "black", "ruff"]
[envs.test]
workspace.members = [
{path = "packages/core", features = ["test"]},
{path = "packages/utils", features = ["test"]},
"packages/cli"
]
dependencies = ["pytest", "coverage", "pytest-cov"]
scripts.test = "pytest --cov {args}"
[envs.lint]
detached = true
workspace.members = ["packages/*"]
dependencies = ["ruff", "black", "mypy"]
scripts.check = ["ruff check .", "black --check .", "mypy ."]
scripts.fmt = ["ruff check --fix .", "black ."]
[[envs.ci.matrix]]
python = ["3.9", "3.10", "3.11", "3.12"]
[envs.ci]
template = "test"
workspace.parallel = false # Disable for CI stability
Library with plugins example¶
Configuration for a library with optional plugins:
[tool.hatch.envs.default]
workspace.members = ["core"]
dependencies = ["pytest"]
[tool.hatch.envs.full]
workspace.members = [
"core",
"plugins/database",
"plugins/cache",
"plugins/auth"
]
dependencies = ["pytest", "pytest-asyncio"]
[tool.hatch.envs.database-only]
workspace.members = [
"core",
{path = "plugins/database", features = ["postgresql", "mysql"]}
]
[[tool.hatch.envs.plugin-test.matrix]]
plugin = ["database", "cache", "auth"]
[tool.hatch.envs.plugin-test]
workspace.members = [
"core",
"plugins/{matrix:plugin}"
]
scripts.test = "pytest plugins/{matrix:plugin}/tests {args}"
[envs.default]
workspace.members = ["core"]
dependencies = ["pytest"]
[envs.full]
workspace.members = [
"core",
"plugins/database",
"plugins/cache",
"plugins/auth"
]
dependencies = ["pytest", "pytest-asyncio"]
[envs.database-only]
workspace.members = [
"core",
{path = "plugins/database", features = ["postgresql", "mysql"]}
]
[[envs.plugin-test.matrix]]
plugin = ["database", "cache", "auth"]
[envs.plugin-test]
workspace.members = [
"core",
"plugins/{matrix:plugin}"
]
scripts.test = "pytest plugins/{matrix:plugin}/tests {args}"