Hey! These docs are for version 2.8, which is no longer officially supported. Click here for the latest version, 2.18!

Pants is designed for extensibility: you can extend Pants by writing custom _plugins_, using a standard Plugin API. In fact, all of Pants's built-in functionality uses the same API!

Some of the ways you can extend Pants:

  • Add support for new languages.

  • Add new goals, like a `publish` goal or `docker` goal.

  • Add new linters, formatters, and type-checkers.

  • Add new codegen implementations.

  • Define new target types that still work with core Pants.

  • Add new forms of dependency inference

  • Define macros to reduce boilerplate in BUILD files.

Thanks to Pants's execution engine, your plugins will automatically bring you the same benefits you get from using core Pants, including:

  • Fine-grained caching.

  • Concurrent execution.

  • Remote execution.

The Plugin API is not yet stable

While we'll try our best to limit changes, the Plugin API does not yet follow the [Deprecation Policy](🔗). Components of the API may change between minor versions—e.g. 2.7 to 2.8—without a deprecation.

We will document changes at [Plugin upgrade guide](🔗).

## Core concepts

The plugin API is split into two main interfaces:

  1. [The Target API](🔗): a declarative interface for creating new target types and extending existing targets.

  2. [The Rules API](🔗): where you define your logic and model each step of your build.

Plugins are written in typed Python 3 code. You write your logic in Python, and then Pants will run your plugin in the Rust engine.

## Locating Plugin code

Plugins can be consumed in either of two ways:

  • From a published package in a repository such as [PyPI](🔗).

  • Directly from in-repo sources.

It's often convenient to use in-repo plugins, particularly when the plugin is only relevant to a single repo and you want to iterate on it rapidly. In other cases, you may want to publish the plugin, so it can be reused across multiple repos.

### Published plugins

You consume published plugins by adding them to the `plugins` option:

### In-repo plugins

Conventionally, in-repo plugins live in a folder called `pants-plugins`, although they may be placed anywhere.

You must specify the path to your plugin's top-level folder using the `pythonpath` option:

In-repo dependencies

In-repo plugin code should not depend on other in-repo code outside of the `pants-plugins` folder. The `pants-plugins` folder helps isolate plugins from regular code, which is necessary due to how Pants's startup sequence works.

You can depend on third-party dependencies in your in-repo plugin by adding them to the `plugins` option:

However, be careful adding third-party dependencies that perform side-effects like reading from the filesystem or making network requests, as they will not work properly with the engine's caching model.

## Enabling Plugins with `register.py`

A Pants [_backend_](🔗) is a Python package that implements some required functionality and uses hooks to register itself with Pants.

A plugin will contain one or more backends, with the hooks for each one defined in a file called `register.py`. To enable a custom plugin you add its backends to your `backend_packages` configuration:

## Building in-repo plugins with Pants

Because plugin code is written in Python, you can use Pants's [Python backend](🔗) to build your plugin code. For example, you can use Pants to lint, format, and test your plugin code.

To do so, set up Pants for [Python support](🔗), and add your `pants-plugins` directory as a source root:

Your plugin code uses the Plugin API, so it depends on Pants's code as a 3rdparty dependency. It's important to depend on the exact Pants version that you're running in the repo.

One way to express this is to add `pantsbuild.pants==<version>` to your `requirements.txt`, but then you have to be careful to keep the versions in sync.

A better way is to use the `pants_requirement()` macro, which uses the `pants_version` from your `pants.toml`:

Pants's [dependency inference](🔗) understands imports of the `pants` module and will automatically add dependencies on the `pants_requirement` where relevant.

`pants_requirement` cannot update a constraints file

If you are using a lockfile—which we recommend for both correctness and performance—then you will need to remember to regenerate your `constraints.txt` file when upgrading Pants versions.

See [Third-party dependencies](🔗).