{"owner":"pypa","repo":"hatch","hasSkills":true,"totalSkillsCount":27,"totalTokensCount":10471,"categories":["anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["docs/how-to/plugins/testing-builds.md","docs/plugins/about.md","docs/plugins/build-hook/custom.md","docs/plugins/build-hook/reference.md","docs/plugins/build-hook/version.md","docs/plugins/builder/binary.md","docs/plugins/builder/custom.md","docs/plugins/builder/reference.md","docs/plugins/builder/sdist.md","docs/plugins/builder/wheel.md","docs/plugins/environment-collector/custom.md","docs/plugins/environment-collector/default.md","docs/plugins/environment-collector/reference.md","docs/plugins/environment/reference.md","docs/plugins/environment/virtual.md","docs/plugins/locker.md","docs/plugins/metadata-hook/custom.md","docs/plugins/metadata-hook/reference.md","docs/plugins/publisher/package-index.md","docs/plugins/publisher/reference.md","docs/plugins/utilities.md","docs/plugins/version-scheme/reference.md","docs/plugins/version-scheme/standard.md","docs/plugins/version-source/code.md","docs/plugins/version-source/env.md","docs/plugins/version-source/reference.md","docs/plugins/version-source/regex.md"],"skills":{"docs/how-to/plugins/testing-builds.md":"# Testing build plugins\n\n-----\n\nFor testing [Hatchling plugins](../../plugins/about.md#hatchling), you'll usually want to generate a project to execute builds as a real user would. For example, as a minimal [pytest](https://github.com/pytest-dev/pytest) fixture:\n\n```python\nfrom pathlib import Path\n\nimport pytest\n\n\n@pytest.fixture\ndef new_project(tmp_path):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {Path.cwd().as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n```\n\nThe issue with this is that after the first test session, the project will be forever cached by pip based on the file path. Therefore, subsequent tests runs will never use updated code.\n\nTo invalidate the cache, copy your code to a new path for every test session:\n\n```python\nimport shutil\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\n\nimport pytest\n\n\n@pytest.fixture(scope='session')\ndef plugin_dir():\n    with TemporaryDirectory() as d:\n        directory = Path(d, 'plugin')\n        shutil.copytree(\n            Path.cwd(), directory, ignore=shutil.ignore_patterns('.git')\n        )\n\n        yield directory.resolve()\n\n\n@pytest.fixture\ndef new_project(tmp_path, plugin_dir):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {plugin_dir.as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n```\n\n!!! note\n    This example chooses to ignore copying `.git` for performance reasons. You may want to ignore more patterns, or copy only specific paths like [this plugin](https://github.com/hynek/hatch-fancy-pypi-readme/blob/main/tests/conftest.py) does.\n","docs/plugins/about.md":"# Plugins\n\n-----\n\nHatch utilizes [pluggy](https://github.com/pytest-dev/pluggy) for its plugin functionality.\n\n## Overview\n\nAll plugins provide registration hooks that return one or more classes that inherit from a particular [type](#types) interface.\n\nEach registration hook must be decorated by Hatch's hook marker. For example, if you wanted to create a new kind of environment you could do:\n\n```python tab=\"hooks.py\"\nfrom hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialEnvironment\n\n\n@hookimpl\ndef hatch_register_environment():\n    return SpecialEnvironment\n```\n\nThe hooks can return a single class or a list of classes.\n\nEvery class must define an attribute called `PLUGIN_NAME` that users will select when they wish to use the plugin. So in the example above, the class might be defined like:\n\n```python tab=\"plugin.py\"\n...\nclass SpecialEnvironment(...):\n    PLUGIN_NAME = 'special'\n    ...\n```\n\n## Project configuration\n\n### Naming\n\nIt is recommended that plugin project names are prefixed with `hatch-`. For example, if you wanted to make a plugin that provides some functionality for a product named `foo` you might do:\n\n```toml tab=\"pyproject.toml\"\n[project]\nname = \"hatch-foo\"\n```\n\n### Discovery\n\nYou'll need to define your project as a [Python plugin](../config/metadata.md#plugins) for Hatch:\n\n```toml tab=\"pyproject.toml\"\n[project.entry-points.hatch]\nfoo = \"pkg.hooks\"\n```\n\nThe name of the plugin should be the project name (excluding any `hatch-` prefix) and the path should represent the module that contains the registration hooks.\n\n### Classifier\n\nAdd [`Framework :: Hatch`](https://pypi.org/search/?c=Framework+%3A%3A+Hatch) to your project's [classifiers](../config/metadata.md#classifiers) to make it easy to search for Hatch plugins:\n\n```toml tab=\"pyproject.toml\"\n[project]\nclassifiers = [\n  ...\n  \"Framework :: Hatch\",\n  ...\n]\n```\n\n## Types\n\n### Hatchling\n\nThese are all involved in building projects and therefore any defined dependencies are automatically installed in each build environment.\n\n- [Builder](builder/reference.md)\n- [Build hook](build-hook/reference.md)\n- [Metadata hook](metadata-hook/reference.md)\n- [Version source](version-source/reference.md)\n- [Version scheme](version-scheme/reference.md)\n\n### Hatch\n\nThese must be installed in the same environment as Hatch itself.\n\n- [Environment](environment/reference.md)\n- [Environment collector](environment-collector/reference.md)\n- [Dependency locker](locker.md)\n- [Publisher](publisher/reference.md)\n","docs/plugins/build-hook/custom.md":"# Custom build hook\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [BuildHookInterface](reference.md#hatchling.builders.hooks.plugin.interface.BuildHookInterface).\n\n## Configuration\n\nThe build hook plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.build.hooks.custom]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.builders.hooks.plugin.interface import BuildHookInterface\n\n\nclass CustomBuildHook(BuildHookInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_build_hook` that returns the desired build hook.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.builders.hooks.plugin.interface.BuildHookInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","docs/plugins/build-hook/reference.md":"# Build hook plugins\n\n-----\n\nA build hook provides code that will be executed at various stages of the build process. See the documentation for [build hook configuration](../../config/build.md#build-hooks).\n\n## Known third-party\n\n- [hatch-argparse-manpage](https://github.com/damonlynch/hatch-argparse-manpage) - generate man pages for [argparse](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser)-based CLIs\n- [hatch-autorun](https://github.com/ofek/hatch-autorun) - used to inject code into an installation that will automatically run before the first import\n- [hatch-build-scripts](https://github.com/rmorshea/hatch-build-scripts) - run arbitrary shell commands that create artifacts\n- [hatch-cython](https://github.com/joshua-auchincloss/hatch-cython) - build [Cython](https://github.com/cython/cython) extensions\n- [hatch-gettext](https://github.com/damonlynch/hatch-gettext) - compiles multi-lingual messages with GNU `gettext` tools\n- [hatch-jupyter-builder](https://github.com/jupyterlab/hatch-jupyter-builder) - used for packages in the Project Jupyter ecosystem\n- [hatch-mypyc](https://github.com/ofek/hatch-mypyc) - compiles code with [Mypyc](https://github.com/mypyc/mypyc)\n- [hatch-odoo](https://github.com/acsone/hatch-odoo) - package Odoo add-ons into the appropriate namespace\n- [hatch-project-name](https://github.com/valentinoli/hatch-project-name/) - writes the project name to a file\n- [scikit-build-core](https://github.com/scikit-build/scikit-build-core) - build extension modules with CMake\n\n## Overview\n\nBuild hooks run for every selected [version](../../config/build.md#versions) of build targets.\n\nThe [initialization](#hatchling.builders.hooks.plugin.interface.BuildHookInterface.initialize) stage occurs immediately before each build and the [finalization](#hatchling.builders.hooks.plugin.interface.BuildHookInterface.finalize) stage occurs immediately after. Each stage has the opportunity to view or modify [build data](#build-data).\n\n## Build data\n\nBuild data is a simple mapping whose contents can influence the behavior of builds. Which fields exist and are recognized depends on each build target.\n\nThe following fields are always present and recognized by the build system itself:\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `artifacts` | `#!python list[str]` | This is a list of extra [`artifact` patterns](../../config/build.md#artifacts) and should generally only be appended to |\n| `force_include` | `#!python dict[str, str]` | This is a mapping of extra [forced inclusion paths](../../config/build.md#forced-inclusion), with this mapping taking precedence in case of conflicts |\n| `build_hooks` | `#!python tuple[str, ...]` | This is an immutable sequence of the names of the configured build hooks and matches the order in which they run |\n\n!!! attention\n    While user-facing TOML options are hyphenated, build data fields should be named with underscores to allow plugins to use them as valid Python identifiers.\n\n## Notes\n\nIn some cases it may be necessary to use `force_include` rather than `artifacts`. For example, say that you want to install a `lib.so` directly at the root of `site-packages` and a project defines a [package](../../config/build.md#packages) `src/foo`. If you create `src/lib.so`, there will never be a match because the directory traversal starts at `src/foo` rather than `src`. In that case you must do either:\n\n```python\nbuild_data['force_include']['src/lib.so'] = 'src/lib.so'\n```\n\nor\n\n```python\nbuild_data['force_include']['/absolute/path/to/src/lib.so'] = 'src/lib.so'\n```\n\n::: hatchling.builders.hooks.plugin.interface.BuildHookInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - config\n      - build_config\n      - target_name\n      - directory\n      - dependencies\n      - clean\n      - initialize\n      - finalize\n","docs/plugins/build-hook/version.md":"# Version build hook\n\n-----\n\nThis writes the project's version to a file.\n\n## Configuration\n\nThe build hook plugin name is `version`.\n\n```toml config-example\n[tool.hatch.build.hooks.version]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.version]\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to the desired file |\n| `template` | A string representing the entire contents of `path` that will be formatted with a `version` variable |\n| `pattern` | Rather than updating the entire file, a regular expression may be used that has a named group called `version` that represents the version. If set to `true`, a pattern will be used that looks for a variable named `__version__` or `VERSION` that is set to a string containing the version, optionally prefixed with the lowercase letter `v`. |\n","docs/plugins/builder/binary.md":"# Binary builder\n\n-----\n\nThis uses [PyApp](https://github.com/ofek/pyapp) to build an application that is able to bootstrap itself at runtime.\n\n!!! note\n    This requires an installation of [Rust](https://www.rust-lang.org).\n\n## Configuration\n\nThe builder plugin name is `binary`.\n\n```toml config-example\n[tool.hatch.build.targets.binary]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `scripts` | all defined | An array of defined [script](../../config/metadata.md#cli) names to limit what gets built |\n| `python-version` | latest compatible Python minor version | The [Python version ID](https://ofek.dev/pyapp/latest/config/#known) to use |\n| `pyapp-version` | | The version of PyApp to use |\n\n## Build behavior\n\nIf any [scripts](../../config/metadata.md#cli) are defined then each one will be built (limited by the `scripts` option). Otherwise, a single executable will be built based on the project name assuming there is an equivalently named module with a `__main__.py` file.\n\nEvery executable will be built inside an `app` directory in the [output directory](../../config/build.md#output-directory).\n\nIf the `CARGO` environment variable is set then that path will be used as the executable for performing builds.\n\nIf the [`CARGO_BUILD_TARGET`](https://doc.rust-lang.org/cargo/reference/config.html#buildtarget) environment variable is set then its value will be appended to the file name stems.\n\nIf the `PYAPP_REPO` environment variable is set then a local build will be performed inside that directory rather than installing from [crates.io](https://crates.io). Note that this is [required](https://github.com/cross-rs/cross/issues/1215) if the `CARGO` environment variable refers to [cross](https://github.com/cross-rs/cross).\n","docs/plugins/builder/custom.md":"# Custom builder\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [BuilderInterface](reference.md#hatchling.builders.plugin.interface.BuilderInterface).\n\n## Configuration\n\nThe builder plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.build.targets.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.builders.plugin.interface import BuilderInterface\n\n\nclass CustomBuilder(BuilderInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_builder` that returns the desired builder.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.builders.plugin.interface.BuilderInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","docs/plugins/builder/reference.md":"# Builder plugins\n\n-----\n\nSee the documentation for [build configuration](../../config/build.md).\n\n## Known third-party\n\n- [hatch-aws](https://github.com/aka-raccoon/hatch-aws) - used for building AWS Lambda functions with SAM\n- [hatch-zipped-directory](https://github.com/dairiki/hatch-zipped-directory) - used for building ZIP archives for installation into various foreign package installation systems\n\n::: hatchling.builders.plugin.interface.BuilderInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - build_config\n      - target_config\n      - config\n      - get_config_class\n      - get_version_api\n      - get_default_versions\n      - clean\n      - recurse_included_files\n      - get_default_build_data\n","docs/plugins/builder/sdist.md":"# Source distribution builder\n\n-----\n\nA source distribution, or `sdist`, is an archive of Python \"source code\". Although largely unspecified, by convention it should include everything that is required to build a [wheel](wheel.md) without making network requests.\n\n## Configuration\n\nThe builder plugin name is `sdist`.\n\n```toml config-example\n[tool.hatch.build.targets.sdist]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `core-metadata-version` | `\"2.4\"` | The version of [core metadata](https://packaging.python.org/specifications/core-metadata/) to use |\n| `strict-naming` | `true` | Whether or not file names should contain the normalized version of the project name |\n| `support-legacy` | `false` | Whether or not to include a `setup.py` file to support legacy installation mechanisms |\n\n## Versions\n\n| Version | Description |\n| --- | --- |\n| `standard` (default) | The latest conventional format |\n\n## Default file selection\n\nWhen the user has not set any [file selection](../../config/build.md#file-selection) options, all files that are not [ignored by your VCS](../../config/build.md#vcs) will be included.\n\n!!! note\n    The following files are always included and cannot be excluded:\n\n    - `/pyproject.toml`\n    - `/hatch.toml`\n    - `/hatch_build.py`\n    - `/.gitignore` or `/.hgignore`\n    - Any defined [`readme`](../../config/metadata.md#readme) file\n    - All defined [`license-files`](../../config/metadata.md#license)\n\n## Reproducibility\n\n[Reproducible builds](../../config/build.md#reproducible-builds) are supported.\n\n## Build data\n\nThis is data that can be modified by [build hooks](../build-hook/reference.md).\n\n| Data | Default | Description |\n| --- | --- | --- |\n| `dependencies` | | Extra [project dependencies](../../config/metadata.md#required) |\n","docs/plugins/builder/wheel.md":"# Wheel builder\n\n-----\n\nA [wheel](https://packaging.python.org/specifications/binary-distribution-format/) is a binary distribution of a Python package that can be installed directly into an environment.\n\n## Configuration\n\nThe builder plugin name is `wheel`.\n\n```toml config-example\n[tool.hatch.build.targets.wheel]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `core-metadata-version` | `\"2.4\"` | The version of [core metadata](https://packaging.python.org/specifications/core-metadata/) to use |\n| `shared-data` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to the `data` subdirectory within the standard [data directory](https://packaging.python.org/en/latest/specifications/binary-distribution-format/#the-data-directory) that will be installed globally in a given Python environment, usually under `#!python sys.prefix` |\n| `shared-scripts` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to the `scripts` subdirectory within the standard [data directory](https://packaging.python.org/en/latest/specifications/binary-distribution-format/#the-data-directory) that will be installed in a given Python environment, usually under `Scripts` on Windows or `bin` otherwise, and would normally be available on PATH |\n| `extra-metadata` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to extra [metadata](https://peps.python.org/pep-0427/#the-dist-info-directory) that will be shipped in a directory named `extra_metadata` |\n| `strict-naming` | `true` | Whether or not file names should contain the normalized version of the project name |\n| `macos-max-compat` | `false` | Whether or not on macOS, when build hooks have set the `infer_tag` [build data](#build-data), the wheel name should signal broad support rather than specific versions for newer SDK versions.<br><br>Note: This option will eventually be removed. |\n| `bypass-selection` | `false` | Whether or not to suppress the error when one has not defined any file selection options and all heuristics have failed to determine what to ship |\n| `sbom-files` | | A list of paths to [Software Bill of Materials](https://peps.python.org/pep-0770/) files that will be included in the `.dist-info/sboms/` directory of the wheel |\n\n!!! note\n    Many build frontends will build the wheel from a source distribution. This is the recommended approach, but it means you need to ensure the SBOM files passed to `sbom-files` are also [included in the source distribution](https://hatch.pypa.io/latest/config/build/#file-selection).\n\n## Versions\n\n| Version | Description |\n| --- | --- |\n| `standard` (default) | The latest standardized format |\n| `editable` | A wheel that only ships `.pth` files or import hooks for real-time development |\n\n## Default file selection\n\nWhen the user has not set any [file selection](../../config/build.md#file-selection) options, the [project name](../../config/metadata.md#name) will be used to determine the package to ship in the following heuristic order:\n\n1. `<NAME>/__init__.py`\n2. `src/<NAME>/__init__.py`\n3. `<NAME>.py`\n4. `<NAMESPACE>/<NAME>/__init__.py`\n\nIf none of these heuristics are satisfied, an error will be raised.\n\n## Reproducibility\n\n[Reproducible builds](../../config/build.md#reproducible-builds) are supported.\n\n## Build data\n\nThis is data that can be modified by [build hooks](../build-hook/reference.md).\n\n| Data | Default | Description |\n| --- | --- | --- |\n| `tag` | | The full [tag](https://peps.python.org/pep-0425/) part of the filename (e.g. `py3-none-any`), defaulting to a cross-platform wheel with the supported major versions of Python based on [project metadata](../../config/metadata.md#python-support) |\n| `infer_tag` | `#!python False` | When `tag` is not set, this may be enabled to use the one most specific to the platform, Python interpreter, and ABI |\n| `pure_python` | `#!python True` | Whether or not to write metadata indicating that the package does not contain any platform-specific files |\n| `dependencies` | | Extra [project dependencies](../../config/metadata.md#required) |\n| `shared_data` | | Additional [`shared-data`](#options) entries, which take precedence in case of conflicts |\n| `shared_scripts` | | Additional [`shared-scripts`](#options) entries, which take precedence in case of conflicts |\n| `extra_metadata` | | Additional [`extra-metadata`](#options) entries, which take precedence in case of conflicts |\n| `force_include_editable` | | Similar to the [`force_include` option](../build-hook/reference.md#build-data) but specifically for the `editable` [version](#versions) and takes precedence |\n| `sbom_files` | | This is a list of the sbom files that should be included under `.dist-info/sboms`. |\n","docs/plugins/environment-collector/custom.md":"# Custom environment collector\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [EnvironmentCollectorInterface](reference.md#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface).\n\n## Configuration\n\nThe environment collector plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.env.collectors.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_plugins.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_plugins.py\"\n    from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface\n\n\n    class CustomEnvironmentCollector(EnvironmentCollectorInterface):\n        ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_environment_collector` that returns the desired environment collector.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","docs/plugins/environment-collector/default.md":"# Default environment collector\n\n-----\n\nThis adds the `default` environment with [type](../../config/environment/overview.md#type) set to [virtual](../environment/virtual.md) and will always be applied.\n\n## Configuration\n\nThe environment collector plugin name is `default`.\n\n```toml config-example\n[tool.hatch.env.collectors.default]\n```\n\n## Options\n\nThere are no options available currently.\n","docs/plugins/environment-collector/reference.md":"# Environment collector plugins\n\n-----\n\nEnvironment collectors allow for dynamically modifying environments or adding environments beyond those defined in config. Users can override default values provided by each environment.\n\n## Known third-party\n\n- [hatch-mkdocs](https://github.com/mkdocs/hatch-mkdocs) - integrate [MkDocs](https://github.com/mkdocs/mkdocs) and infer dependencies into an env\n\n## Installation\n\nAny required environment collectors that are not built-in must be manually installed alongside Hatch or listed in the `tool.hatch.env.requires` array for automatic management:\n\n```toml config-example\n[tool.hatch.env]\nrequires = [\n  \"...\",\n]\n```\n\n::: hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - get_initial_config\n      - finalize_config\n      - finalize_environments\n","docs/plugins/environment/reference.md":"# Environment plugins\n\n-----\n\nSee the documentation for [environment configuration](../../config/environment/overview.md).\n\n## Known third-party\n\n- [hatch-conda](https://github.com/OldGrumpyViking/hatch-conda) - environments backed by Conda/Mamba\n- [hatch-containers](https://github.com/ofek/hatch-containers) - environments run inside containers\n- [hatch-pip-compile](https://github.com/juftin/hatch-pip-compile) - use [pip-compile](https://github.com/jazzband/pip-tools) to manage project dependencies and lockfiles\n- [hatch-pip-deepfreeze](https://github.com/sbidoul/hatch-pip-deepfreeze) - [virtual](virtual.md) environments with dependency locking by [pip-deepfreeze](https://github.com/sbidoul/pip-deepfreeze)\n\n## Installation\n\nAny required environment types that are not built-in must be manually installed alongside Hatch or listed in the `tool.hatch.env.requires` array for automatic management:\n\n```toml config-example\n[tool.hatch.env]\nrequires = [\n  \"...\",\n]\n```\n\n## Life cycle\n\nWhenever an environment is used, the following logic is performed:\n\n::: hatch.project.core.Project.prepare_environment\n    options:\n      show_root_heading: false\n      show_root_toc_entry: false\n\n## Build environments\n\nAll environment types should [offer support](#hatch.env.plugin.interface.EnvironmentInterface.fs_context) for synchronized storage between the local file system and the environment. This functionality is used in the following scenarios:\n\n- the [`build`](../../cli/reference.md#hatch-build) command\n- commands that read dependencies, like [`dep hash`](../../cli/reference.md#hatch-dep-hash), if any [project dependencies](../../config/metadata.md#dependencies) are [set dynamically](../../config/metadata.md#dynamic)\n\n::: hatch.env.plugin.interface.EnvironmentInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - find\n      - create\n      - remove\n      - exists\n      - install_project\n      - install_project_dev_mode\n      - dependencies_in_sync\n      - sync_dependencies\n      - dependency_hash\n      - project_dependencies\n      - project_root\n      - sep\n      - pathsep\n      - fs_context\n      - activate\n      - deactivate\n      - app_status_creation\n      - app_status_pre_installation\n      - app_status_post_installation\n      - app_status_project_installation\n      - app_status_dependency_state_check\n      - app_status_dependency_installation_check\n      - app_status_dependency_synchronization\n      - app\n      - root\n      - name\n      - data_directory\n      - isolated_data_directory\n      - config\n      - platform\n      - environment_dependencies\n      - dependencies\n      - sources\n      - get_source_install_args\n      - env_vars\n      - env_include\n      - env_exclude\n      - platforms\n      - skip_install\n      - dev_mode\n      - description\n      - command_context\n      - enter_shell\n      - run_shell_command\n      - resolve_commands\n      - get_env_vars\n      - apply_features\n      - construct_pip_install_command\n      - join_command_args\n      - check_compatibility\n      - get_option_types\n      - get_env_var_option\n      - get_context\n\n## Dependency lockers\n\n**Dependency lockers** are implemented: register classes with `hatch_register_locker` (see [Dependency locker plugins](../locker.md)). They stay **decoupled** from environment plugins—no subclassing [`EnvironmentInterface`](#hatch.env.plugin.interface.EnvironmentInterface) just to change locking—and call the environment’s **public API** (for example [`command_context`](#hatch.env.plugin.interface.EnvironmentInterface.command_context) and [`platform`](../utilities.md)).\n\nFor moving artifacts between the workspace and the environment, custom lockers should prefer [`fs_context`](#hatch.env.plugin.interface.EnvironmentInterface.fs_context) and [`FileSystemContext`](../utilities.md#hatch.env.plugin.interface.FileSystemContext) over ad hoc I/O.\n\nEnd-user commands: [How to use lockfiles](../../how-to/environment/lockfiles.md).\n","docs/plugins/environment/virtual.md":"# Virtual environment\n\n-----\n\nThis uses virtual environments backed by [virtualenv](https://github.com/pypa/virtualenv) or [UV](https://github.com/astral-sh/uv).\n\n## Configuration\n\nThe environment plugin name is `virtual`.\n\n```toml config-example\n[tool.hatch.envs.<ENV_NAME>]\ntype = \"virtual\"\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `python` | | The version of Python to find on your system and subsequently use to create the environment, defaulting to the `HATCH_PYTHON` environment variable, followed by the [normal resolution logic](#python-resolution). Setting the `HATCH_PYTHON` environment variable to `self` will force the use of the Python executable Hatch is running on. For more information, see the [documentation](https://virtualenv.pypa.io/en/latest/user_guide.html#python-discovery). |\n| `python-sources` | `['external', 'internal']` | This may be set to an array of strings that are either the literal `internal` or `external`. External considers only Python executables that are already on `PATH`. Internal considers only [internally managed Python distributions](#internal-distributions). |\n| `path` | | An explicit path to the virtual environment. The path may be absolute or relative to the project root. Any environments that [inherit](../../config/environment/overview.md#inheritance) this option will also use this path. The environment variable `HATCH_ENV_TYPE_VIRTUAL_PATH` may be used, which will take precedence. |\n| `system-packages` | `false` | Whether or not to give the virtual environment access to the system `site-packages` directory |\n| `installer` | `pip` | When set to `uv`, [UV](https://github.com/astral-sh/uv) will be used in place of virtualenv & pip for virtual environment creation and dependency management, respectively. If you intend to provide UV yourself, you may set the `HATCH_ENV_TYPE_VIRTUAL_UV_PATH` environment variable which should be the absolute path to a UV binary. This environment variable implicitly sets the `installer` option to `uv` (if unset). |\n\n## Location\n\nThe [location](../../cli/reference.md#hatch-env-find) of environments is determined in the following heuristic order:\n\n1. The `path` option\n2. A directory named after the environment within the configured `virtual` [environment directory](../../config/hatch.md#environments) if the directory resides somewhere within the project root or if it is set to a `.virtualenvs` directory within the user's home directory\n3. Otherwise, environments are stored within the configured `virtual` [environment directory](../../config/hatch.md#environments) in a deeply nested structure in order to support multiple projects\n\nAdditionally, when the `path` option is not used, the name of the directory for the `default` environment will be the normalized project name to provide a more meaningful default [shell](../../cli/reference.md#hatch-shell) prompt.\n\n## Python resolution\n\nVirtual environments necessarily require a parent installation of Python. The following rules determine how the parent is resolved.\n\nThe Python choice is determined by the [`python` option](#options) followed by the `HATCH_PYTHON` environment variable. If the choice is via the environment variable, then resolution stops and that path is used unconditionally.\n\nThe resolvers will be based on the [`python-sources` option](#options) and all resolved interpreters will ensure compatibility with the project's defined [Python support](../../config/metadata.md#python-support).\n\nIf a Python version has been chosen then each resolver will try to find an interpreter that satisfies that version.\n\nIf no version has been chosen, then each resolver will try to find a version that matches the version of Python that Hatch is currently running on. If not found then each resolver will try to find the highest compatible version.\n\n!!! note\n    Some external Python paths are considered unstable and are ignored during resolution. For example, if Hatch is installed via Homebrew then `sys.executable` will be ignored because the interpreter could change or be removed at any time.\n\n!!! note\n    When resolution finds a match using an [internally managed distribution](#internal-distributions) and an update is available, the latest distribution will automatically be downloaded before environment creation.\n\n## Internal distributions\n\nThe following options are recognized for internal Python resolution.\n\n!!! tip\n    You can set custom sources for distributions by setting the `HATCH_PYTHON_SOURCE_<NAME>` environment variable where `<NAME>` is the uppercased version of the distribution name with periods replaced by underscores e.g. `HATCH_PYTHON_SOURCE_PYPY3_10`.\n\n### CPython\n\n| NAME |\n| --- |\n| `3.7` |\n| `3.8` |\n| `3.9` |\n| `3.10` |\n| `3.11` |\n| `3.12` |\n| `3.13` |\n| `3.14` |\n| `3.15` |\n\nThe source of distributions is the [python-build-standalone](https://github.com/indygreg/python-build-standalone) project.\n\nSome distributions have [variants](https://gregoryszorc.com/docs/python-build-standalone/main/running.html) that may be configured with environment variables. Options may be combined.\n\n| Option | Platforms | Allowed values |\n| --- | --- | --- |\n| `HATCH_PYTHON_VARIANT_CPU` | <ul><li>Linux</li></ul> | <ul><li><code>v1</code></li><li><code>v2</code></li><li><code>v3</code> (default)</li><li><code>v4</code></li></ul> |\n| `HATCH_PYTHON_VARIANT_GIL` | <ul><li>Linux</li><li>Windows</li><li>macOS</li></ul> | <ul><li><code>freethreaded</code></li></ul> |\n\n### PyPy\n\n| NAME |\n| --- |\n| `pypy2.7` |\n| `pypy3.9` |\n| `pypy3.10` |\n| `pypy3.11` |\n\nThe source of distributions is the [PyPy](https://www.pypy.org) project.\n\n## Troubleshooting\n\n### macOS SIP\n\nIf you need to set linker environment variables like those starting with `DYLD_` or `LD_`, any executable secured by [System Integrity Protection](https://en.wikipedia.org/wiki/System_Integrity_Protection) that is invoked when [running commands](../../environment.md#command-execution) will not see those environment variable modifications as macOS strips those.\n\nHatch interprets such commands as shell commands but deliberately ignores such paths to protected shells. This workaround suffices for the majority of use cases but there are 2 situations in which it may not:\n\n1. There are no unprotected `sh`, `bash`, `zsh`, nor `fish` executables found along PATH.\n2. The desired executable is a project's [script](../../config/metadata.md#cli), and the [location](#location) of environments contains spaces or is longer than 124[^1] characters. In this case `pip` and other installers will create such an entry point with a shebang pointing to `/bin/sh` (which is protected) to avoid shebang limitations. Rather than changing the location, you could invoke the script as e.g. `python -m pytest` (if the project supports that method of invocation by shipping a `__main__.py`).\n\n[^1]: The shebang length limit is [usually](https://web.archive.org/web/20221231220856/https://www.in-ulm.de/~mascheck/various/shebang/#length) 127 but 3 characters surround the executable path: `#!<EXE_PATH>\\n`\n","docs/plugins/locker.md":"# Dependency locker plugins\n\n-----\n\nHatch selects a **locker** plugin to **generate** PEP 751 lockfiles, verify they are **in sync** with the configured dependency inputs, and **apply** them when syncing a `locked` environment. Built-in lockers are **`uv`** and **`pip`**, matching the [virtual environment installer](../how-to/environment/select-installer.md).\n\n**Dependency lockers** are registered with `hatch_register_locker` (see [Registration](#registration) below).\n\n## Registration\n\n```python tab=\"hooks.py\"\nfrom hatchling.plugin import hookimpl\n\nfrom .locker import MyLocker\n\n\n@hookimpl\ndef hatch_register_locker():\n    return MyLocker\n```\n\nExpose the module on the `hatch` entry point (see [Plugins — Discovery](about.md#discovery)) and list the distribution under [`tool.hatch.env.requires`](environment/reference.md#installation) when the plugin is not installed globally.\n\n## Configuration\n\n- Global default: [`tool.hatch.locker`](../config/environment/overview.md#locker) (string plugin name).\n- Per environment: [`tool.hatch.envs.<name>.locker`](../config/environment/overview.md#locker) overrides the global value.\n- If unset, Hatch picks `uv` when the environment uses the UV installer, otherwise `pip`.\n\n## Built-in lockers\n\n| `PLUGIN_NAME` | When selected | Notes |\n| ------------- | ------------- | ----- |\n| `uv` | Virtual env + UV installer | `uv pip compile` / `uv pip sync`; supports layered locks (extras, dependency-groups, `pyproject.toml`). |\n| `pip` | Any supported environment | `pip lock`; flat dependency list only (no layered extras/groups in the pip locker). `apply_lock` is a no-op — use UV for `locked` installs from a pylock today. |\n","docs/plugins/metadata-hook/custom.md":"# Custom metadata hook\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [MetadataHookInterface](reference.md#hatchling.metadata.plugin.interface.MetadataHookInterface).\n\n## Configuration\n\nThe metadata hook plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.metadata.hooks.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.metadata.plugin.interface import MetadataHookInterface\n\n\nclass CustomMetadataHook(MetadataHookInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_metadata_hook` that returns the desired build hook.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.metadata.plugin.interface.MetadataHookInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","docs/plugins/metadata-hook/reference.md":"# Metadata hook plugins\n\n-----\n\nMetadata hooks allow for the modification of [project metadata](../../config/metadata.md) after it has been loaded.\n\n## Known third-party\n\n- [hatch-docstring-description](https://github.com/flying-sheep/hatch-docstring-description) - set the project description using docstrings\n- [hatch-fancy-pypi-readme](https://github.com/hynek/hatch-fancy-pypi-readme) - dynamically construct the README\n- [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version) - uses fields from NodeJS `package.json` files\n- [hatch-odoo](https://github.com/acsone/hatch-odoo) - determine dependencies based on manifests of Odoo add-ons\n- [hatch-requirements-txt](https://github.com/repo-helper/hatch-requirements-txt) - read project dependencies from `requirements.txt` files\n- [UniDep](https://github.com/basnijholt/unidep) - for unified `pip` and `conda` dependency management using a single `requirements.yaml` file for both \n\n::: hatchling.metadata.plugin.interface.MetadataHookInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - update\n      - get_known_classifiers\n","docs/plugins/publisher/package-index.md":"# Index publisher\n\n-----\n\nSee the documentation for [publishing](../../publish.md).\n\n## Options\n\n| Flag | Config name | Description |\n| --- | --- | --- |\n| `-r`/`--repo` | `repo` | The repository with which to publish artifacts |\n| `-u`/`--user` | `user` | The user with which to authenticate |\n| `-a`/`--auth` | `auth` | The credentials to use for authentication |\n| `--ca-cert` | `ca-cert` | The path to a CA bundle |\n| `--client-cert` | `client-cert` | The path to a client certificate, optionally containing the private key |\n| `--client-key` | `client-key` | The path to the client certificate's private key |\n| | `repos` | A table of named [repositories](#repositories) to their respective options |\n\n## Configuration\n\nThe publisher plugin name is `index`.\n\n```toml tab=\"config.toml\"\n[publish.index]\n```\n\n### Repositories\n\nAll top-level options can be overridden per repository using the `repos` table\nwith a required `url` attribute for each repository. The following shows the\ndefault configuration:\n\n```toml tab=\"config.toml\"\n[publish.index.repos.main]\nurl = \"https://upload.pypi.org/legacy/\"\n\n[publish.index.repos.test]\nurl = \"https://test.pypi.org/legacy/\"\n```\n\nThe `repo` and `repos` options have no effect.\n\n### Confirmation prompt\n\nYou can require a confirmation prompt or use of the `-y`/`--yes` flag by\nsetting publishers' `disable` option to `true` in either Hatch's\n[config file](../../config/hatch.md) or project-specific configuration (which takes\nprecedence):\n\n```toml tab=\"config.toml\"\n[publish.index]\ndisable = true\n```\n\n```toml config-example\n[tool.hatch.publish.index]\ndisable = true\n```\n","docs/plugins/publisher/reference.md":"# Publisher plugins\n\n-----\n\n## Known third-party\n\n- [hatch-aws-publisher](https://github.com/aka-raccoon/hatch-aws-publisher) - publish AWS Lambda functions with SAM\n\n::: hatch.publish.plugin.interface.PublisherInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - cache_dir\n      - project_config\n      - plugin_config\n      - disable\n      - publish\n","docs/plugins/utilities.md":"# Plugin utilities\n\n-----\n\n::: hatchling.builders.utils.get_reproducible_timestamp\n    options:\n      show_root_full_path: true\n\n::: hatchling.builders.config.BuilderConfig\n    options:\n      show_source: false\n      members:\n      - directory\n      - ignore_vcs\n      - reproducible\n      - dev_mode_dirs\n      - versions\n      - dependencies\n      - default_include\n      - default_exclude\n      - default_packages\n      - default_only_include\n\n::: hatchling.bridge.app.Application\n    options:\n      show_source: false\n      members:\n      - abort\n      - verbosity\n      - display_debug\n      - display_error\n      - display_info\n      - display_success\n      - display_waiting\n      - display_warning\n\n::: hatch.utils.platform.Platform\n    options:\n      show_source: false\n      members:\n      - format_for_subprocess\n      - run_command\n      - check_command\n      - check_command_output\n      - capture_process\n      - exit_with_command\n      - default_shell\n      - modules\n      - home\n      - name\n      - display_name\n      - windows\n      - macos\n      - linux\n\n::: hatch.env.context.EnvironmentContextFormatter\n    options:\n      show_source: false\n      members:\n      - formatters\n\n::: hatch.env.plugin.interface.FileSystemContext\n    options:\n      show_source: false\n      members:\n      - env\n      - sync_local\n      - sync_env\n      - local_path\n      - env_path\n      - join\n\n::: hatch.project.sources.Source\n    options:\n      show_source: false\n\n::: hatch.project.sources.PathSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.GitSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.UrlSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.IndexSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.WorkspaceSource\n    options:\n      show_source: false\n","docs/plugins/version-scheme/reference.md":"# Version scheme plugins\n\n-----\n\n## Known third-party\n\n- [hatch-calver](https://github.com/akx/hatch-calver) - uses [calendar versioning](https://calver.org)\n- [hatch-semver](https://github.com/Nagidal/hatch-semver) - uses [semantic versioning](https://semver.org)\n\n::: hatchling.version.scheme.plugin.interface.VersionSchemeInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - validate_bump\n      - update\n","docs/plugins/version-scheme/standard.md":"# Standard version scheme\n\n-----\n\nSee the documentation for [versioning](../../version.md#updating).\n\n## Configuration\n\nThe version scheme plugin name is `standard`.\n\n```toml config-example\n[tool.hatch.version]\nscheme = \"standard\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `validate-bump` | When setting a specific version, this determines whether to check that the new version is higher than the original. The default is `true`. |\n","docs/plugins/version-source/code.md":"# Code version source\n\n-----\n\n## Updates\n\nSetting the version is not supported.\n\n## Configuration\n\nThe version source plugin name is `code`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"code\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to a Python file or extension module that will be loaded |\n| `expression` | A Python expression that when evaluated in the context of the loaded file returns the version. The default expression is simply `__version__`. |\n| `search-paths` | A list of relative paths to directories that will be prepended to Python's search path |\n\n## Missing imports\n\nIf the chosen path imports another module in your project, then you'll need to use absolute imports coupled with the `search-paths` option. For example, say you need to load the following file:\n\n```python tab=\"src/pkg/\\_\\_init\\_\\_.py\"\n    from ._version import get_version\n\n    __version__ = get_version()\n```\n\nYou should change it to:\n\n```python tab=\"src/pkg/\\_\\_init\\_\\_.py\"\n    from pkg._version import get_version\n\n    __version__ = get_version()\n```\n\nand the configuration would become:\n\n```toml config-example\n[tool.hatch.version]\nsource = \"code\"\npath = \"src/pkg/__init__.py\"\nsearch-paths = [\"src\"]\n```\n","docs/plugins/version-source/env.md":"# Environment version source\n\n-----\n\nRetrieves the version from an environment variable. This can be useful in build pipelines where the version is set by an external trigger.\n\n## Updates\n\nSetting the version is not supported.\n\n## Configuration\n\nThe version source plugin name is `env`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"env\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `variable` (required) | The name of the environment variable |\n","docs/plugins/version-source/reference.md":"# Version source plugins\n\n-----\n\n## Known third-party\n\n- [hatch-vcs](https://github.com/ofek/hatch-vcs) - uses your preferred version control system (like Git)\n- [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version) - uses the `version` field of NodeJS `package.json` files\n- [hatch-regex-commit](https://github.com/frankie567/hatch-regex-commit) - automatically creates a Git commit and tag after version bumping\n- [versioningit](https://github.com/jwodder/versioningit) - determines version from Git or Mercurial tags, with customizable version formatting\n\n::: hatchling.version.source.plugin.interface.VersionSourceInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - get_version_data\n      - set_version\n","docs/plugins/version-source/regex.md":"# Regex version source\n\n-----\n\nSee the documentation for [versioning](../../version.md).\n\n## Updates\n\nSetting the version is supported.\n\n## Configuration\n\nThe version source plugin name is `regex`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"regex\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to a file containing the project's version |\n| `pattern` | A regular expression that has a named group called `version` that represents the version. The default pattern looks for a variable named `__version__` or `VERSION` that is set to a string containing the version, optionally prefixed with the lowercase letter `v`. |\n"},"files":{"docs/how-to/plugins/testing-builds.md":"# Testing build plugins\n\n-----\n\nFor testing [Hatchling plugins](../../plugins/about.md#hatchling), you'll usually want to generate a project to execute builds as a real user would. For example, as a minimal [pytest](https://github.com/pytest-dev/pytest) fixture:\n\n```python\nfrom pathlib import Path\n\nimport pytest\n\n\n@pytest.fixture\ndef new_project(tmp_path):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {Path.cwd().as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n```\n\nThe issue with this is that after the first test session, the project will be forever cached by pip based on the file path. Therefore, subsequent tests runs will never use updated code.\n\nTo invalidate the cache, copy your code to a new path for every test session:\n\n```python\nimport shutil\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\n\nimport pytest\n\n\n@pytest.fixture(scope='session')\ndef plugin_dir():\n    with TemporaryDirectory() as d:\n        directory = Path(d, 'plugin')\n        shutil.copytree(\n            Path.cwd(), directory, ignore=shutil.ignore_patterns('.git')\n        )\n\n        yield directory.resolve()\n\n\n@pytest.fixture\ndef new_project(tmp_path, plugin_dir):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {plugin_dir.as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n```\n\n!!! note\n    This example chooses to ignore copying `.git` for performance reasons. You may want to ignore more patterns, or copy only specific paths like [this plugin](https://github.com/hynek/hatch-fancy-pypi-readme/blob/main/tests/conftest.py) does.\n","docs/plugins/about.md":"# Plugins\n\n-----\n\nHatch utilizes [pluggy](https://github.com/pytest-dev/pluggy) for its plugin functionality.\n\n## Overview\n\nAll plugins provide registration hooks that return one or more classes that inherit from a particular [type](#types) interface.\n\nEach registration hook must be decorated by Hatch's hook marker. For example, if you wanted to create a new kind of environment you could do:\n\n```python tab=\"hooks.py\"\nfrom hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialEnvironment\n\n\n@hookimpl\ndef hatch_register_environment():\n    return SpecialEnvironment\n```\n\nThe hooks can return a single class or a list of classes.\n\nEvery class must define an attribute called `PLUGIN_NAME` that users will select when they wish to use the plugin. So in the example above, the class might be defined like:\n\n```python tab=\"plugin.py\"\n...\nclass SpecialEnvironment(...):\n    PLUGIN_NAME = 'special'\n    ...\n```\n\n## Project configuration\n\n### Naming\n\nIt is recommended that plugin project names are prefixed with `hatch-`. For example, if you wanted to make a plugin that provides some functionality for a product named `foo` you might do:\n\n```toml tab=\"pyproject.toml\"\n[project]\nname = \"hatch-foo\"\n```\n\n### Discovery\n\nYou'll need to define your project as a [Python plugin](../config/metadata.md#plugins) for Hatch:\n\n```toml tab=\"pyproject.toml\"\n[project.entry-points.hatch]\nfoo = \"pkg.hooks\"\n```\n\nThe name of the plugin should be the project name (excluding any `hatch-` prefix) and the path should represent the module that contains the registration hooks.\n\n### Classifier\n\nAdd [`Framework :: Hatch`](https://pypi.org/search/?c=Framework+%3A%3A+Hatch) to your project's [classifiers](../config/metadata.md#classifiers) to make it easy to search for Hatch plugins:\n\n```toml tab=\"pyproject.toml\"\n[project]\nclassifiers = [\n  ...\n  \"Framework :: Hatch\",\n  ...\n]\n```\n\n## Types\n\n### Hatchling\n\nThese are all involved in building projects and therefore any defined dependencies are automatically installed in each build environment.\n\n- [Builder](builder/reference.md)\n- [Build hook](build-hook/reference.md)\n- [Metadata hook](metadata-hook/reference.md)\n- [Version source](version-source/reference.md)\n- [Version scheme](version-scheme/reference.md)\n\n### Hatch\n\nThese must be installed in the same environment as Hatch itself.\n\n- [Environment](environment/reference.md)\n- [Environment collector](environment-collector/reference.md)\n- [Dependency locker](locker.md)\n- [Publisher](publisher/reference.md)\n","docs/plugins/build-hook/custom.md":"# Custom build hook\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [BuildHookInterface](reference.md#hatchling.builders.hooks.plugin.interface.BuildHookInterface).\n\n## Configuration\n\nThe build hook plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.build.hooks.custom]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.builders.hooks.plugin.interface import BuildHookInterface\n\n\nclass CustomBuildHook(BuildHookInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_build_hook` that returns the desired build hook.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.builders.hooks.plugin.interface.BuildHookInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","docs/plugins/build-hook/reference.md":"# Build hook plugins\n\n-----\n\nA build hook provides code that will be executed at various stages of the build process. See the documentation for [build hook configuration](../../config/build.md#build-hooks).\n\n## Known third-party\n\n- [hatch-argparse-manpage](https://github.com/damonlynch/hatch-argparse-manpage) - generate man pages for [argparse](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser)-based CLIs\n- [hatch-autorun](https://github.com/ofek/hatch-autorun) - used to inject code into an installation that will automatically run before the first import\n- [hatch-build-scripts](https://github.com/rmorshea/hatch-build-scripts) - run arbitrary shell commands that create artifacts\n- [hatch-cython](https://github.com/joshua-auchincloss/hatch-cython) - build [Cython](https://github.com/cython/cython) extensions\n- [hatch-gettext](https://github.com/damonlynch/hatch-gettext) - compiles multi-lingual messages with GNU `gettext` tools\n- [hatch-jupyter-builder](https://github.com/jupyterlab/hatch-jupyter-builder) - used for packages in the Project Jupyter ecosystem\n- [hatch-mypyc](https://github.com/ofek/hatch-mypyc) - compiles code with [Mypyc](https://github.com/mypyc/mypyc)\n- [hatch-odoo](https://github.com/acsone/hatch-odoo) - package Odoo add-ons into the appropriate namespace\n- [hatch-project-name](https://github.com/valentinoli/hatch-project-name/) - writes the project name to a file\n- [scikit-build-core](https://github.com/scikit-build/scikit-build-core) - build extension modules with CMake\n\n## Overview\n\nBuild hooks run for every selected [version](../../config/build.md#versions) of build targets.\n\nThe [initialization](#hatchling.builders.hooks.plugin.interface.BuildHookInterface.initialize) stage occurs immediately before each build and the [finalization](#hatchling.builders.hooks.plugin.interface.BuildHookInterface.finalize) stage occurs immediately after. Each stage has the opportunity to view or modify [build data](#build-data).\n\n## Build data\n\nBuild data is a simple mapping whose contents can influence the behavior of builds. Which fields exist and are recognized depends on each build target.\n\nThe following fields are always present and recognized by the build system itself:\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `artifacts` | `#!python list[str]` | This is a list of extra [`artifact` patterns](../../config/build.md#artifacts) and should generally only be appended to |\n| `force_include` | `#!python dict[str, str]` | This is a mapping of extra [forced inclusion paths](../../config/build.md#forced-inclusion), with this mapping taking precedence in case of conflicts |\n| `build_hooks` | `#!python tuple[str, ...]` | This is an immutable sequence of the names of the configured build hooks and matches the order in which they run |\n\n!!! attention\n    While user-facing TOML options are hyphenated, build data fields should be named with underscores to allow plugins to use them as valid Python identifiers.\n\n## Notes\n\nIn some cases it may be necessary to use `force_include` rather than `artifacts`. For example, say that you want to install a `lib.so` directly at the root of `site-packages` and a project defines a [package](../../config/build.md#packages) `src/foo`. If you create `src/lib.so`, there will never be a match because the directory traversal starts at `src/foo` rather than `src`. In that case you must do either:\n\n```python\nbuild_data['force_include']['src/lib.so'] = 'src/lib.so'\n```\n\nor\n\n```python\nbuild_data['force_include']['/absolute/path/to/src/lib.so'] = 'src/lib.so'\n```\n\n::: hatchling.builders.hooks.plugin.interface.BuildHookInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - config\n      - build_config\n      - target_name\n      - directory\n      - dependencies\n      - clean\n      - initialize\n      - finalize\n","docs/plugins/build-hook/version.md":"# Version build hook\n\n-----\n\nThis writes the project's version to a file.\n\n## Configuration\n\nThe build hook plugin name is `version`.\n\n```toml config-example\n[tool.hatch.build.hooks.version]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.version]\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to the desired file |\n| `template` | A string representing the entire contents of `path` that will be formatted with a `version` variable |\n| `pattern` | Rather than updating the entire file, a regular expression may be used that has a named group called `version` that represents the version. If set to `true`, a pattern will be used that looks for a variable named `__version__` or `VERSION` that is set to a string containing the version, optionally prefixed with the lowercase letter `v`. |\n","docs/plugins/builder/binary.md":"# Binary builder\n\n-----\n\nThis uses [PyApp](https://github.com/ofek/pyapp) to build an application that is able to bootstrap itself at runtime.\n\n!!! note\n    This requires an installation of [Rust](https://www.rust-lang.org).\n\n## Configuration\n\nThe builder plugin name is `binary`.\n\n```toml config-example\n[tool.hatch.build.targets.binary]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `scripts` | all defined | An array of defined [script](../../config/metadata.md#cli) names to limit what gets built |\n| `python-version` | latest compatible Python minor version | The [Python version ID](https://ofek.dev/pyapp/latest/config/#known) to use |\n| `pyapp-version` | | The version of PyApp to use |\n\n## Build behavior\n\nIf any [scripts](../../config/metadata.md#cli) are defined then each one will be built (limited by the `scripts` option). Otherwise, a single executable will be built based on the project name assuming there is an equivalently named module with a `__main__.py` file.\n\nEvery executable will be built inside an `app` directory in the [output directory](../../config/build.md#output-directory).\n\nIf the `CARGO` environment variable is set then that path will be used as the executable for performing builds.\n\nIf the [`CARGO_BUILD_TARGET`](https://doc.rust-lang.org/cargo/reference/config.html#buildtarget) environment variable is set then its value will be appended to the file name stems.\n\nIf the `PYAPP_REPO` environment variable is set then a local build will be performed inside that directory rather than installing from [crates.io](https://crates.io). Note that this is [required](https://github.com/cross-rs/cross/issues/1215) if the `CARGO` environment variable refers to [cross](https://github.com/cross-rs/cross).\n","docs/plugins/builder/custom.md":"# Custom builder\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [BuilderInterface](reference.md#hatchling.builders.plugin.interface.BuilderInterface).\n\n## Configuration\n\nThe builder plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.build.targets.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.builders.plugin.interface import BuilderInterface\n\n\nclass CustomBuilder(BuilderInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_builder` that returns the desired builder.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.builders.plugin.interface.BuilderInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","docs/plugins/builder/reference.md":"# Builder plugins\n\n-----\n\nSee the documentation for [build configuration](../../config/build.md).\n\n## Known third-party\n\n- [hatch-aws](https://github.com/aka-raccoon/hatch-aws) - used for building AWS Lambda functions with SAM\n- [hatch-zipped-directory](https://github.com/dairiki/hatch-zipped-directory) - used for building ZIP archives for installation into various foreign package installation systems\n\n::: hatchling.builders.plugin.interface.BuilderInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - build_config\n      - target_config\n      - config\n      - get_config_class\n      - get_version_api\n      - get_default_versions\n      - clean\n      - recurse_included_files\n      - get_default_build_data\n","docs/plugins/builder/sdist.md":"# Source distribution builder\n\n-----\n\nA source distribution, or `sdist`, is an archive of Python \"source code\". Although largely unspecified, by convention it should include everything that is required to build a [wheel](wheel.md) without making network requests.\n\n## Configuration\n\nThe builder plugin name is `sdist`.\n\n```toml config-example\n[tool.hatch.build.targets.sdist]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `core-metadata-version` | `\"2.4\"` | The version of [core metadata](https://packaging.python.org/specifications/core-metadata/) to use |\n| `strict-naming` | `true` | Whether or not file names should contain the normalized version of the project name |\n| `support-legacy` | `false` | Whether or not to include a `setup.py` file to support legacy installation mechanisms |\n\n## Versions\n\n| Version | Description |\n| --- | --- |\n| `standard` (default) | The latest conventional format |\n\n## Default file selection\n\nWhen the user has not set any [file selection](../../config/build.md#file-selection) options, all files that are not [ignored by your VCS](../../config/build.md#vcs) will be included.\n\n!!! note\n    The following files are always included and cannot be excluded:\n\n    - `/pyproject.toml`\n    - `/hatch.toml`\n    - `/hatch_build.py`\n    - `/.gitignore` or `/.hgignore`\n    - Any defined [`readme`](../../config/metadata.md#readme) file\n    - All defined [`license-files`](../../config/metadata.md#license)\n\n## Reproducibility\n\n[Reproducible builds](../../config/build.md#reproducible-builds) are supported.\n\n## Build data\n\nThis is data that can be modified by [build hooks](../build-hook/reference.md).\n\n| Data | Default | Description |\n| --- | --- | --- |\n| `dependencies` | | Extra [project dependencies](../../config/metadata.md#required) |\n","docs/plugins/builder/wheel.md":"# Wheel builder\n\n-----\n\nA [wheel](https://packaging.python.org/specifications/binary-distribution-format/) is a binary distribution of a Python package that can be installed directly into an environment.\n\n## Configuration\n\nThe builder plugin name is `wheel`.\n\n```toml config-example\n[tool.hatch.build.targets.wheel]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `core-metadata-version` | `\"2.4\"` | The version of [core metadata](https://packaging.python.org/specifications/core-metadata/) to use |\n| `shared-data` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to the `data` subdirectory within the standard [data directory](https://packaging.python.org/en/latest/specifications/binary-distribution-format/#the-data-directory) that will be installed globally in a given Python environment, usually under `#!python sys.prefix` |\n| `shared-scripts` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to the `scripts` subdirectory within the standard [data directory](https://packaging.python.org/en/latest/specifications/binary-distribution-format/#the-data-directory) that will be installed in a given Python environment, usually under `Scripts` on Windows or `bin` otherwise, and would normally be available on PATH |\n| `extra-metadata` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to extra [metadata](https://peps.python.org/pep-0427/#the-dist-info-directory) that will be shipped in a directory named `extra_metadata` |\n| `strict-naming` | `true` | Whether or not file names should contain the normalized version of the project name |\n| `macos-max-compat` | `false` | Whether or not on macOS, when build hooks have set the `infer_tag` [build data](#build-data), the wheel name should signal broad support rather than specific versions for newer SDK versions.<br><br>Note: This option will eventually be removed. |\n| `bypass-selection` | `false` | Whether or not to suppress the error when one has not defined any file selection options and all heuristics have failed to determine what to ship |\n| `sbom-files` | | A list of paths to [Software Bill of Materials](https://peps.python.org/pep-0770/) files that will be included in the `.dist-info/sboms/` directory of the wheel |\n\n!!! note\n    Many build frontends will build the wheel from a source distribution. This is the recommended approach, but it means you need to ensure the SBOM files passed to `sbom-files` are also [included in the source distribution](https://hatch.pypa.io/latest/config/build/#file-selection).\n\n## Versions\n\n| Version | Description |\n| --- | --- |\n| `standard` (default) | The latest standardized format |\n| `editable` | A wheel that only ships `.pth` files or import hooks for real-time development |\n\n## Default file selection\n\nWhen the user has not set any [file selection](../../config/build.md#file-selection) options, the [project name](../../config/metadata.md#name) will be used to determine the package to ship in the following heuristic order:\n\n1. `<NAME>/__init__.py`\n2. `src/<NAME>/__init__.py`\n3. `<NAME>.py`\n4. `<NAMESPACE>/<NAME>/__init__.py`\n\nIf none of these heuristics are satisfied, an error will be raised.\n\n## Reproducibility\n\n[Reproducible builds](../../config/build.md#reproducible-builds) are supported.\n\n## Build data\n\nThis is data that can be modified by [build hooks](../build-hook/reference.md).\n\n| Data | Default | Description |\n| --- | --- | --- |\n| `tag` | | The full [tag](https://peps.python.org/pep-0425/) part of the filename (e.g. `py3-none-any`), defaulting to a cross-platform wheel with the supported major versions of Python based on [project metadata](../../config/metadata.md#python-support) |\n| `infer_tag` | `#!python False` | When `tag` is not set, this may be enabled to use the one most specific to the platform, Python interpreter, and ABI |\n| `pure_python` | `#!python True` | Whether or not to write metadata indicating that the package does not contain any platform-specific files |\n| `dependencies` | | Extra [project dependencies](../../config/metadata.md#required) |\n| `shared_data` | | Additional [`shared-data`](#options) entries, which take precedence in case of conflicts |\n| `shared_scripts` | | Additional [`shared-scripts`](#options) entries, which take precedence in case of conflicts |\n| `extra_metadata` | | Additional [`extra-metadata`](#options) entries, which take precedence in case of conflicts |\n| `force_include_editable` | | Similar to the [`force_include` option](../build-hook/reference.md#build-data) but specifically for the `editable` [version](#versions) and takes precedence |\n| `sbom_files` | | This is a list of the sbom files that should be included under `.dist-info/sboms`. |\n","docs/plugins/environment-collector/custom.md":"# Custom environment collector\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [EnvironmentCollectorInterface](reference.md#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface).\n\n## Configuration\n\nThe environment collector plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.env.collectors.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_plugins.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_plugins.py\"\n    from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface\n\n\n    class CustomEnvironmentCollector(EnvironmentCollectorInterface):\n        ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_environment_collector` that returns the desired environment collector.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","docs/plugins/environment-collector/default.md":"# Default environment collector\n\n-----\n\nThis adds the `default` environment with [type](../../config/environment/overview.md#type) set to [virtual](../environment/virtual.md) and will always be applied.\n\n## Configuration\n\nThe environment collector plugin name is `default`.\n\n```toml config-example\n[tool.hatch.env.collectors.default]\n```\n\n## Options\n\nThere are no options available currently.\n","docs/plugins/environment-collector/reference.md":"# Environment collector plugins\n\n-----\n\nEnvironment collectors allow for dynamically modifying environments or adding environments beyond those defined in config. Users can override default values provided by each environment.\n\n## Known third-party\n\n- [hatch-mkdocs](https://github.com/mkdocs/hatch-mkdocs) - integrate [MkDocs](https://github.com/mkdocs/mkdocs) and infer dependencies into an env\n\n## Installation\n\nAny required environment collectors that are not built-in must be manually installed alongside Hatch or listed in the `tool.hatch.env.requires` array for automatic management:\n\n```toml config-example\n[tool.hatch.env]\nrequires = [\n  \"...\",\n]\n```\n\n::: hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - get_initial_config\n      - finalize_config\n      - finalize_environments\n","docs/plugins/environment/reference.md":"# Environment plugins\n\n-----\n\nSee the documentation for [environment configuration](../../config/environment/overview.md).\n\n## Known third-party\n\n- [hatch-conda](https://github.com/OldGrumpyViking/hatch-conda) - environments backed by Conda/Mamba\n- [hatch-containers](https://github.com/ofek/hatch-containers) - environments run inside containers\n- [hatch-pip-compile](https://github.com/juftin/hatch-pip-compile) - use [pip-compile](https://github.com/jazzband/pip-tools) to manage project dependencies and lockfiles\n- [hatch-pip-deepfreeze](https://github.com/sbidoul/hatch-pip-deepfreeze) - [virtual](virtual.md) environments with dependency locking by [pip-deepfreeze](https://github.com/sbidoul/pip-deepfreeze)\n\n## Installation\n\nAny required environment types that are not built-in must be manually installed alongside Hatch or listed in the `tool.hatch.env.requires` array for automatic management:\n\n```toml config-example\n[tool.hatch.env]\nrequires = [\n  \"...\",\n]\n```\n\n## Life cycle\n\nWhenever an environment is used, the following logic is performed:\n\n::: hatch.project.core.Project.prepare_environment\n    options:\n      show_root_heading: false\n      show_root_toc_entry: false\n\n## Build environments\n\nAll environment types should [offer support](#hatch.env.plugin.interface.EnvironmentInterface.fs_context) for synchronized storage between the local file system and the environment. This functionality is used in the following scenarios:\n\n- the [`build`](../../cli/reference.md#hatch-build) command\n- commands that read dependencies, like [`dep hash`](../../cli/reference.md#hatch-dep-hash), if any [project dependencies](../../config/metadata.md#dependencies) are [set dynamically](../../config/metadata.md#dynamic)\n\n::: hatch.env.plugin.interface.EnvironmentInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - find\n      - create\n      - remove\n      - exists\n      - install_project\n      - install_project_dev_mode\n      - dependencies_in_sync\n      - sync_dependencies\n      - dependency_hash\n      - project_dependencies\n      - project_root\n      - sep\n      - pathsep\n      - fs_context\n      - activate\n      - deactivate\n      - app_status_creation\n      - app_status_pre_installation\n      - app_status_post_installation\n      - app_status_project_installation\n      - app_status_dependency_state_check\n      - app_status_dependency_installation_check\n      - app_status_dependency_synchronization\n      - app\n      - root\n      - name\n      - data_directory\n      - isolated_data_directory\n      - config\n      - platform\n      - environment_dependencies\n      - dependencies\n      - sources\n      - get_source_install_args\n      - env_vars\n      - env_include\n      - env_exclude\n      - platforms\n      - skip_install\n      - dev_mode\n      - description\n      - command_context\n      - enter_shell\n      - run_shell_command\n      - resolve_commands\n      - get_env_vars\n      - apply_features\n      - construct_pip_install_command\n      - join_command_args\n      - check_compatibility\n      - get_option_types\n      - get_env_var_option\n      - get_context\n\n## Dependency lockers\n\n**Dependency lockers** are implemented: register classes with `hatch_register_locker` (see [Dependency locker plugins](../locker.md)). They stay **decoupled** from environment plugins—no subclassing [`EnvironmentInterface`](#hatch.env.plugin.interface.EnvironmentInterface) just to change locking—and call the environment’s **public API** (for example [`command_context`](#hatch.env.plugin.interface.EnvironmentInterface.command_context) and [`platform`](../utilities.md)).\n\nFor moving artifacts between the workspace and the environment, custom lockers should prefer [`fs_context`](#hatch.env.plugin.interface.EnvironmentInterface.fs_context) and [`FileSystemContext`](../utilities.md#hatch.env.plugin.interface.FileSystemContext) over ad hoc I/O.\n\nEnd-user commands: [How to use lockfiles](../../how-to/environment/lockfiles.md).\n","docs/plugins/environment/virtual.md":"# Virtual environment\n\n-----\n\nThis uses virtual environments backed by [virtualenv](https://github.com/pypa/virtualenv) or [UV](https://github.com/astral-sh/uv).\n\n## Configuration\n\nThe environment plugin name is `virtual`.\n\n```toml config-example\n[tool.hatch.envs.<ENV_NAME>]\ntype = \"virtual\"\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `python` | | The version of Python to find on your system and subsequently use to create the environment, defaulting to the `HATCH_PYTHON` environment variable, followed by the [normal resolution logic](#python-resolution). Setting the `HATCH_PYTHON` environment variable to `self` will force the use of the Python executable Hatch is running on. For more information, see the [documentation](https://virtualenv.pypa.io/en/latest/user_guide.html#python-discovery). |\n| `python-sources` | `['external', 'internal']` | This may be set to an array of strings that are either the literal `internal` or `external`. External considers only Python executables that are already on `PATH`. Internal considers only [internally managed Python distributions](#internal-distributions). |\n| `path` | | An explicit path to the virtual environment. The path may be absolute or relative to the project root. Any environments that [inherit](../../config/environment/overview.md#inheritance) this option will also use this path. The environment variable `HATCH_ENV_TYPE_VIRTUAL_PATH` may be used, which will take precedence. |\n| `system-packages` | `false` | Whether or not to give the virtual environment access to the system `site-packages` directory |\n| `installer` | `pip` | When set to `uv`, [UV](https://github.com/astral-sh/uv) will be used in place of virtualenv & pip for virtual environment creation and dependency management, respectively. If you intend to provide UV yourself, you may set the `HATCH_ENV_TYPE_VIRTUAL_UV_PATH` environment variable which should be the absolute path to a UV binary. This environment variable implicitly sets the `installer` option to `uv` (if unset). |\n\n## Location\n\nThe [location](../../cli/reference.md#hatch-env-find) of environments is determined in the following heuristic order:\n\n1. The `path` option\n2. A directory named after the environment within the configured `virtual` [environment directory](../../config/hatch.md#environments) if the directory resides somewhere within the project root or if it is set to a `.virtualenvs` directory within the user's home directory\n3. Otherwise, environments are stored within the configured `virtual` [environment directory](../../config/hatch.md#environments) in a deeply nested structure in order to support multiple projects\n\nAdditionally, when the `path` option is not used, the name of the directory for the `default` environment will be the normalized project name to provide a more meaningful default [shell](../../cli/reference.md#hatch-shell) prompt.\n\n## Python resolution\n\nVirtual environments necessarily require a parent installation of Python. The following rules determine how the parent is resolved.\n\nThe Python choice is determined by the [`python` option](#options) followed by the `HATCH_PYTHON` environment variable. If the choice is via the environment variable, then resolution stops and that path is used unconditionally.\n\nThe resolvers will be based on the [`python-sources` option](#options) and all resolved interpreters will ensure compatibility with the project's defined [Python support](../../config/metadata.md#python-support).\n\nIf a Python version has been chosen then each resolver will try to find an interpreter that satisfies that version.\n\nIf no version has been chosen, then each resolver will try to find a version that matches the version of Python that Hatch is currently running on. If not found then each resolver will try to find the highest compatible version.\n\n!!! note\n    Some external Python paths are considered unstable and are ignored during resolution. For example, if Hatch is installed via Homebrew then `sys.executable` will be ignored because the interpreter could change or be removed at any time.\n\n!!! note\n    When resolution finds a match using an [internally managed distribution](#internal-distributions) and an update is available, the latest distribution will automatically be downloaded before environment creation.\n\n## Internal distributions\n\nThe following options are recognized for internal Python resolution.\n\n!!! tip\n    You can set custom sources for distributions by setting the `HATCH_PYTHON_SOURCE_<NAME>` environment variable where `<NAME>` is the uppercased version of the distribution name with periods replaced by underscores e.g. `HATCH_PYTHON_SOURCE_PYPY3_10`.\n\n### CPython\n\n| NAME |\n| --- |\n| `3.7` |\n| `3.8` |\n| `3.9` |\n| `3.10` |\n| `3.11` |\n| `3.12` |\n| `3.13` |\n| `3.14` |\n| `3.15` |\n\nThe source of distributions is the [python-build-standalone](https://github.com/indygreg/python-build-standalone) project.\n\nSome distributions have [variants](https://gregoryszorc.com/docs/python-build-standalone/main/running.html) that may be configured with environment variables. Options may be combined.\n\n| Option | Platforms | Allowed values |\n| --- | --- | --- |\n| `HATCH_PYTHON_VARIANT_CPU` | <ul><li>Linux</li></ul> | <ul><li><code>v1</code></li><li><code>v2</code></li><li><code>v3</code> (default)</li><li><code>v4</code></li></ul> |\n| `HATCH_PYTHON_VARIANT_GIL` | <ul><li>Linux</li><li>Windows</li><li>macOS</li></ul> | <ul><li><code>freethreaded</code></li></ul> |\n\n### PyPy\n\n| NAME |\n| --- |\n| `pypy2.7` |\n| `pypy3.9` |\n| `pypy3.10` |\n| `pypy3.11` |\n\nThe source of distributions is the [PyPy](https://www.pypy.org) project.\n\n## Troubleshooting\n\n### macOS SIP\n\nIf you need to set linker environment variables like those starting with `DYLD_` or `LD_`, any executable secured by [System Integrity Protection](https://en.wikipedia.org/wiki/System_Integrity_Protection) that is invoked when [running commands](../../environment.md#command-execution) will not see those environment variable modifications as macOS strips those.\n\nHatch interprets such commands as shell commands but deliberately ignores such paths to protected shells. This workaround suffices for the majority of use cases but there are 2 situations in which it may not:\n\n1. There are no unprotected `sh`, `bash`, `zsh`, nor `fish` executables found along PATH.\n2. The desired executable is a project's [script](../../config/metadata.md#cli), and the [location](#location) of environments contains spaces or is longer than 124[^1] characters. In this case `pip` and other installers will create such an entry point with a shebang pointing to `/bin/sh` (which is protected) to avoid shebang limitations. Rather than changing the location, you could invoke the script as e.g. `python -m pytest` (if the project supports that method of invocation by shipping a `__main__.py`).\n\n[^1]: The shebang length limit is [usually](https://web.archive.org/web/20221231220856/https://www.in-ulm.de/~mascheck/various/shebang/#length) 127 but 3 characters surround the executable path: `#!<EXE_PATH>\\n`\n","docs/plugins/locker.md":"# Dependency locker plugins\n\n-----\n\nHatch selects a **locker** plugin to **generate** PEP 751 lockfiles, verify they are **in sync** with the configured dependency inputs, and **apply** them when syncing a `locked` environment. Built-in lockers are **`uv`** and **`pip`**, matching the [virtual environment installer](../how-to/environment/select-installer.md).\n\n**Dependency lockers** are registered with `hatch_register_locker` (see [Registration](#registration) below).\n\n## Registration\n\n```python tab=\"hooks.py\"\nfrom hatchling.plugin import hookimpl\n\nfrom .locker import MyLocker\n\n\n@hookimpl\ndef hatch_register_locker():\n    return MyLocker\n```\n\nExpose the module on the `hatch` entry point (see [Plugins — Discovery](about.md#discovery)) and list the distribution under [`tool.hatch.env.requires`](environment/reference.md#installation) when the plugin is not installed globally.\n\n## Configuration\n\n- Global default: [`tool.hatch.locker`](../config/environment/overview.md#locker) (string plugin name).\n- Per environment: [`tool.hatch.envs.<name>.locker`](../config/environment/overview.md#locker) overrides the global value.\n- If unset, Hatch picks `uv` when the environment uses the UV installer, otherwise `pip`.\n\n## Built-in lockers\n\n| `PLUGIN_NAME` | When selected | Notes |\n| ------------- | ------------- | ----- |\n| `uv` | Virtual env + UV installer | `uv pip compile` / `uv pip sync`; supports layered locks (extras, dependency-groups, `pyproject.toml`). |\n| `pip` | Any supported environment | `pip lock`; flat dependency list only (no layered extras/groups in the pip locker). `apply_lock` is a no-op — use UV for `locked` installs from a pylock today. |\n","docs/plugins/metadata-hook/custom.md":"# Custom metadata hook\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [MetadataHookInterface](reference.md#hatchling.metadata.plugin.interface.MetadataHookInterface).\n\n## Configuration\n\nThe metadata hook plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.metadata.hooks.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.metadata.plugin.interface import MetadataHookInterface\n\n\nclass CustomMetadataHook(MetadataHookInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_metadata_hook` that returns the desired build hook.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.metadata.plugin.interface.MetadataHookInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","docs/plugins/metadata-hook/reference.md":"# Metadata hook plugins\n\n-----\n\nMetadata hooks allow for the modification of [project metadata](../../config/metadata.md) after it has been loaded.\n\n## Known third-party\n\n- [hatch-docstring-description](https://github.com/flying-sheep/hatch-docstring-description) - set the project description using docstrings\n- [hatch-fancy-pypi-readme](https://github.com/hynek/hatch-fancy-pypi-readme) - dynamically construct the README\n- [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version) - uses fields from NodeJS `package.json` files\n- [hatch-odoo](https://github.com/acsone/hatch-odoo) - determine dependencies based on manifests of Odoo add-ons\n- [hatch-requirements-txt](https://github.com/repo-helper/hatch-requirements-txt) - read project dependencies from `requirements.txt` files\n- [UniDep](https://github.com/basnijholt/unidep) - for unified `pip` and `conda` dependency management using a single `requirements.yaml` file for both \n\n::: hatchling.metadata.plugin.interface.MetadataHookInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - update\n      - get_known_classifiers\n","docs/plugins/publisher/package-index.md":"# Index publisher\n\n-----\n\nSee the documentation for [publishing](../../publish.md).\n\n## Options\n\n| Flag | Config name | Description |\n| --- | --- | --- |\n| `-r`/`--repo` | `repo` | The repository with which to publish artifacts |\n| `-u`/`--user` | `user` | The user with which to authenticate |\n| `-a`/`--auth` | `auth` | The credentials to use for authentication |\n| `--ca-cert` | `ca-cert` | The path to a CA bundle |\n| `--client-cert` | `client-cert` | The path to a client certificate, optionally containing the private key |\n| `--client-key` | `client-key` | The path to the client certificate's private key |\n| | `repos` | A table of named [repositories](#repositories) to their respective options |\n\n## Configuration\n\nThe publisher plugin name is `index`.\n\n```toml tab=\"config.toml\"\n[publish.index]\n```\n\n### Repositories\n\nAll top-level options can be overridden per repository using the `repos` table\nwith a required `url` attribute for each repository. The following shows the\ndefault configuration:\n\n```toml tab=\"config.toml\"\n[publish.index.repos.main]\nurl = \"https://upload.pypi.org/legacy/\"\n\n[publish.index.repos.test]\nurl = \"https://test.pypi.org/legacy/\"\n```\n\nThe `repo` and `repos` options have no effect.\n\n### Confirmation prompt\n\nYou can require a confirmation prompt or use of the `-y`/`--yes` flag by\nsetting publishers' `disable` option to `true` in either Hatch's\n[config file](../../config/hatch.md) or project-specific configuration (which takes\nprecedence):\n\n```toml tab=\"config.toml\"\n[publish.index]\ndisable = true\n```\n\n```toml config-example\n[tool.hatch.publish.index]\ndisable = true\n```\n","docs/plugins/publisher/reference.md":"# Publisher plugins\n\n-----\n\n## Known third-party\n\n- [hatch-aws-publisher](https://github.com/aka-raccoon/hatch-aws-publisher) - publish AWS Lambda functions with SAM\n\n::: hatch.publish.plugin.interface.PublisherInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - cache_dir\n      - project_config\n      - plugin_config\n      - disable\n      - publish\n","docs/plugins/utilities.md":"# Plugin utilities\n\n-----\n\n::: hatchling.builders.utils.get_reproducible_timestamp\n    options:\n      show_root_full_path: true\n\n::: hatchling.builders.config.BuilderConfig\n    options:\n      show_source: false\n      members:\n      - directory\n      - ignore_vcs\n      - reproducible\n      - dev_mode_dirs\n      - versions\n      - dependencies\n      - default_include\n      - default_exclude\n      - default_packages\n      - default_only_include\n\n::: hatchling.bridge.app.Application\n    options:\n      show_source: false\n      members:\n      - abort\n      - verbosity\n      - display_debug\n      - display_error\n      - display_info\n      - display_success\n      - display_waiting\n      - display_warning\n\n::: hatch.utils.platform.Platform\n    options:\n      show_source: false\n      members:\n      - format_for_subprocess\n      - run_command\n      - check_command\n      - check_command_output\n      - capture_process\n      - exit_with_command\n      - default_shell\n      - modules\n      - home\n      - name\n      - display_name\n      - windows\n      - macos\n      - linux\n\n::: hatch.env.context.EnvironmentContextFormatter\n    options:\n      show_source: false\n      members:\n      - formatters\n\n::: hatch.env.plugin.interface.FileSystemContext\n    options:\n      show_source: false\n      members:\n      - env\n      - sync_local\n      - sync_env\n      - local_path\n      - env_path\n      - join\n\n::: hatch.project.sources.Source\n    options:\n      show_source: false\n\n::: hatch.project.sources.PathSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.GitSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.UrlSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.IndexSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.WorkspaceSource\n    options:\n      show_source: false\n","docs/plugins/version-scheme/reference.md":"# Version scheme plugins\n\n-----\n\n## Known third-party\n\n- [hatch-calver](https://github.com/akx/hatch-calver) - uses [calendar versioning](https://calver.org)\n- [hatch-semver](https://github.com/Nagidal/hatch-semver) - uses [semantic versioning](https://semver.org)\n\n::: hatchling.version.scheme.plugin.interface.VersionSchemeInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - validate_bump\n      - update\n","docs/plugins/version-scheme/standard.md":"# Standard version scheme\n\n-----\n\nSee the documentation for [versioning](../../version.md#updating).\n\n## Configuration\n\nThe version scheme plugin name is `standard`.\n\n```toml config-example\n[tool.hatch.version]\nscheme = \"standard\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `validate-bump` | When setting a specific version, this determines whether to check that the new version is higher than the original. The default is `true`. |\n","docs/plugins/version-source/code.md":"# Code version source\n\n-----\n\n## Updates\n\nSetting the version is not supported.\n\n## Configuration\n\nThe version source plugin name is `code`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"code\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to a Python file or extension module that will be loaded |\n| `expression` | A Python expression that when evaluated in the context of the loaded file returns the version. The default expression is simply `__version__`. |\n| `search-paths` | A list of relative paths to directories that will be prepended to Python's search path |\n\n## Missing imports\n\nIf the chosen path imports another module in your project, then you'll need to use absolute imports coupled with the `search-paths` option. For example, say you need to load the following file:\n\n```python tab=\"src/pkg/\\_\\_init\\_\\_.py\"\n    from ._version import get_version\n\n    __version__ = get_version()\n```\n\nYou should change it to:\n\n```python tab=\"src/pkg/\\_\\_init\\_\\_.py\"\n    from pkg._version import get_version\n\n    __version__ = get_version()\n```\n\nand the configuration would become:\n\n```toml config-example\n[tool.hatch.version]\nsource = \"code\"\npath = \"src/pkg/__init__.py\"\nsearch-paths = [\"src\"]\n```\n","docs/plugins/version-source/env.md":"# Environment version source\n\n-----\n\nRetrieves the version from an environment variable. This can be useful in build pipelines where the version is set by an external trigger.\n\n## Updates\n\nSetting the version is not supported.\n\n## Configuration\n\nThe version source plugin name is `env`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"env\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `variable` (required) | The name of the environment variable |\n","docs/plugins/version-source/reference.md":"# Version source plugins\n\n-----\n\n## Known third-party\n\n- [hatch-vcs](https://github.com/ofek/hatch-vcs) - uses your preferred version control system (like Git)\n- [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version) - uses the `version` field of NodeJS `package.json` files\n- [hatch-regex-commit](https://github.com/frankie567/hatch-regex-commit) - automatically creates a Git commit and tag after version bumping\n- [versioningit](https://github.com/jwodder/versioningit) - determines version from Git or Mercurial tags, with customizable version formatting\n\n::: hatchling.version.source.plugin.interface.VersionSourceInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - get_version_data\n      - set_version\n","docs/plugins/version-source/regex.md":"# Regex version source\n\n-----\n\nSee the documentation for [versioning](../../version.md).\n\n## Updates\n\nSetting the version is supported.\n\n## Configuration\n\nThe version source plugin name is `regex`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"regex\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to a file containing the project's version |\n| `pattern` | A regular expression that has a named group called `version` that represents the version. The default pattern looks for a variable named `__version__` or `VERSION` that is set to a string containing the version, optionally prefixed with the lowercase letter `v`. |\n"},"items":[{"name":"testing-builds.md","path":"docs/how-to/plugins/testing-builds.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/how-to/plugins/testing-builds.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Testing build plugins\n\n-----\n\nFor testing [Hatchling plugins](../../plugins/about.md#hatchling), you'll usually want to generate a project to execute builds as a real user would. For example, as a minimal [pytest](https://github.com/pytest-dev/pytest) fixture:\n\n```python\nfrom pathlib import Path\n\nimport pytest\n\n\n@pytest.fixture\ndef new_project(tmp_path):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {Path.cwd().as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n```\n\nThe issue with this is that after the first test session, the project will be forever cached by pip based on the file path. Therefore, subsequent tests runs will never use updated code.\n\nTo invalidate the cache, copy your code to a new path for every test session:\n\n```python\nimport shutil\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\n\nimport pytest\n\n\n@pytest.fixture(scope='session')\ndef plugin_dir():\n    with TemporaryDirectory() as d:\n        directory = Path(d, 'plugin')\n        shutil.copytree(\n            Path.cwd(), directory, ignore=shutil.ignore_patterns('.git')\n        )\n\n        yield directory.resolve()\n\n\n@pytest.fixture\ndef new_project(tmp_path, plugin_dir):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {plugin_dir.as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n```\n\n!!! note\n    This example chooses to ignore copying `.git` for performance reasons. You may want to ignore more patterns, or copy only specific paths like [this plugin](https://github.com/hynek/hatch-fancy-pypi-readme/blob/main/tests/conftest.py) does.\n","isInternal":false,"tokens":490,"sizeBytes":2049},{"name":"about.md","path":"docs/plugins/about.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/about.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins\n\n-----\n\nHatch utilizes [pluggy](https://github.com/pytest-dev/pluggy) for its plugin functionality.\n\n## Overview\n\nAll plugins provide registration hooks that return one or more classes that inherit from a particular [type](#types) interface.\n\nEach registration hook must be decorated by Hatch's hook marker. For example, if you wanted to create a new kind of environment you could do:\n\n```python tab=\"hooks.py\"\nfrom hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialEnvironment\n\n\n@hookimpl\ndef hatch_register_environment():\n    return SpecialEnvironment\n```\n\nThe hooks can return a single class or a list of classes.\n\nEvery class must define an attribute called `PLUGIN_NAME` that users will select when they wish to use the plugin. So in the example above, the class might be defined like:\n\n```python tab=\"plugin.py\"\n...\nclass SpecialEnvironment(...):\n    PLUGIN_NAME = 'special'\n    ...\n```\n\n## Project configuration\n\n### Naming\n\nIt is recommended that plugin project names are prefixed with `hatch-`. For example, if you wanted to make a plugin that provides some functionality for a product named `foo` you might do:\n\n```toml tab=\"pyproject.toml\"\n[project]\nname = \"hatch-foo\"\n```\n\n### Discovery\n\nYou'll need to define your project as a [Python plugin](../config/metadata.md#plugins) for Hatch:\n\n```toml tab=\"pyproject.toml\"\n[project.entry-points.hatch]\nfoo = \"pkg.hooks\"\n```\n\nThe name of the plugin should be the project name (excluding any `hatch-` prefix) and the path should represent the module that contains the registration hooks.\n\n### Classifier\n\nAdd [`Framework :: Hatch`](https://pypi.org/search/?c=Framework+%3A%3A+Hatch) to your project's [classifiers](../config/metadata.md#classifiers) to make it easy to search for Hatch plugins:\n\n```toml tab=\"pyproject.toml\"\n[project]\nclassifiers = [\n  ...\n  \"Framework :: Hatch\",\n  ...\n]\n```\n\n## Types\n\n### Hatchling\n\nThese are all involved in building projects and therefore any defined dependencies are automatically installed in each build environment.\n\n- [Builder](builder/reference.md)\n- [Build hook](build-hook/reference.md)\n- [Metadata hook](metadata-hook/reference.md)\n- [Version source](version-source/reference.md)\n- [Version scheme](version-scheme/reference.md)\n\n### Hatch\n\nThese must be installed in the same environment as Hatch itself.\n\n- [Environment](environment/reference.md)\n- [Environment collector](environment-collector/reference.md)\n- [Dependency locker](locker.md)\n- [Publisher](publisher/reference.md)\n","isInternal":false,"tokens":561,"sizeBytes":2501},{"name":"custom.md","path":"docs/plugins/build-hook/custom.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/build-hook/custom.md","title":"Build-hook Skill","category":"anthropic-skill","format":"markdown","content":"# Custom build hook\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [BuildHookInterface](reference.md#hatchling.builders.hooks.plugin.interface.BuildHookInterface).\n\n## Configuration\n\nThe build hook plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.build.hooks.custom]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.builders.hooks.plugin.interface import BuildHookInterface\n\n\nclass CustomBuildHook(BuildHookInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_build_hook` that returns the desired build hook.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.builders.hooks.plugin.interface.BuildHookInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","isInternal":false,"tokens":216,"sizeBytes":958},{"name":"reference.md","path":"docs/plugins/build-hook/reference.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/build-hook/reference.md","title":"Build-hook Skill","category":"anthropic-skill","format":"markdown","content":"# Build hook plugins\n\n-----\n\nA build hook provides code that will be executed at various stages of the build process. See the documentation for [build hook configuration](../../config/build.md#build-hooks).\n\n## Known third-party\n\n- [hatch-argparse-manpage](https://github.com/damonlynch/hatch-argparse-manpage) - generate man pages for [argparse](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser)-based CLIs\n- [hatch-autorun](https://github.com/ofek/hatch-autorun) - used to inject code into an installation that will automatically run before the first import\n- [hatch-build-scripts](https://github.com/rmorshea/hatch-build-scripts) - run arbitrary shell commands that create artifacts\n- [hatch-cython](https://github.com/joshua-auchincloss/hatch-cython) - build [Cython](https://github.com/cython/cython) extensions\n- [hatch-gettext](https://github.com/damonlynch/hatch-gettext) - compiles multi-lingual messages with GNU `gettext` tools\n- [hatch-jupyter-builder](https://github.com/jupyterlab/hatch-jupyter-builder) - used for packages in the Project Jupyter ecosystem\n- [hatch-mypyc](https://github.com/ofek/hatch-mypyc) - compiles code with [Mypyc](https://github.com/mypyc/mypyc)\n- [hatch-odoo](https://github.com/acsone/hatch-odoo) - package Odoo add-ons into the appropriate namespace\n- [hatch-project-name](https://github.com/valentinoli/hatch-project-name/) - writes the project name to a file\n- [scikit-build-core](https://github.com/scikit-build/scikit-build-core) - build extension modules with CMake\n\n## Overview\n\nBuild hooks run for every selected [version](../../config/build.md#versions) of build targets.\n\nThe [initialization](#hatchling.builders.hooks.plugin.interface.BuildHookInterface.initialize) stage occurs immediately before each build and the [finalization](#hatchling.builders.hooks.plugin.interface.BuildHookInterface.finalize) stage occurs immediately after. Each stage has the opportunity to view or modify [build data](#build-data).\n\n## Build data\n\nBuild data is a simple mapping whose contents can influence the behavior of builds. Which fields exist and are recognized depends on each build target.\n\nThe following fields are always present and recognized by the build system itself:\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `artifacts` | `#!python list[str]` | This is a list of extra [`artifact` patterns](../../config/build.md#artifacts) and should generally only be appended to |\n| `force_include` | `#!python dict[str, str]` | This is a mapping of extra [forced inclusion paths](../../config/build.md#forced-inclusion), with this mapping taking precedence in case of conflicts |\n| `build_hooks` | `#!python tuple[str, ...]` | This is an immutable sequence of the names of the configured build hooks and matches the order in which they run |\n\n!!! attention\n    While user-facing TOML options are hyphenated, build data fields should be named with underscores to allow plugins to use them as valid Python identifiers.\n\n## Notes\n\nIn some cases it may be necessary to use `force_include` rather than `artifacts`. For example, say that you want to install a `lib.so` directly at the root of `site-packages` and a project defines a [package](../../config/build.md#packages) `src/foo`. If you create `src/lib.so`, there will never be a match because the directory traversal starts at `src/foo` rather than `src`. In that case you must do either:\n\n```python\nbuild_data['force_include']['src/lib.so'] = 'src/lib.so'\n```\n\nor\n\n```python\nbuild_data['force_include']['/absolute/path/to/src/lib.so'] = 'src/lib.so'\n```\n\n::: hatchling.builders.hooks.plugin.interface.BuildHookInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - config\n      - build_config\n      - target_name\n      - directory\n      - dependencies\n      - clean\n      - initialize\n      - finalize\n","isInternal":false,"tokens":929,"sizeBytes":3862},{"name":"version.md","path":"docs/plugins/build-hook/version.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/build-hook/version.md","title":"Build-hook Skill","category":"anthropic-skill","format":"markdown","content":"# Version build hook\n\n-----\n\nThis writes the project's version to a file.\n\n## Configuration\n\nThe build hook plugin name is `version`.\n\n```toml config-example\n[tool.hatch.build.hooks.version]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.version]\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to the desired file |\n| `template` | A string representing the entire contents of `path` that will be formatted with a `version` variable |\n| `pattern` | Rather than updating the entire file, a regular expression may be used that has a named group called `version` that represents the version. If set to `true`, a pattern will be used that looks for a variable named `__version__` or `VERSION` that is set to a string containing the version, optionally prefixed with the lowercase letter `v`. |\n","isInternal":false,"tokens":191,"sizeBytes":835},{"name":"binary.md","path":"docs/plugins/builder/binary.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/builder/binary.md","title":"Builder Skill","category":"anthropic-skill","format":"markdown","content":"# Binary builder\n\n-----\n\nThis uses [PyApp](https://github.com/ofek/pyapp) to build an application that is able to bootstrap itself at runtime.\n\n!!! note\n    This requires an installation of [Rust](https://www.rust-lang.org).\n\n## Configuration\n\nThe builder plugin name is `binary`.\n\n```toml config-example\n[tool.hatch.build.targets.binary]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `scripts` | all defined | An array of defined [script](../../config/metadata.md#cli) names to limit what gets built |\n| `python-version` | latest compatible Python minor version | The [Python version ID](https://ofek.dev/pyapp/latest/config/#known) to use |\n| `pyapp-version` | | The version of PyApp to use |\n\n## Build behavior\n\nIf any [scripts](../../config/metadata.md#cli) are defined then each one will be built (limited by the `scripts` option). Otherwise, a single executable will be built based on the project name assuming there is an equivalently named module with a `__main__.py` file.\n\nEvery executable will be built inside an `app` directory in the [output directory](../../config/build.md#output-directory).\n\nIf the `CARGO` environment variable is set then that path will be used as the executable for performing builds.\n\nIf the [`CARGO_BUILD_TARGET`](https://doc.rust-lang.org/cargo/reference/config.html#buildtarget) environment variable is set then its value will be appended to the file name stems.\n\nIf the `PYAPP_REPO` environment variable is set then a local build will be performed inside that directory rather than installing from [crates.io](https://crates.io). Note that this is [required](https://github.com/cross-rs/cross/issues/1215) if the `CARGO` environment variable refers to [cross](https://github.com/cross-rs/cross).\n","isInternal":false,"tokens":415,"sizeBytes":1764},{"name":"custom.md","path":"docs/plugins/builder/custom.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/builder/custom.md","title":"Builder Skill","category":"anthropic-skill","format":"markdown","content":"# Custom builder\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [BuilderInterface](reference.md#hatchling.builders.plugin.interface.BuilderInterface).\n\n## Configuration\n\nThe builder plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.build.targets.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.builders.plugin.interface import BuilderInterface\n\n\nclass CustomBuilder(BuilderInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_builder` that returns the desired builder.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.builders.plugin.interface.BuilderInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","isInternal":false,"tokens":185,"sizeBytes":864},{"name":"reference.md","path":"docs/plugins/builder/reference.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/builder/reference.md","title":"Builder Skill","category":"anthropic-skill","format":"markdown","content":"# Builder plugins\n\n-----\n\nSee the documentation for [build configuration](../../config/build.md).\n\n## Known third-party\n\n- [hatch-aws](https://github.com/aka-raccoon/hatch-aws) - used for building AWS Lambda functions with SAM\n- [hatch-zipped-directory](https://github.com/dairiki/hatch-zipped-directory) - used for building ZIP archives for installation into various foreign package installation systems\n\n::: hatchling.builders.plugin.interface.BuilderInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - build_config\n      - target_config\n      - config\n      - get_config_class\n      - get_version_api\n      - get_default_versions\n      - clean\n      - recurse_included_files\n      - get_default_build_data\n","isInternal":false,"tokens":169,"sizeBytes":748},{"name":"sdist.md","path":"docs/plugins/builder/sdist.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/builder/sdist.md","title":"Builder Skill","category":"anthropic-skill","format":"markdown","content":"# Source distribution builder\n\n-----\n\nA source distribution, or `sdist`, is an archive of Python \"source code\". Although largely unspecified, by convention it should include everything that is required to build a [wheel](wheel.md) without making network requests.\n\n## Configuration\n\nThe builder plugin name is `sdist`.\n\n```toml config-example\n[tool.hatch.build.targets.sdist]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `core-metadata-version` | `\"2.4\"` | The version of [core metadata](https://packaging.python.org/specifications/core-metadata/) to use |\n| `strict-naming` | `true` | Whether or not file names should contain the normalized version of the project name |\n| `support-legacy` | `false` | Whether or not to include a `setup.py` file to support legacy installation mechanisms |\n\n## Versions\n\n| Version | Description |\n| --- | --- |\n| `standard` (default) | The latest conventional format |\n\n## Default file selection\n\nWhen the user has not set any [file selection](../../config/build.md#file-selection) options, all files that are not [ignored by your VCS](../../config/build.md#vcs) will be included.\n\n!!! note\n    The following files are always included and cannot be excluded:\n\n    - `/pyproject.toml`\n    - `/hatch.toml`\n    - `/hatch_build.py`\n    - `/.gitignore` or `/.hgignore`\n    - Any defined [`readme`](../../config/metadata.md#readme) file\n    - All defined [`license-files`](../../config/metadata.md#license)\n\n## Reproducibility\n\n[Reproducible builds](../../config/build.md#reproducible-builds) are supported.\n\n## Build data\n\nThis is data that can be modified by [build hooks](../build-hook/reference.md).\n\n| Data | Default | Description |\n| --- | --- | --- |\n| `dependencies` | | Extra [project dependencies](../../config/metadata.md#required) |\n","isInternal":false,"tokens":430,"sizeBytes":1802},{"name":"wheel.md","path":"docs/plugins/builder/wheel.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/builder/wheel.md","title":"Builder Skill","category":"anthropic-skill","format":"markdown","content":"# Wheel builder\n\n-----\n\nA [wheel](https://packaging.python.org/specifications/binary-distribution-format/) is a binary distribution of a Python package that can be installed directly into an environment.\n\n## Configuration\n\nThe builder plugin name is `wheel`.\n\n```toml config-example\n[tool.hatch.build.targets.wheel]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `core-metadata-version` | `\"2.4\"` | The version of [core metadata](https://packaging.python.org/specifications/core-metadata/) to use |\n| `shared-data` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to the `data` subdirectory within the standard [data directory](https://packaging.python.org/en/latest/specifications/binary-distribution-format/#the-data-directory) that will be installed globally in a given Python environment, usually under `#!python sys.prefix` |\n| `shared-scripts` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to the `scripts` subdirectory within the standard [data directory](https://packaging.python.org/en/latest/specifications/binary-distribution-format/#the-data-directory) that will be installed in a given Python environment, usually under `Scripts` on Windows or `bin` otherwise, and would normally be available on PATH |\n| `extra-metadata` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to extra [metadata](https://peps.python.org/pep-0427/#the-dist-info-directory) that will be shipped in a directory named `extra_metadata` |\n| `strict-naming` | `true` | Whether or not file names should contain the normalized version of the project name |\n| `macos-max-compat` | `false` | Whether or not on macOS, when build hooks have set the `infer_tag` [build data](#build-data), the wheel name should signal broad support rather than specific versions for newer SDK versions.<br><br>Note: This option will eventually be removed. |\n| `bypass-selection` | `false` | Whether or not to suppress the error when one has not defined any file selection options and all heuristics have failed to determine what to ship |\n| `sbom-files` | | A list of paths to [Software Bill of Materials](https://peps.python.org/pep-0770/) files that will be included in the `.dist-info/sboms/` directory of the wheel |\n\n!!! note\n    Many build frontends will build the wheel from a source distribution. This is the recommended approach, but it means you need to ensure the SBOM files passed to `sbom-files` are also [included in the source distribution](https://hatch.pypa.io/latest/config/build/#file-selection).\n\n## Versions\n\n| Version | Description |\n| --- | --- |\n| `standard` (default) | The latest standardized format |\n| `editable` | A wheel that only ships `.pth` files or import hooks for real-time development |\n\n## Default file selection\n\nWhen the user has not set any [file selection](../../config/build.md#file-selection) options, the [project name](../../config/metadata.md#name) will be used to determine the package to ship in the following heuristic order:\n\n1. `<NAME>/__init__.py`\n2. `src/<NAME>/__init__.py`\n3. `<NAME>.py`\n4. `<NAMESPACE>/<NAME>/__init__.py`\n\nIf none of these heuristics are satisfied, an error will be raised.\n\n## Reproducibility\n\n[Reproducible builds](../../config/build.md#reproducible-builds) are supported.\n\n## Build data\n\nThis is data that can be modified by [build hooks](../build-hook/reference.md).\n\n| Data | Default | Description |\n| --- | --- | --- |\n| `tag` | | The full [tag](https://peps.python.org/pep-0425/) part of the filename (e.g. `py3-none-any`), defaulting to a cross-platform wheel with the supported major versions of Python based on [project metadata](../../config/metadata.md#python-support) |\n| `infer_tag` | `#!python False` | When `tag` is not set, this may be enabled to use the one most specific to the platform, Python interpreter, and ABI |\n| `pure_python` | `#!python True` | Whether or not to write metadata indicating that the package does not contain any platform-specific files |\n| `dependencies` | | Extra [project dependencies](../../config/metadata.md#required) |\n| `shared_data` | | Additional [`shared-data`](#options) entries, which take precedence in case of conflicts |\n| `shared_scripts` | | Additional [`shared-scripts`](#options) entries, which take precedence in case of conflicts |\n| `extra_metadata` | | Additional [`extra-metadata`](#options) entries, which take precedence in case of conflicts |\n| `force_include_editable` | | Similar to the [`force_include` option](../build-hook/reference.md#build-data) but specifically for the `editable` [version](#versions) and takes precedence |\n| `sbom_files` | | This is a list of the sbom files that should be included under `.dist-info/sboms`. |\n","isInternal":false,"tokens":1133,"sizeBytes":4852},{"name":"custom.md","path":"docs/plugins/environment-collector/custom.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/environment-collector/custom.md","title":"Environment-collector Skill","category":"anthropic-skill","format":"markdown","content":"# Custom environment collector\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [EnvironmentCollectorInterface](reference.md#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface).\n\n## Configuration\n\nThe environment collector plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.env.collectors.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_plugins.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_plugins.py\"\n    from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface\n\n\n    class CustomEnvironmentCollector(EnvironmentCollectorInterface):\n        ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_environment_collector` that returns the desired environment collector.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","isInternal":false,"tokens":203,"sizeBytes":1021},{"name":"default.md","path":"docs/plugins/environment-collector/default.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/environment-collector/default.md","title":"Environment-collector Skill","category":"anthropic-skill","format":"markdown","content":"# Default environment collector\n\n-----\n\nThis adds the `default` environment with [type](../../config/environment/overview.md#type) set to [virtual](../environment/virtual.md) and will always be applied.\n\n## Configuration\n\nThe environment collector plugin name is `default`.\n\n```toml config-example\n[tool.hatch.env.collectors.default]\n```\n\n## Options\n\nThere are no options available currently.\n","isInternal":false,"tokens":82,"sizeBytes":393},{"name":"reference.md","path":"docs/plugins/environment-collector/reference.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/environment-collector/reference.md","title":"Environment-collector Skill","category":"anthropic-skill","format":"markdown","content":"# Environment collector plugins\n\n-----\n\nEnvironment collectors allow for dynamically modifying environments or adding environments beyond those defined in config. Users can override default values provided by each environment.\n\n## Known third-party\n\n- [hatch-mkdocs](https://github.com/mkdocs/hatch-mkdocs) - integrate [MkDocs](https://github.com/mkdocs/mkdocs) and infer dependencies into an env\n\n## Installation\n\nAny required environment collectors that are not built-in must be manually installed alongside Hatch or listed in the `tool.hatch.env.requires` array for automatic management:\n\n```toml config-example\n[tool.hatch.env]\nrequires = [\n  \"...\",\n]\n```\n\n::: hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - get_initial_config\n      - finalize_config\n      - finalize_environments\n","isInternal":false,"tokens":186,"sizeBytes":890},{"name":"reference.md","path":"docs/plugins/environment/reference.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/environment/reference.md","title":"Environment Skill","category":"anthropic-skill","format":"markdown","content":"# Environment plugins\n\n-----\n\nSee the documentation for [environment configuration](../../config/environment/overview.md).\n\n## Known third-party\n\n- [hatch-conda](https://github.com/OldGrumpyViking/hatch-conda) - environments backed by Conda/Mamba\n- [hatch-containers](https://github.com/ofek/hatch-containers) - environments run inside containers\n- [hatch-pip-compile](https://github.com/juftin/hatch-pip-compile) - use [pip-compile](https://github.com/jazzband/pip-tools) to manage project dependencies and lockfiles\n- [hatch-pip-deepfreeze](https://github.com/sbidoul/hatch-pip-deepfreeze) - [virtual](virtual.md) environments with dependency locking by [pip-deepfreeze](https://github.com/sbidoul/pip-deepfreeze)\n\n## Installation\n\nAny required environment types that are not built-in must be manually installed alongside Hatch or listed in the `tool.hatch.env.requires` array for automatic management:\n\n```toml config-example\n[tool.hatch.env]\nrequires = [\n  \"...\",\n]\n```\n\n## Life cycle\n\nWhenever an environment is used, the following logic is performed:\n\n::: hatch.project.core.Project.prepare_environment\n    options:\n      show_root_heading: false\n      show_root_toc_entry: false\n\n## Build environments\n\nAll environment types should [offer support](#hatch.env.plugin.interface.EnvironmentInterface.fs_context) for synchronized storage between the local file system and the environment. This functionality is used in the following scenarios:\n\n- the [`build`](../../cli/reference.md#hatch-build) command\n- commands that read dependencies, like [`dep hash`](../../cli/reference.md#hatch-dep-hash), if any [project dependencies](../../config/metadata.md#dependencies) are [set dynamically](../../config/metadata.md#dynamic)\n\n::: hatch.env.plugin.interface.EnvironmentInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - find\n      - create\n      - remove\n      - exists\n      - install_project\n      - install_project_dev_mode\n      - dependencies_in_sync\n      - sync_dependencies\n      - dependency_hash\n      - project_dependencies\n      - project_root\n      - sep\n      - pathsep\n      - fs_context\n      - activate\n      - deactivate\n      - app_status_creation\n      - app_status_pre_installation\n      - app_status_post_installation\n      - app_status_project_installation\n      - app_status_dependency_state_check\n      - app_status_dependency_installation_check\n      - app_status_dependency_synchronization\n      - app\n      - root\n      - name\n      - data_directory\n      - isolated_data_directory\n      - config\n      - platform\n      - environment_dependencies\n      - dependencies\n      - sources\n      - get_source_install_args\n      - env_vars\n      - env_include\n      - env_exclude\n      - platforms\n      - skip_install\n      - dev_mode\n      - description\n      - command_context\n      - enter_shell\n      - run_shell_command\n      - resolve_commands\n      - get_env_vars\n      - apply_features\n      - construct_pip_install_command\n      - join_command_args\n      - check_compatibility\n      - get_option_types\n      - get_env_var_option\n      - get_context\n\n## Dependency lockers\n\n**Dependency lockers** are implemented: register classes with `hatch_register_locker` (see [Dependency locker plugins](../locker.md)). They stay **decoupled** from environment plugins—no subclassing [`EnvironmentInterface`](#hatch.env.plugin.interface.EnvironmentInterface) just to change locking—and call the environment’s **public API** (for example [`command_context`](#hatch.env.plugin.interface.EnvironmentInterface.command_context) and [`platform`](../utilities.md)).\n\nFor moving artifacts between the workspace and the environment, custom lockers should prefer [`fs_context`](#hatch.env.plugin.interface.EnvironmentInterface.fs_context) and [`FileSystemContext`](../utilities.md#hatch.env.plugin.interface.FileSystemContext) over ad hoc I/O.\n\nEnd-user commands: [How to use lockfiles](../../how-to/environment/lockfiles.md).\n","isInternal":false,"tokens":872,"sizeBytes":3957},{"name":"virtual.md","path":"docs/plugins/environment/virtual.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/environment/virtual.md","title":"Environment Skill","category":"anthropic-skill","format":"markdown","content":"# Virtual environment\n\n-----\n\nThis uses virtual environments backed by [virtualenv](https://github.com/pypa/virtualenv) or [UV](https://github.com/astral-sh/uv).\n\n## Configuration\n\nThe environment plugin name is `virtual`.\n\n```toml config-example\n[tool.hatch.envs.<ENV_NAME>]\ntype = \"virtual\"\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `python` | | The version of Python to find on your system and subsequently use to create the environment, defaulting to the `HATCH_PYTHON` environment variable, followed by the [normal resolution logic](#python-resolution). Setting the `HATCH_PYTHON` environment variable to `self` will force the use of the Python executable Hatch is running on. For more information, see the [documentation](https://virtualenv.pypa.io/en/latest/user_guide.html#python-discovery). |\n| `python-sources` | `['external', 'internal']` | This may be set to an array of strings that are either the literal `internal` or `external`. External considers only Python executables that are already on `PATH`. Internal considers only [internally managed Python distributions](#internal-distributions). |\n| `path` | | An explicit path to the virtual environment. The path may be absolute or relative to the project root. Any environments that [inherit](../../config/environment/overview.md#inheritance) this option will also use this path. The environment variable `HATCH_ENV_TYPE_VIRTUAL_PATH` may be used, which will take precedence. |\n| `system-packages` | `false` | Whether or not to give the virtual environment access to the system `site-packages` directory |\n| `installer` | `pip` | When set to `uv`, [UV](https://github.com/astral-sh/uv) will be used in place of virtualenv & pip for virtual environment creation and dependency management, respectively. If you intend to provide UV yourself, you may set the `HATCH_ENV_TYPE_VIRTUAL_UV_PATH` environment variable which should be the absolute path to a UV binary. This environment variable implicitly sets the `installer` option to `uv` (if unset). |\n\n## Location\n\nThe [location](../../cli/reference.md#hatch-env-find) of environments is determined in the following heuristic order:\n\n1. The `path` option\n2. A directory named after the environment within the configured `virtual` [environment directory](../../config/hatch.md#environments) if the directory resides somewhere within the project root or if it is set to a `.virtualenvs` directory within the user's home directory\n3. Otherwise, environments are stored within the configured `virtual` [environment directory](../../config/hatch.md#environments) in a deeply nested structure in order to support multiple projects\n\nAdditionally, when the `path` option is not used, the name of the directory for the `default` environment will be the normalized project name to provide a more meaningful default [shell](../../cli/reference.md#hatch-shell) prompt.\n\n## Python resolution\n\nVirtual environments necessarily require a parent installation of Python. The following rules determine how the parent is resolved.\n\nThe Python choice is determined by the [`python` option](#options) followed by the `HATCH_PYTHON` environment variable. If the choice is via the environment variable, then resolution stops and that path is used unconditionally.\n\nThe resolvers will be based on the [`python-sources` option](#options) and all resolved interpreters will ensure compatibility with the project's defined [Python support](../../config/metadata.md#python-support).\n\nIf a Python version has been chosen then each resolver will try to find an interpreter that satisfies that version.\n\nIf no version has been chosen, then each resolver will try to find a version that matches the version of Python that Hatch is currently running on. If not found then each resolver will try to find the highest compatible version.\n\n!!! note\n    Some external Python paths are considered unstable and are ignored during resolution. For example, if Hatch is installed via Homebrew then `sys.executable` will be ignored because the interpreter could change or be removed at any time.\n\n!!! note\n    When resolution finds a match using an [internally managed distribution](#internal-distributions) and an update is available, the latest distribution will automatically be downloaded before environment creation.\n\n## Internal distributions\n\nThe following options are recognized for internal Python resolution.\n\n!!! tip\n    You can set custom sources for distributions by setting the `HATCH_PYTHON_SOURCE_<NAME>` environment variable where `<NAME>` is the uppercased version of the distribution name with periods replaced by underscores e.g. `HATCH_PYTHON_SOURCE_PYPY3_10`.\n\n### CPython\n\n| NAME |\n| --- |\n| `3.7` |\n| `3.8` |\n| `3.9` |\n| `3.10` |\n| `3.11` |\n| `3.12` |\n| `3.13` |\n| `3.14` |\n| `3.15` |\n\nThe source of distributions is the [python-build-standalone](https://github.com/indygreg/python-build-standalone) project.\n\nSome distributions have [variants](https://gregoryszorc.com/docs/python-build-standalone/main/running.html) that may be configured with environment variables. Options may be combined.\n\n| Option | Platforms | Allowed values |\n| --- | --- | --- |\n| `HATCH_PYTHON_VARIANT_CPU` | <ul><li>Linux</li></ul> | <ul><li><code>v1</code></li><li><code>v2</code></li><li><code>v3</code> (default)</li><li><code>v4</code></li></ul> |\n| `HATCH_PYTHON_VARIANT_GIL` | <ul><li>Linux</li><li>Windows</li><li>macOS</li></ul> | <ul><li><code>freethreaded</code></li></ul> |\n\n### PyPy\n\n| NAME |\n| --- |\n| `pypy2.7` |\n| `pypy3.9` |\n| `pypy3.10` |\n| `pypy3.11` |\n\nThe source of distributions is the [PyPy](https://www.pypy.org) project.\n\n## Troubleshooting\n\n### macOS SIP\n\nIf you need to set linker environment variables like those starting with `DYLD_` or `LD_`, any executable secured by [System Integrity Protection](https://en.wikipedia.org/wiki/System_Integrity_Protection) that is invoked when [running commands](../../environment.md#command-execution) will not see those environment variable modifications as macOS strips those.\n\nHatch interprets such commands as shell commands but deliberately ignores such paths to protected shells. This workaround suffices for the majority of use cases but there are 2 situations in which it may not:\n\n1. There are no unprotected `sh`, `bash`, `zsh`, nor `fish` executables found along PATH.\n2. The desired executable is a project's [script](../../config/metadata.md#cli), and the [location](#location) of environments contains spaces or is longer than 124[^1] characters. In this case `pip` and other installers will create such an entry point with a shebang pointing to `/bin/sh` (which is protected) to avoid shebang limitations. Rather than changing the location, you could invoke the script as e.g. `python -m pytest` (if the project supports that method of invocation by shipping a `__main__.py`).\n\n[^1]: The shebang length limit is [usually](https://web.archive.org/web/20221231220856/https://www.in-ulm.de/~mascheck/various/shebang/#length) 127 but 3 characters surround the executable path: `#!<EXE_PATH>\\n`\n","isInternal":false,"tokens":1653,"sizeBytes":7071},{"name":"locker.md","path":"docs/plugins/locker.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/locker.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Dependency locker plugins\n\n-----\n\nHatch selects a **locker** plugin to **generate** PEP 751 lockfiles, verify they are **in sync** with the configured dependency inputs, and **apply** them when syncing a `locked` environment. Built-in lockers are **`uv`** and **`pip`**, matching the [virtual environment installer](../how-to/environment/select-installer.md).\n\n**Dependency lockers** are registered with `hatch_register_locker` (see [Registration](#registration) below).\n\n## Registration\n\n```python tab=\"hooks.py\"\nfrom hatchling.plugin import hookimpl\n\nfrom .locker import MyLocker\n\n\n@hookimpl\ndef hatch_register_locker():\n    return MyLocker\n```\n\nExpose the module on the `hatch` entry point (see [Plugins — Discovery](about.md#discovery)) and list the distribution under [`tool.hatch.env.requires`](environment/reference.md#installation) when the plugin is not installed globally.\n\n## Configuration\n\n- Global default: [`tool.hatch.locker`](../config/environment/overview.md#locker) (string plugin name).\n- Per environment: [`tool.hatch.envs.<name>.locker`](../config/environment/overview.md#locker) overrides the global value.\n- If unset, Hatch picks `uv` when the environment uses the UV installer, otherwise `pip`.\n\n## Built-in lockers\n\n| `PLUGIN_NAME` | When selected | Notes |\n| ------------- | ------------- | ----- |\n| `uv` | Virtual env + UV installer | `uv pip compile` / `uv pip sync`; supports layered locks (extras, dependency-groups, `pyproject.toml`). |\n| `pip` | Any supported environment | `pip lock`; flat dependency list only (no layered extras/groups in the pip locker). `apply_lock` is a no-op — use UV for `locked` installs from a pylock today. |\n","isInternal":false,"tokens":390,"sizeBytes":1675},{"name":"custom.md","path":"docs/plugins/metadata-hook/custom.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/metadata-hook/custom.md","title":"Metadata-hook Skill","category":"anthropic-skill","format":"markdown","content":"# Custom metadata hook\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [MetadataHookInterface](reference.md#hatchling.metadata.plugin.interface.MetadataHookInterface).\n\n## Configuration\n\nThe metadata hook plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.metadata.hooks.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.metadata.plugin.interface import MetadataHookInterface\n\n\nclass CustomMetadataHook(MetadataHookInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_metadata_hook` that returns the desired build hook.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.metadata.plugin.interface.MetadataHookInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n","isInternal":false,"tokens":198,"sizeBytes":916},{"name":"reference.md","path":"docs/plugins/metadata-hook/reference.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/metadata-hook/reference.md","title":"Metadata-hook Skill","category":"anthropic-skill","format":"markdown","content":"# Metadata hook plugins\n\n-----\n\nMetadata hooks allow for the modification of [project metadata](../../config/metadata.md) after it has been loaded.\n\n## Known third-party\n\n- [hatch-docstring-description](https://github.com/flying-sheep/hatch-docstring-description) - set the project description using docstrings\n- [hatch-fancy-pypi-readme](https://github.com/hynek/hatch-fancy-pypi-readme) - dynamically construct the README\n- [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version) - uses fields from NodeJS `package.json` files\n- [hatch-odoo](https://github.com/acsone/hatch-odoo) - determine dependencies based on manifests of Odoo add-ons\n- [hatch-requirements-txt](https://github.com/repo-helper/hatch-requirements-txt) - read project dependencies from `requirements.txt` files\n- [UniDep](https://github.com/basnijholt/unidep) - for unified `pip` and `conda` dependency management using a single `requirements.yaml` file for both \n\n::: hatchling.metadata.plugin.interface.MetadataHookInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - update\n      - get_known_classifiers\n","isInternal":false,"tokens":280,"sizeBytes":1136},{"name":"package-index.md","path":"docs/plugins/publisher/package-index.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/publisher/package-index.md","title":"Publisher Skill","category":"anthropic-skill","format":"markdown","content":"# Index publisher\n\n-----\n\nSee the documentation for [publishing](../../publish.md).\n\n## Options\n\n| Flag | Config name | Description |\n| --- | --- | --- |\n| `-r`/`--repo` | `repo` | The repository with which to publish artifacts |\n| `-u`/`--user` | `user` | The user with which to authenticate |\n| `-a`/`--auth` | `auth` | The credentials to use for authentication |\n| `--ca-cert` | `ca-cert` | The path to a CA bundle |\n| `--client-cert` | `client-cert` | The path to a client certificate, optionally containing the private key |\n| `--client-key` | `client-key` | The path to the client certificate's private key |\n| | `repos` | A table of named [repositories](#repositories) to their respective options |\n\n## Configuration\n\nThe publisher plugin name is `index`.\n\n```toml tab=\"config.toml\"\n[publish.index]\n```\n\n### Repositories\n\nAll top-level options can be overridden per repository using the `repos` table\nwith a required `url` attribute for each repository. The following shows the\ndefault configuration:\n\n```toml tab=\"config.toml\"\n[publish.index.repos.main]\nurl = \"https://upload.pypi.org/legacy/\"\n\n[publish.index.repos.test]\nurl = \"https://test.pypi.org/legacy/\"\n```\n\nThe `repo` and `repos` options have no effect.\n\n### Confirmation prompt\n\nYou can require a confirmation prompt or use of the `-y`/`--yes` flag by\nsetting publishers' `disable` option to `true` in either Hatch's\n[config file](../../config/hatch.md) or project-specific configuration (which takes\nprecedence):\n\n```toml tab=\"config.toml\"\n[publish.index]\ndisable = true\n```\n\n```toml config-example\n[tool.hatch.publish.index]\ndisable = true\n```\n","isInternal":false,"tokens":413,"sizeBytes":1613},{"name":"reference.md","path":"docs/plugins/publisher/reference.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/publisher/reference.md","title":"Publisher Skill","category":"anthropic-skill","format":"markdown","content":"# Publisher plugins\n\n-----\n\n## Known third-party\n\n- [hatch-aws-publisher](https://github.com/aka-raccoon/hatch-aws-publisher) - publish AWS Lambda functions with SAM\n\n::: hatch.publish.plugin.interface.PublisherInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - cache_dir\n      - project_config\n      - plugin_config\n      - disable\n      - publish\n","isInternal":false,"tokens":95,"sizeBytes":389},{"name":"utilities.md","path":"docs/plugins/utilities.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/utilities.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugin utilities\n\n-----\n\n::: hatchling.builders.utils.get_reproducible_timestamp\n    options:\n      show_root_full_path: true\n\n::: hatchling.builders.config.BuilderConfig\n    options:\n      show_source: false\n      members:\n      - directory\n      - ignore_vcs\n      - reproducible\n      - dev_mode_dirs\n      - versions\n      - dependencies\n      - default_include\n      - default_exclude\n      - default_packages\n      - default_only_include\n\n::: hatchling.bridge.app.Application\n    options:\n      show_source: false\n      members:\n      - abort\n      - verbosity\n      - display_debug\n      - display_error\n      - display_info\n      - display_success\n      - display_waiting\n      - display_warning\n\n::: hatch.utils.platform.Platform\n    options:\n      show_source: false\n      members:\n      - format_for_subprocess\n      - run_command\n      - check_command\n      - check_command_output\n      - capture_process\n      - exit_with_command\n      - default_shell\n      - modules\n      - home\n      - name\n      - display_name\n      - windows\n      - macos\n      - linux\n\n::: hatch.env.context.EnvironmentContextFormatter\n    options:\n      show_source: false\n      members:\n      - formatters\n\n::: hatch.env.plugin.interface.FileSystemContext\n    options:\n      show_source: false\n      members:\n      - env\n      - sync_local\n      - sync_env\n      - local_path\n      - env_path\n      - join\n\n::: hatch.project.sources.Source\n    options:\n      show_source: false\n\n::: hatch.project.sources.PathSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.GitSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.UrlSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.IndexSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.WorkspaceSource\n    options:\n      show_source: false\n","isInternal":false,"tokens":423,"sizeBytes":1853},{"name":"reference.md","path":"docs/plugins/version-scheme/reference.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/version-scheme/reference.md","title":"Version-scheme Skill","category":"anthropic-skill","format":"markdown","content":"# Version scheme plugins\n\n-----\n\n## Known third-party\n\n- [hatch-calver](https://github.com/akx/hatch-calver) - uses [calendar versioning](https://calver.org)\n- [hatch-semver](https://github.com/Nagidal/hatch-semver) - uses [semantic versioning](https://semver.org)\n\n::: hatchling.version.scheme.plugin.interface.VersionSchemeInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - validate_bump\n      - update\n","isInternal":false,"tokens":116,"sizeBytes":448},{"name":"standard.md","path":"docs/plugins/version-scheme/standard.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/version-scheme/standard.md","title":"Version-scheme Skill","category":"anthropic-skill","format":"markdown","content":"# Standard version scheme\n\n-----\n\nSee the documentation for [versioning](../../version.md#updating).\n\n## Configuration\n\nThe version scheme plugin name is `standard`.\n\n```toml config-example\n[tool.hatch.version]\nscheme = \"standard\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `validate-bump` | When setting a specific version, this determines whether to check that the new version is higher than the original. The default is `true`. |\n","isInternal":false,"tokens":99,"sizeBytes":448},{"name":"code.md","path":"docs/plugins/version-source/code.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/version-source/code.md","title":"Version-source Skill","category":"anthropic-skill","format":"markdown","content":"# Code version source\n\n-----\n\n## Updates\n\nSetting the version is not supported.\n\n## Configuration\n\nThe version source plugin name is `code`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"code\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to a Python file or extension module that will be loaded |\n| `expression` | A Python expression that when evaluated in the context of the loaded file returns the version. The default expression is simply `__version__`. |\n| `search-paths` | A list of relative paths to directories that will be prepended to Python's search path |\n\n## Missing imports\n\nIf the chosen path imports another module in your project, then you'll need to use absolute imports coupled with the `search-paths` option. For example, say you need to load the following file:\n\n```python tab=\"src/pkg/\\_\\_init\\_\\_.py\"\n    from ._version import get_version\n\n    __version__ = get_version()\n```\n\nYou should change it to:\n\n```python tab=\"src/pkg/\\_\\_init\\_\\_.py\"\n    from pkg._version import get_version\n\n    __version__ = get_version()\n```\n\nand the configuration would become:\n\n```toml config-example\n[tool.hatch.version]\nsource = \"code\"\npath = \"src/pkg/__init__.py\"\nsearch-paths = [\"src\"]\n```\n","isInternal":false,"tokens":301,"sizeBytes":1255},{"name":"env.md","path":"docs/plugins/version-source/env.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/version-source/env.md","title":"Version-source Skill","category":"anthropic-skill","format":"markdown","content":"# Environment version source\n\n-----\n\nRetrieves the version from an environment variable. This can be useful in build pipelines where the version is set by an external trigger.\n\n## Updates\n\nSetting the version is not supported.\n\n## Configuration\n\nThe version source plugin name is `env`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"env\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `variable` (required) | The name of the environment variable |\n","isInternal":false,"tokens":102,"sizeBytes":468},{"name":"reference.md","path":"docs/plugins/version-source/reference.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/version-source/reference.md","title":"Version-source Skill","category":"anthropic-skill","format":"markdown","content":"# Version source plugins\n\n-----\n\n## Known third-party\n\n- [hatch-vcs](https://github.com/ofek/hatch-vcs) - uses your preferred version control system (like Git)\n- [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version) - uses the `version` field of NodeJS `package.json` files\n- [hatch-regex-commit](https://github.com/frankie567/hatch-regex-commit) - automatically creates a Git commit and tag after version bumping\n- [versioningit](https://github.com/jwodder/versioningit) - determines version from Git or Mercurial tags, with customizable version formatting\n\n::: hatchling.version.source.plugin.interface.VersionSourceInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - get_version_data\n      - set_version\n","isInternal":false,"tokens":189,"sizeBytes":768},{"name":"regex.md","path":"docs/plugins/version-source/regex.md","rawUrl":"https://raw.githubusercontent.com/pypa/hatch/HEAD/docs/plugins/version-source/regex.md","title":"Version-source Skill","category":"anthropic-skill","format":"markdown","content":"# Regex version source\n\n-----\n\nSee the documentation for [versioning](../../version.md).\n\n## Updates\n\nSetting the version is supported.\n\n## Configuration\n\nThe version source plugin name is `regex`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"regex\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to a file containing the project's version |\n| `pattern` | A regular expression that has a named group called `version` that represents the version. The default pattern looks for a variable named `__version__` or `VERSION` that is set to a string containing the version, optionally prefixed with the lowercase letter `v`. |\n","isInternal":false,"tokens":150,"sizeBytes":678}],"systemPromptSnippet":"<yakaai_skills repo=\"pypa/hatch\">\n<!-- File: docs/how-to/plugins/testing-builds.md (Tokens: ~490 | Category: anthropic-skill) -->\n# Testing build plugins\n\n-----\n\nFor testing [Hatchling plugins](../../plugins/about.md#hatchling), you'll usually want to generate a project to execute builds as a real user would. For example, as a minimal [pytest](https://github.com/pytest-dev/pytest) fixture:\n\n```python\nfrom pathlib import Path\n\nimport pytest\n\n\n@pytest.fixture\ndef new_project(tmp_path):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {Path.cwd().as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n```\n\nThe issue with this is that after the first test session, the project will be forever cached by pip based on the file path. Therefore, subsequent tests runs will never use updated code.\n\nTo invalidate the cache, copy your code to a new path for every test session:\n\n```python\nimport shutil\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\n\nimport pytest\n\n\n@pytest.fixture(scope='session')\ndef plugin_dir():\n    with TemporaryDirectory() as d:\n        directory = Path(d, 'plugin')\n        shutil.copytree(\n            Path.cwd(), directory, ignore=shutil.ignore_patterns('.git')\n        )\n\n        yield directory.resolve()\n\n\n@pytest.fixture\ndef new_project(tmp_path, plugin_dir):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {plugin_dir.as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n```\n\n!!! note\n    This example chooses to ignore copying `.git` for performance reasons. You may want to ignore more patterns, or copy only specific paths like [this plugin](https://github.com/hynek/hatch-fancy-pypi-readme/blob/main/tests/conftest.py) does.\n\n<!-- File: docs/plugins/about.md (Tokens: ~561 | Category: anthropic-skill) -->\n# Plugins\n\n-----\n\nHatch utilizes [pluggy](https://github.com/pytest-dev/pluggy) for its plugin functionality.\n\n## Overview\n\nAll plugins provide registration hooks that return one or more classes that inherit from a particular [type](#types) interface.\n\nEach registration hook must be decorated by Hatch's hook marker. For example, if you wanted to create a new kind of environment you could do:\n\n```python tab=\"hooks.py\"\nfrom hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialEnvironment\n\n\n@hookimpl\ndef hatch_register_environment():\n    return SpecialEnvironment\n```\n\nThe hooks can return a single class or a list of classes.\n\nEvery class must define an attribute called `PLUGIN_NAME` that users will select when they wish to use the plugin. So in the example above, the class might be defined like:\n\n```python tab=\"plugin.py\"\n...\nclass SpecialEnvironment(...):\n    PLUGIN_NAME = 'special'\n    ...\n```\n\n## Project configuration\n\n### Naming\n\nIt is recommended that plugin project names are prefixed with `hatch-`. For example, if you wanted to make a plugin that provides some functionality for a product named `foo` you might do:\n\n```toml tab=\"pyproject.toml\"\n[project]\nname = \"hatch-foo\"\n```\n\n### Discovery\n\nYou'll need to define your project as a [Python plugin](../config/metadata.md#plugins) for Hatch:\n\n```toml tab=\"pyproject.toml\"\n[project.entry-points.hatch]\nfoo = \"pkg.hooks\"\n```\n\nThe name of the plugin should be the project name (excluding any `hatch-` prefix) and the path should represent the module that contains the registration hooks.\n\n### Classifier\n\nAdd [`Framework :: Hatch`](https://pypi.org/search/?c=Framework+%3A%3A+Hatch) to your project's [classifiers](../config/metadata.md#classifiers) to make it easy to search for Hatch plugins:\n\n```toml tab=\"pyproject.toml\"\n[project]\nclassifiers = [\n  ...\n  \"Framework :: Hatch\",\n  ...\n]\n```\n\n## Types\n\n### Hatchling\n\nThese are all involved in building projects and therefore any defined dependencies are automatically installed in each build environment.\n\n- [Builder](builder/reference.md)\n- [Build hook](build-hook/reference.md)\n- [Metadata hook](metadata-hook/reference.md)\n- [Version source](version-source/reference.md)\n- [Version scheme](version-scheme/reference.md)\n\n### Hatch\n\nThese must be installed in the same environment as Hatch itself.\n\n- [Environment](environment/reference.md)\n- [Environment collector](environment-collector/reference.md)\n- [Dependency locker](locker.md)\n- [Publisher](publisher/reference.md)\n\n<!-- File: docs/plugins/build-hook/custom.md (Tokens: ~216 | Category: anthropic-skill) -->\n# Custom build hook\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [BuildHookInterface](reference.md#hatchling.builders.hooks.plugin.interface.BuildHookInterface).\n\n## Configuration\n\nThe build hook plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.build.hooks.custom]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.builders.hooks.plugin.interface import BuildHookInterface\n\n\nclass CustomBuildHook(BuildHookInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_build_hook` that returns the desired build hook.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.builders.hooks.plugin.interface.BuildHookInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n\n<!-- File: docs/plugins/build-hook/reference.md (Tokens: ~929 | Category: anthropic-skill) -->\n# Build hook plugins\n\n-----\n\nA build hook provides code that will be executed at various stages of the build process. See the documentation for [build hook configuration](../../config/build.md#build-hooks).\n\n## Known third-party\n\n- [hatch-argparse-manpage](https://github.com/damonlynch/hatch-argparse-manpage) - generate man pages for [argparse](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser)-based CLIs\n- [hatch-autorun](https://github.com/ofek/hatch-autorun) - used to inject code into an installation that will automatically run before the first import\n- [hatch-build-scripts](https://github.com/rmorshea/hatch-build-scripts) - run arbitrary shell commands that create artifacts\n- [hatch-cython](https://github.com/joshua-auchincloss/hatch-cython) - build [Cython](https://github.com/cython/cython) extensions\n- [hatch-gettext](https://github.com/damonlynch/hatch-gettext) - compiles multi-lingual messages with GNU `gettext` tools\n- [hatch-jupyter-builder](https://github.com/jupyterlab/hatch-jupyter-builder) - used for packages in the Project Jupyter ecosystem\n- [hatch-mypyc](https://github.com/ofek/hatch-mypyc) - compiles code with [Mypyc](https://github.com/mypyc/mypyc)\n- [hatch-odoo](https://github.com/acsone/hatch-odoo) - package Odoo add-ons into the appropriate namespace\n- [hatch-project-name](https://github.com/valentinoli/hatch-project-name/) - writes the project name to a file\n- [scikit-build-core](https://github.com/scikit-build/scikit-build-core) - build extension modules with CMake\n\n## Overview\n\nBuild hooks run for every selected [version](../../config/build.md#versions) of build targets.\n\nThe [initialization](#hatchling.builders.hooks.plugin.interface.BuildHookInterface.initialize) stage occurs immediately before each build and the [finalization](#hatchling.builders.hooks.plugin.interface.BuildHookInterface.finalize) stage occurs immediately after. Each stage has the opportunity to view or modify [build data](#build-data).\n\n## Build data\n\nBuild data is a simple mapping whose contents can influence the behavior of builds. Which fields exist and are recognized depends on each build target.\n\nThe following fields are always present and recognized by the build system itself:\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `artifacts` | `#!python list[str]` | This is a list of extra [`artifact` patterns](../../config/build.md#artifacts) and should generally only be appended to |\n| `force_include` | `#!python dict[str, str]` | This is a mapping of extra [forced inclusion paths](../../config/build.md#forced-inclusion), with this mapping taking precedence in case of conflicts |\n| `build_hooks` | `#!python tuple[str, ...]` | This is an immutable sequence of the names of the configured build hooks and matches the order in which they run |\n\n!!! attention\n    While user-facing TOML options are hyphenated, build data fields should be named with underscores to allow plugins to use them as valid Python identifiers.\n\n## Notes\n\nIn some cases it may be necessary to use `force_include` rather than `artifacts`. For example, say that you want to install a `lib.so` directly at the root of `site-packages` and a project defines a [package](../../config/build.md#packages) `src/foo`. If you create `src/lib.so`, there will never be a match because the directory traversal starts at `src/foo` rather than `src`. In that case you must do either:\n\n```python\nbuild_data['force_include']['src/lib.so'] = 'src/lib.so'\n```\n\nor\n\n```python\nbuild_data['force_include']['/absolute/path/to/src/lib.so'] = 'src/lib.so'\n```\n\n::: hatchling.builders.hooks.plugin.interface.BuildHookInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - config\n      - build_config\n      - target_name\n      - directory\n      - dependencies\n      - clean\n      - initialize\n      - finalize\n\n<!-- File: docs/plugins/build-hook/version.md (Tokens: ~191 | Category: anthropic-skill) -->\n# Version build hook\n\n-----\n\nThis writes the project's version to a file.\n\n## Configuration\n\nThe build hook plugin name is `version`.\n\n```toml config-example\n[tool.hatch.build.hooks.version]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.version]\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to the desired file |\n| `template` | A string representing the entire contents of `path` that will be formatted with a `version` variable |\n| `pattern` | Rather than updating the entire file, a regular expression may be used that has a named group called `version` that represents the version. If set to `true`, a pattern will be used that looks for a variable named `__version__` or `VERSION` that is set to a string containing the version, optionally prefixed with the lowercase letter `v`. |\n\n<!-- File: docs/plugins/builder/binary.md (Tokens: ~415 | Category: anthropic-skill) -->\n# Binary builder\n\n-----\n\nThis uses [PyApp](https://github.com/ofek/pyapp) to build an application that is able to bootstrap itself at runtime.\n\n!!! note\n    This requires an installation of [Rust](https://www.rust-lang.org).\n\n## Configuration\n\nThe builder plugin name is `binary`.\n\n```toml config-example\n[tool.hatch.build.targets.binary]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `scripts` | all defined | An array of defined [script](../../config/metadata.md#cli) names to limit what gets built |\n| `python-version` | latest compatible Python minor version | The [Python version ID](https://ofek.dev/pyapp/latest/config/#known) to use |\n| `pyapp-version` | | The version of PyApp to use |\n\n## Build behavior\n\nIf any [scripts](../../config/metadata.md#cli) are defined then each one will be built (limited by the `scripts` option). Otherwise, a single executable will be built based on the project name assuming there is an equivalently named module with a `__main__.py` file.\n\nEvery executable will be built inside an `app` directory in the [output directory](../../config/build.md#output-directory).\n\nIf the `CARGO` environment variable is set then that path will be used as the executable for performing builds.\n\nIf the [`CARGO_BUILD_TARGET`](https://doc.rust-lang.org/cargo/reference/config.html#buildtarget) environment variable is set then its value will be appended to the file name stems.\n\nIf the `PYAPP_REPO` environment variable is set then a local build will be performed inside that directory rather than installing from [crates.io](https://crates.io). Note that this is [required](https://github.com/cross-rs/cross/issues/1215) if the `CARGO` environment variable refers to [cross](https://github.com/cross-rs/cross).\n\n<!-- File: docs/plugins/builder/custom.md (Tokens: ~185 | Category: anthropic-skill) -->\n# Custom builder\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [BuilderInterface](reference.md#hatchling.builders.plugin.interface.BuilderInterface).\n\n## Configuration\n\nThe builder plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.build.targets.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.builders.plugin.interface import BuilderInterface\n\n\nclass CustomBuilder(BuilderInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_builder` that returns the desired builder.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.builders.plugin.interface.BuilderInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n\n<!-- File: docs/plugins/builder/reference.md (Tokens: ~169 | Category: anthropic-skill) -->\n# Builder plugins\n\n-----\n\nSee the documentation for [build configuration](../../config/build.md).\n\n## Known third-party\n\n- [hatch-aws](https://github.com/aka-raccoon/hatch-aws) - used for building AWS Lambda functions with SAM\n- [hatch-zipped-directory](https://github.com/dairiki/hatch-zipped-directory) - used for building ZIP archives for installation into various foreign package installation systems\n\n::: hatchling.builders.plugin.interface.BuilderInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - build_config\n      - target_config\n      - config\n      - get_config_class\n      - get_version_api\n      - get_default_versions\n      - clean\n      - recurse_included_files\n      - get_default_build_data\n\n<!-- File: docs/plugins/builder/sdist.md (Tokens: ~430 | Category: anthropic-skill) -->\n# Source distribution builder\n\n-----\n\nA source distribution, or `sdist`, is an archive of Python \"source code\". Although largely unspecified, by convention it should include everything that is required to build a [wheel](wheel.md) without making network requests.\n\n## Configuration\n\nThe builder plugin name is `sdist`.\n\n```toml config-example\n[tool.hatch.build.targets.sdist]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `core-metadata-version` | `\"2.4\"` | The version of [core metadata](https://packaging.python.org/specifications/core-metadata/) to use |\n| `strict-naming` | `true` | Whether or not file names should contain the normalized version of the project name |\n| `support-legacy` | `false` | Whether or not to include a `setup.py` file to support legacy installation mechanisms |\n\n## Versions\n\n| Version | Description |\n| --- | --- |\n| `standard` (default) | The latest conventional format |\n\n## Default file selection\n\nWhen the user has not set any [file selection](../../config/build.md#file-selection) options, all files that are not [ignored by your VCS](../../config/build.md#vcs) will be included.\n\n!!! note\n    The following files are always included and cannot be excluded:\n\n    - `/pyproject.toml`\n    - `/hatch.toml`\n    - `/hatch_build.py`\n    - `/.gitignore` or `/.hgignore`\n    - Any defined [`readme`](../../config/metadata.md#readme) file\n    - All defined [`license-files`](../../config/metadata.md#license)\n\n## Reproducibility\n\n[Reproducible builds](../../config/build.md#reproducible-builds) are supported.\n\n## Build data\n\nThis is data that can be modified by [build hooks](../build-hook/reference.md).\n\n| Data | Default | Description |\n| --- | --- | --- |\n| `dependencies` | | Extra [project dependencies](../../config/metadata.md#required) |\n\n<!-- File: docs/plugins/builder/wheel.md (Tokens: ~1133 | Category: anthropic-skill) -->\n# Wheel builder\n\n-----\n\nA [wheel](https://packaging.python.org/specifications/binary-distribution-format/) is a binary distribution of a Python package that can be installed directly into an environment.\n\n## Configuration\n\nThe builder plugin name is `wheel`.\n\n```toml config-example\n[tool.hatch.build.targets.wheel]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `core-metadata-version` | `\"2.4\"` | The version of [core metadata](https://packaging.python.org/specifications/core-metadata/) to use |\n| `shared-data` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to the `data` subdirectory within the standard [data directory](https://packaging.python.org/en/latest/specifications/binary-distribution-format/#the-data-directory) that will be installed globally in a given Python environment, usually under `#!python sys.prefix` |\n| `shared-scripts` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to the `scripts` subdirectory within the standard [data directory](https://packaging.python.org/en/latest/specifications/binary-distribution-format/#the-data-directory) that will be installed in a given Python environment, usually under `Scripts` on Windows or `bin` otherwise, and would normally be available on PATH |\n| `extra-metadata` | | A mapping similar to the [forced inclusion](../../config/build.md#forced-inclusion) option corresponding to extra [metadata](https://peps.python.org/pep-0427/#the-dist-info-directory) that will be shipped in a directory named `extra_metadata` |\n| `strict-naming` | `true` | Whether or not file names should contain the normalized version of the project name |\n| `macos-max-compat` | `false` | Whether or not on macOS, when build hooks have set the `infer_tag` [build data](#build-data), the wheel name should signal broad support rather than specific versions for newer SDK versions.<br><br>Note: This option will eventually be removed. |\n| `bypass-selection` | `false` | Whether or not to suppress the error when one has not defined any file selection options and all heuristics have failed to determine what to ship |\n| `sbom-files` | | A list of paths to [Software Bill of Materials](https://peps.python.org/pep-0770/) files that will be included in the `.dist-info/sboms/` directory of the wheel |\n\n!!! note\n    Many build frontends will build the wheel from a source distribution. This is the recommended approach, but it means you need to ensure the SBOM files passed to `sbom-files` are also [included in the source distribution](https://hatch.pypa.io/latest/config/build/#file-selection).\n\n## Versions\n\n| Version | Description |\n| --- | --- |\n| `standard` (default) | The latest standardized format |\n| `editable` | A wheel that only ships `.pth` files or import hooks for real-time development |\n\n## Default file selection\n\nWhen the user has not set any [file selection](../../config/build.md#file-selection) options, the [project name](../../config/metadata.md#name) will be used to determine the package to ship in the following heuristic order:\n\n1. `<NAME>/__init__.py`\n2. `src/<NAME>/__init__.py`\n3. `<NAME>.py`\n4. `<NAMESPACE>/<NAME>/__init__.py`\n\nIf none of these heuristics are satisfied, an error will be raised.\n\n## Reproducibility\n\n[Reproducible builds](../../config/build.md#reproducible-builds) are supported.\n\n## Build data\n\nThis is data that can be modified by [build hooks](../build-hook/reference.md).\n\n| Data | Default | Description |\n| --- | --- | --- |\n| `tag` | | The full [tag](https://peps.python.org/pep-0425/) part of the filename (e.g. `py3-none-any`), defaulting to a cross-platform wheel with the supported major versions of Python based on [project metadata](../../config/metadata.md#python-support) |\n| `infer_tag` | `#!python False` | When `tag` is not set, this may be enabled to use the one most specific to the platform, Python interpreter, and ABI |\n| `pure_python` | `#!python True` | Whether or not to write metadata indicating that the package does not contain any platform-specific files |\n| `dependencies` | | Extra [project dependencies](../../config/metadata.md#required) |\n| `shared_data` | | Additional [`shared-data`](#options) entries, which take precedence in case of conflicts |\n| `shared_scripts` | | Additional [`shared-scripts`](#options) entries, which take precedence in case of conflicts |\n| `extra_metadata` | | Additional [`extra-metadata`](#options) entries, which take precedence in case of conflicts |\n| `force_include_editable` | | Similar to the [`force_include` option](../build-hook/reference.md#build-data) but specifically for the `editable` [version](#versions) and takes precedence |\n| `sbom_files` | | This is a list of the sbom files that should be included under `.dist-info/sboms`. |\n\n<!-- File: docs/plugins/environment-collector/custom.md (Tokens: ~203 | Category: anthropic-skill) -->\n# Custom environment collector\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [EnvironmentCollectorInterface](reference.md#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface).\n\n## Configuration\n\nThe environment collector plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.env.collectors.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_plugins.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_plugins.py\"\n    from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface\n\n\n    class CustomEnvironmentCollector(EnvironmentCollectorInterface):\n        ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_environment_collector` that returns the desired environment collector.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n\n<!-- File: docs/plugins/environment-collector/default.md (Tokens: ~82 | Category: anthropic-skill) -->\n# Default environment collector\n\n-----\n\nThis adds the `default` environment with [type](../../config/environment/overview.md#type) set to [virtual](../environment/virtual.md) and will always be applied.\n\n## Configuration\n\nThe environment collector plugin name is `default`.\n\n```toml config-example\n[tool.hatch.env.collectors.default]\n```\n\n## Options\n\nThere are no options available currently.\n\n<!-- File: docs/plugins/environment-collector/reference.md (Tokens: ~186 | Category: anthropic-skill) -->\n# Environment collector plugins\n\n-----\n\nEnvironment collectors allow for dynamically modifying environments or adding environments beyond those defined in config. Users can override default values provided by each environment.\n\n## Known third-party\n\n- [hatch-mkdocs](https://github.com/mkdocs/hatch-mkdocs) - integrate [MkDocs](https://github.com/mkdocs/mkdocs) and infer dependencies into an env\n\n## Installation\n\nAny required environment collectors that are not built-in must be manually installed alongside Hatch or listed in the `tool.hatch.env.requires` array for automatic management:\n\n```toml config-example\n[tool.hatch.env]\nrequires = [\n  \"...\",\n]\n```\n\n::: hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - get_initial_config\n      - finalize_config\n      - finalize_environments\n\n<!-- File: docs/plugins/environment/reference.md (Tokens: ~872 | Category: anthropic-skill) -->\n# Environment plugins\n\n-----\n\nSee the documentation for [environment configuration](../../config/environment/overview.md).\n\n## Known third-party\n\n- [hatch-conda](https://github.com/OldGrumpyViking/hatch-conda) - environments backed by Conda/Mamba\n- [hatch-containers](https://github.com/ofek/hatch-containers) - environments run inside containers\n- [hatch-pip-compile](https://github.com/juftin/hatch-pip-compile) - use [pip-compile](https://github.com/jazzband/pip-tools) to manage project dependencies and lockfiles\n- [hatch-pip-deepfreeze](https://github.com/sbidoul/hatch-pip-deepfreeze) - [virtual](virtual.md) environments with dependency locking by [pip-deepfreeze](https://github.com/sbidoul/pip-deepfreeze)\n\n## Installation\n\nAny required environment types that are not built-in must be manually installed alongside Hatch or listed in the `tool.hatch.env.requires` array for automatic management:\n\n```toml config-example\n[tool.hatch.env]\nrequires = [\n  \"...\",\n]\n```\n\n## Life cycle\n\nWhenever an environment is used, the following logic is performed:\n\n::: hatch.project.core.Project.prepare_environment\n    options:\n      show_root_heading: false\n      show_root_toc_entry: false\n\n## Build environments\n\nAll environment types should [offer support](#hatch.env.plugin.interface.EnvironmentInterface.fs_context) for synchronized storage between the local file system and the environment. This functionality is used in the following scenarios:\n\n- the [`build`](../../cli/reference.md#hatch-build) command\n- commands that read dependencies, like [`dep hash`](../../cli/reference.md#hatch-dep-hash), if any [project dependencies](../../config/metadata.md#dependencies) are [set dynamically](../../config/metadata.md#dynamic)\n\n::: hatch.env.plugin.interface.EnvironmentInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - find\n      - create\n      - remove\n      - exists\n      - install_project\n      - install_project_dev_mode\n      - dependencies_in_sync\n      - sync_dependencies\n      - dependency_hash\n      - project_dependencies\n      - project_root\n      - sep\n      - pathsep\n      - fs_context\n      - activate\n      - deactivate\n      - app_status_creation\n      - app_status_pre_installation\n      - app_status_post_installation\n      - app_status_project_installation\n      - app_status_dependency_state_check\n      - app_status_dependency_installation_check\n      - app_status_dependency_synchronization\n      - app\n      - root\n      - name\n      - data_directory\n      - isolated_data_directory\n      - config\n      - platform\n      - environment_dependencies\n      - dependencies\n      - sources\n      - get_source_install_args\n      - env_vars\n      - env_include\n      - env_exclude\n      - platforms\n      - skip_install\n      - dev_mode\n      - description\n      - command_context\n      - enter_shell\n      - run_shell_command\n      - resolve_commands\n      - get_env_vars\n      - apply_features\n      - construct_pip_install_command\n      - join_command_args\n      - check_compatibility\n      - get_option_types\n      - get_env_var_option\n      - get_context\n\n## Dependency lockers\n\n**Dependency lockers** are implemented: register classes with `hatch_register_locker` (see [Dependency locker plugins](../locker.md)). They stay **decoupled** from environment plugins—no subclassing [`EnvironmentInterface`](#hatch.env.plugin.interface.EnvironmentInterface) just to change locking—and call the environment’s **public API** (for example [`command_context`](#hatch.env.plugin.interface.EnvironmentInterface.command_context) and [`platform`](../utilities.md)).\n\nFor moving artifacts between the workspace and the environment, custom lockers should prefer [`fs_context`](#hatch.env.plugin.interface.EnvironmentInterface.fs_context) and [`FileSystemContext`](../utilities.md#hatch.env.plugin.interface.FileSystemContext) over ad hoc I/O.\n\nEnd-user commands: [How to use lockfiles](../../how-to/environment/lockfiles.md).\n\n<!-- File: docs/plugins/environment/virtual.md (Tokens: ~1653 | Category: anthropic-skill) -->\n# Virtual environment\n\n-----\n\nThis uses virtual environments backed by [virtualenv](https://github.com/pypa/virtualenv) or [UV](https://github.com/astral-sh/uv).\n\n## Configuration\n\nThe environment plugin name is `virtual`.\n\n```toml config-example\n[tool.hatch.envs.<ENV_NAME>]\ntype = \"virtual\"\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `python` | | The version of Python to find on your system and subsequently use to create the environment, defaulting to the `HATCH_PYTHON` environment variable, followed by the [normal resolution logic](#python-resolution). Setting the `HATCH_PYTHON` environment variable to `self` will force the use of the Python executable Hatch is running on. For more information, see the [documentation](https://virtualenv.pypa.io/en/latest/user_guide.html#python-discovery). |\n| `python-sources` | `['external', 'internal']` | This may be set to an array of strings that are either the literal `internal` or `external`. External considers only Python executables that are already on `PATH`. Internal considers only [internally managed Python distributions](#internal-distributions). |\n| `path` | | An explicit path to the virtual environment. The path may be absolute or relative to the project root. Any environments that [inherit](../../config/environment/overview.md#inheritance) this option will also use this path. The environment variable `HATCH_ENV_TYPE_VIRTUAL_PATH` may be used, which will take precedence. |\n| `system-packages` | `false` | Whether or not to give the virtual environment access to the system `site-packages` directory |\n| `installer` | `pip` | When set to `uv`, [UV](https://github.com/astral-sh/uv) will be used in place of virtualenv & pip for virtual environment creation and dependency management, respectively. If you intend to provide UV yourself, you may set the `HATCH_ENV_TYPE_VIRTUAL_UV_PATH` environment variable which should be the absolute path to a UV binary. This environment variable implicitly sets the `installer` option to `uv` (if unset). |\n\n## Location\n\nThe [location](../../cli/reference.md#hatch-env-find) of environments is determined in the following heuristic order:\n\n1. The `path` option\n2. A directory named after the environment within the configured `virtual` [environment directory](../../config/hatch.md#environments) if the directory resides somewhere within the project root or if it is set to a `.virtualenvs` directory within the user's home directory\n3. Otherwise, environments are stored within the configured `virtual` [environment directory](../../config/hatch.md#environments) in a deeply nested structure in order to support multiple projects\n\nAdditionally, when the `path` option is not used, the name of the directory for the `default` environment will be the normalized project name to provide a more meaningful default [shell](../../cli/reference.md#hatch-shell) prompt.\n\n## Python resolution\n\nVirtual environments necessarily require a parent installation of Python. The following rules determine how the parent is resolved.\n\nThe Python choice is determined by the [`python` option](#options) followed by the `HATCH_PYTHON` environment variable. If the choice is via the environment variable, then resolution stops and that path is used unconditionally.\n\nThe resolvers will be based on the [`python-sources` option](#options) and all resolved interpreters will ensure compatibility with the project's defined [Python support](../../config/metadata.md#python-support).\n\nIf a Python version has been chosen then each resolver will try to find an interpreter that satisfies that version.\n\nIf no version has been chosen, then each resolver will try to find a version that matches the version of Python that Hatch is currently running on. If not found then each resolver will try to find the highest compatible version.\n\n!!! note\n    Some external Python paths are considered unstable and are ignored during resolution. For example, if Hatch is installed via Homebrew then `sys.executable` will be ignored because the interpreter could change or be removed at any time.\n\n!!! note\n    When resolution finds a match using an [internally managed distribution](#internal-distributions) and an update is available, the latest distribution will automatically be downloaded before environment creation.\n\n## Internal distributions\n\nThe following options are recognized for internal Python resolution.\n\n!!! tip\n    You can set custom sources for distributions by setting the `HATCH_PYTHON_SOURCE_<NAME>` environment variable where `<NAME>` is the uppercased version of the distribution name with periods replaced by underscores e.g. `HATCH_PYTHON_SOURCE_PYPY3_10`.\n\n### CPython\n\n| NAME |\n| --- |\n| `3.7` |\n| `3.8` |\n| `3.9` |\n| `3.10` |\n| `3.11` |\n| `3.12` |\n| `3.13` |\n| `3.14` |\n| `3.15` |\n\nThe source of distributions is the [python-build-standalone](https://github.com/indygreg/python-build-standalone) project.\n\nSome distributions have [variants](https://gregoryszorc.com/docs/python-build-standalone/main/running.html) that may be configured with environment variables. Options may be combined.\n\n| Option | Platforms | Allowed values |\n| --- | --- | --- |\n| `HATCH_PYTHON_VARIANT_CPU` | <ul><li>Linux</li></ul> | <ul><li><code>v1</code></li><li><code>v2</code></li><li><code>v3</code> (default)</li><li><code>v4</code></li></ul> |\n| `HATCH_PYTHON_VARIANT_GIL` | <ul><li>Linux</li><li>Windows</li><li>macOS</li></ul> | <ul><li><code>freethreaded</code></li></ul> |\n\n### PyPy\n\n| NAME |\n| --- |\n| `pypy2.7` |\n| `pypy3.9` |\n| `pypy3.10` |\n| `pypy3.11` |\n\nThe source of distributions is the [PyPy](https://www.pypy.org) project.\n\n## Troubleshooting\n\n### macOS SIP\n\nIf you need to set linker environment variables like those starting with `DYLD_` or `LD_`, any executable secured by [System Integrity Protection](https://en.wikipedia.org/wiki/System_Integrity_Protection) that is invoked when [running commands](../../environment.md#command-execution) will not see those environment variable modifications as macOS strips those.\n\nHatch interprets such commands as shell commands but deliberately ignores such paths to protected shells. This workaround suffices for the majority of use cases but there are 2 situations in which it may not:\n\n1. There are no unprotected `sh`, `bash`, `zsh`, nor `fish` executables found along PATH.\n2. The desired executable is a project's [script](../../config/metadata.md#cli), and the [location](#location) of environments contains spaces or is longer than 124[^1] characters. In this case `pip` and other installers will create such an entry point with a shebang pointing to `/bin/sh` (which is protected) to avoid shebang limitations. Rather than changing the location, you could invoke the script as e.g. `python -m pytest` (if the project supports that method of invocation by shipping a `__main__.py`).\n\n[^1]: The shebang length limit is [usually](https://web.archive.org/web/20221231220856/https://www.in-ulm.de/~mascheck/various/shebang/#length) 127 but 3 characters surround the executable path: `#!<EXE_PATH>\\n`\n\n<!-- File: docs/plugins/locker.md (Tokens: ~390 | Category: anthropic-skill) -->\n# Dependency locker plugins\n\n-----\n\nHatch selects a **locker** plugin to **generate** PEP 751 lockfiles, verify they are **in sync** with the configured dependency inputs, and **apply** them when syncing a `locked` environment. Built-in lockers are **`uv`** and **`pip`**, matching the [virtual environment installer](../how-to/environment/select-installer.md).\n\n**Dependency lockers** are registered with `hatch_register_locker` (see [Registration](#registration) below).\n\n## Registration\n\n```python tab=\"hooks.py\"\nfrom hatchling.plugin import hookimpl\n\nfrom .locker import MyLocker\n\n\n@hookimpl\ndef hatch_register_locker():\n    return MyLocker\n```\n\nExpose the module on the `hatch` entry point (see [Plugins — Discovery](about.md#discovery)) and list the distribution under [`tool.hatch.env.requires`](environment/reference.md#installation) when the plugin is not installed globally.\n\n## Configuration\n\n- Global default: [`tool.hatch.locker`](../config/environment/overview.md#locker) (string plugin name).\n- Per environment: [`tool.hatch.envs.<name>.locker`](../config/environment/overview.md#locker) overrides the global value.\n- If unset, Hatch picks `uv` when the environment uses the UV installer, otherwise `pip`.\n\n## Built-in lockers\n\n| `PLUGIN_NAME` | When selected | Notes |\n| ------------- | ------------- | ----- |\n| `uv` | Virtual env + UV installer | `uv pip compile` / `uv pip sync`; supports layered locks (extras, dependency-groups, `pyproject.toml`). |\n| `pip` | Any supported environment | `pip lock`; flat dependency list only (no layered extras/groups in the pip locker). `apply_lock` is a no-op — use UV for `locked` installs from a pylock today. |\n\n<!-- File: docs/plugins/metadata-hook/custom.md (Tokens: ~198 | Category: anthropic-skill) -->\n# Custom metadata hook\n\n-----\n\nThis is a custom class in a given Python file that inherits from the [MetadataHookInterface](reference.md#hatchling.metadata.plugin.interface.MetadataHookInterface).\n\n## Configuration\n\nThe metadata hook plugin name is `custom`.\n\n```toml config-example\n[tool.hatch.metadata.hooks.custom]\n```\n\n## Options\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `path` | `hatch_build.py` | The path of the Python file |\n\n## Example\n\n```python tab=\"hatch_build.py\"\nfrom hatchling.metadata.plugin.interface import MetadataHookInterface\n\n\nclass CustomMetadataHook(MetadataHookInterface):\n    ...\n```\n\nIf multiple subclasses are found, you must define a function named `get_metadata_hook` that returns the desired build hook.\n\n!!! note\n    Any defined [PLUGIN_NAME](reference.md#hatchling.metadata.plugin.interface.MetadataHookInterface.PLUGIN_NAME) is ignored and will always be `custom`.\n\n<!-- File: docs/plugins/metadata-hook/reference.md (Tokens: ~280 | Category: anthropic-skill) -->\n# Metadata hook plugins\n\n-----\n\nMetadata hooks allow for the modification of [project metadata](../../config/metadata.md) after it has been loaded.\n\n## Known third-party\n\n- [hatch-docstring-description](https://github.com/flying-sheep/hatch-docstring-description) - set the project description using docstrings\n- [hatch-fancy-pypi-readme](https://github.com/hynek/hatch-fancy-pypi-readme) - dynamically construct the README\n- [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version) - uses fields from NodeJS `package.json` files\n- [hatch-odoo](https://github.com/acsone/hatch-odoo) - determine dependencies based on manifests of Odoo add-ons\n- [hatch-requirements-txt](https://github.com/repo-helper/hatch-requirements-txt) - read project dependencies from `requirements.txt` files\n- [UniDep](https://github.com/basnijholt/unidep) - for unified `pip` and `conda` dependency management using a single `requirements.yaml` file for both \n\n::: hatchling.metadata.plugin.interface.MetadataHookInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - update\n      - get_known_classifiers\n\n<!-- File: docs/plugins/publisher/package-index.md (Tokens: ~413 | Category: anthropic-skill) -->\n# Index publisher\n\n-----\n\nSee the documentation for [publishing](../../publish.md).\n\n## Options\n\n| Flag | Config name | Description |\n| --- | --- | --- |\n| `-r`/`--repo` | `repo` | The repository with which to publish artifacts |\n| `-u`/`--user` | `user` | The user with which to authenticate |\n| `-a`/`--auth` | `auth` | The credentials to use for authentication |\n| `--ca-cert` | `ca-cert` | The path to a CA bundle |\n| `--client-cert` | `client-cert` | The path to a client certificate, optionally containing the private key |\n| `--client-key` | `client-key` | The path to the client certificate's private key |\n| | `repos` | A table of named [repositories](#repositories) to their respective options |\n\n## Configuration\n\nThe publisher plugin name is `index`.\n\n```toml tab=\"config.toml\"\n[publish.index]\n```\n\n### Repositories\n\nAll top-level options can be overridden per repository using the `repos` table\nwith a required `url` attribute for each repository. The following shows the\ndefault configuration:\n\n```toml tab=\"config.toml\"\n[publish.index.repos.main]\nurl = \"https://upload.pypi.org/legacy/\"\n\n[publish.index.repos.test]\nurl = \"https://test.pypi.org/legacy/\"\n```\n\nThe `repo` and `repos` options have no effect.\n\n### Confirmation prompt\n\nYou can require a confirmation prompt or use of the `-y`/`--yes` flag by\nsetting publishers' `disable` option to `true` in either Hatch's\n[config file](../../config/hatch.md) or project-specific configuration (which takes\nprecedence):\n\n```toml tab=\"config.toml\"\n[publish.index]\ndisable = true\n```\n\n```toml config-example\n[tool.hatch.publish.index]\ndisable = true\n```\n\n<!-- File: docs/plugins/publisher/reference.md (Tokens: ~95 | Category: anthropic-skill) -->\n# Publisher plugins\n\n-----\n\n## Known third-party\n\n- [hatch-aws-publisher](https://github.com/aka-raccoon/hatch-aws-publisher) - publish AWS Lambda functions with SAM\n\n::: hatch.publish.plugin.interface.PublisherInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - app\n      - root\n      - cache_dir\n      - project_config\n      - plugin_config\n      - disable\n      - publish\n\n<!-- File: docs/plugins/utilities.md (Tokens: ~423 | Category: anthropic-skill) -->\n# Plugin utilities\n\n-----\n\n::: hatchling.builders.utils.get_reproducible_timestamp\n    options:\n      show_root_full_path: true\n\n::: hatchling.builders.config.BuilderConfig\n    options:\n      show_source: false\n      members:\n      - directory\n      - ignore_vcs\n      - reproducible\n      - dev_mode_dirs\n      - versions\n      - dependencies\n      - default_include\n      - default_exclude\n      - default_packages\n      - default_only_include\n\n::: hatchling.bridge.app.Application\n    options:\n      show_source: false\n      members:\n      - abort\n      - verbosity\n      - display_debug\n      - display_error\n      - display_info\n      - display_success\n      - display_waiting\n      - display_warning\n\n::: hatch.utils.platform.Platform\n    options:\n      show_source: false\n      members:\n      - format_for_subprocess\n      - run_command\n      - check_command\n      - check_command_output\n      - capture_process\n      - exit_with_command\n      - default_shell\n      - modules\n      - home\n      - name\n      - display_name\n      - windows\n      - macos\n      - linux\n\n::: hatch.env.context.EnvironmentContextFormatter\n    options:\n      show_source: false\n      members:\n      - formatters\n\n::: hatch.env.plugin.interface.FileSystemContext\n    options:\n      show_source: false\n      members:\n      - env\n      - sync_local\n      - sync_env\n      - local_path\n      - env_path\n      - join\n\n::: hatch.project.sources.Source\n    options:\n      show_source: false\n\n::: hatch.project.sources.PathSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.GitSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.UrlSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.IndexSource\n    options:\n      show_source: false\n\n::: hatch.project.sources.WorkspaceSource\n    options:\n      show_source: false\n\n<!-- File: docs/plugins/version-scheme/reference.md (Tokens: ~116 | Category: anthropic-skill) -->\n# Version scheme plugins\n\n-----\n\n## Known third-party\n\n- [hatch-calver](https://github.com/akx/hatch-calver) - uses [calendar versioning](https://calver.org)\n- [hatch-semver](https://github.com/Nagidal/hatch-semver) - uses [semantic versioning](https://semver.org)\n\n::: hatchling.version.scheme.plugin.interface.VersionSchemeInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - validate_bump\n      - update\n\n<!-- File: docs/plugins/version-scheme/standard.md (Tokens: ~99 | Category: anthropic-skill) -->\n# Standard version scheme\n\n-----\n\nSee the documentation for [versioning](../../version.md#updating).\n\n## Configuration\n\nThe version scheme plugin name is `standard`.\n\n```toml config-example\n[tool.hatch.version]\nscheme = \"standard\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `validate-bump` | When setting a specific version, this determines whether to check that the new version is higher than the original. The default is `true`. |\n\n<!-- File: docs/plugins/version-source/code.md (Tokens: ~301 | Category: anthropic-skill) -->\n# Code version source\n\n-----\n\n## Updates\n\nSetting the version is not supported.\n\n## Configuration\n\nThe version source plugin name is `code`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"code\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to a Python file or extension module that will be loaded |\n| `expression` | A Python expression that when evaluated in the context of the loaded file returns the version. The default expression is simply `__version__`. |\n| `search-paths` | A list of relative paths to directories that will be prepended to Python's search path |\n\n## Missing imports\n\nIf the chosen path imports another module in your project, then you'll need to use absolute imports coupled with the `search-paths` option. For example, say you need to load the following file:\n\n```python tab=\"src/pkg/\\_\\_init\\_\\_.py\"\n    from ._version import get_version\n\n    __version__ = get_version()\n```\n\nYou should change it to:\n\n```python tab=\"src/pkg/\\_\\_init\\_\\_.py\"\n    from pkg._version import get_version\n\n    __version__ = get_version()\n```\n\nand the configuration would become:\n\n```toml config-example\n[tool.hatch.version]\nsource = \"code\"\npath = \"src/pkg/__init__.py\"\nsearch-paths = [\"src\"]\n```\n\n<!-- File: docs/plugins/version-source/env.md (Tokens: ~102 | Category: anthropic-skill) -->\n# Environment version source\n\n-----\n\nRetrieves the version from an environment variable. This can be useful in build pipelines where the version is set by an external trigger.\n\n## Updates\n\nSetting the version is not supported.\n\n## Configuration\n\nThe version source plugin name is `env`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"env\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `variable` (required) | The name of the environment variable |\n\n<!-- File: docs/plugins/version-source/reference.md (Tokens: ~189 | Category: anthropic-skill) -->\n# Version source plugins\n\n-----\n\n## Known third-party\n\n- [hatch-vcs](https://github.com/ofek/hatch-vcs) - uses your preferred version control system (like Git)\n- [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version) - uses the `version` field of NodeJS `package.json` files\n- [hatch-regex-commit](https://github.com/frankie567/hatch-regex-commit) - automatically creates a Git commit and tag after version bumping\n- [versioningit](https://github.com/jwodder/versioningit) - determines version from Git or Mercurial tags, with customizable version formatting\n\n::: hatchling.version.source.plugin.interface.VersionSourceInterface\n    options:\n      members:\n      - PLUGIN_NAME\n      - root\n      - config\n      - get_version_data\n      - set_version\n\n<!-- File: docs/plugins/version-source/regex.md (Tokens: ~150 | Category: anthropic-skill) -->\n# Regex version source\n\n-----\n\nSee the documentation for [versioning](../../version.md).\n\n## Updates\n\nSetting the version is supported.\n\n## Configuration\n\nThe version source plugin name is `regex`.\n\n```toml config-example\n[tool.hatch.version]\nsource = \"regex\"\n```\n\n## Options\n\n| Option | Description |\n| --- | --- |\n| `path` (required) | A relative path to a file containing the project's version |\n| `pattern` | A regular expression that has a named group called `version` that represents the version. The default pattern looks for a variable named `__version__` or `VERSION` that is set to a string containing the version, optionally prefixed with the lowercase letter `v`. |\n</yakaai_skills>"}