Plugins

Many plugins are available for tox. These include, but are not limited to, the extensions found on the tox-dev org on ‘GitHub.

Plugins are automatically discovered once from the Python environment that tox itself is installed in. This means that if tox is installed in an isolated environment (e.g. when installed using pipx or uv), the plugin(s) must be installed in the same environment. To ensure a plugin is always available, you can include the plugin is listed in requires, which will cause tox to auto-provision a new isolated environment with both tox and the plugin(s) installed. For example:

requires = ["tox>=4", "tox-uv>=1"]
[tox]
requires =
    tox>=4
    tox-uv>=1

For more information, refer to the user guide.

Plugins can be disabled via the TOX_DISABLED_EXTERNAL_PLUGINS environment variable. This variable can be set to a comma separated list of plugin names, e.g.:

`bash env TOX_DISABLED_EXTERNAL_PLUGINS=tox-uv,tox-extra tox --version `

Developing your own plugin

The below provides some guidance on how to develop your own plugin for tox. A reference guide to the plugin API can be found in API.

Extensions points

tox uses pluggy to customize the default behavior. It provides an extension mechanism for plugin management by calling hooks.

Pluggy discovers a plugin by looking up for entry-points named tox, for example in a pyproject.toml:

[project.entry-points.tox]
your_plugin = "your_plugin.hooks"

Therefore, to start using a plugin, you solely need to install it in the same environment tox is running in and it will be discovered via the defined entry-point (in the example above, tox will load your_plugin.hooks).

A plugin is created by implementing extension points in the form of hooks. For example the following code snippet would define a new --magic command line interface flag the user can specify:

from tox.config.cli.parser import ToxParser
from tox.plugin import impl


@impl
def tox_add_option(parser: ToxParser) -> None:
    parser.add_argument("--magic", action="store_true", help="magical flag")

You can define such hooks either in a package installed alongside tox or within a toxfile.py found alongside your tox configuration file (root of your project).

tox.plugin.NAME = 'tox'

the name of the tox hook

tox.plugin.impl

decorator to mark tox plugin hooks

tox.plugin.spec.tox_add_core_config(core_conf, state)

Called when the core configuration is built for a tox environment.

Parameters:
  • core_conf (ConfigSet) – the core configuration object

  • state (State) – the global tox state object

Return type:

None

tox.plugin.spec.tox_add_env_config(env_conf, state)

Called when configuration is built for a tox environment.

Parameters:
  • env_conf (EnvConfigSet) – the core configuration object

  • state (State) – the global tox state object

Return type:

None

tox.plugin.spec.tox_add_option(parser)

Add a command line argument. This is the first hook to be called, right after the logging setup and config source discovery.

Parameters:

parser (ToxParser) – the command line parser

Return type:

None

tox.plugin.spec.tox_after_run_commands(tox_env, exit_code, outcomes)

Called after the commands set is executed.

Parameters:
  • tox_env (ToxEnv) – the tox environment being executed

  • exit_code (int) – exit code of the command

  • outcomes (list[Outcome]) – outcome of each command execution

Return type:

None

tox.plugin.spec.tox_before_run_commands(tox_env)

Called before the commands set is executed.

Parameters:

tox_env (ToxEnv) – the tox environment being executed

Return type:

None

tox.plugin.spec.tox_env_teardown(tox_env)

Called after a tox environment has been teared down.

Parameters:

tox_env (ToxEnv) – the tox environment

Return type:

None

tox.plugin.spec.tox_extend_envs()

Declare additional environment names.

Added in version 4.29.0.

This hook is called without any arguments early in the lifecycle. It is expected to return an iterable of strings with environment names for tox to consider. It can be used to facilitate dynamic creation of additional environments from within tox plugins.

This is ideal to pair with tox_add_core_config that has access to state.conf.memory_seed_loaders allowing to extend it with instances of tox.config.loader.memory.MemoryLoader early enough before tox starts caching configuration values sourced elsewhere.

Return type:

Iterable[str]

tox.plugin.spec.tox_on_install(tox_env, arguments, section, of_type)

Called before executing an installation command.

Parameters:
  • tox_env (ToxEnv) – the tox environment where the command runs in

  • arguments (Any) – installation arguments

  • section (str) – section of the installation

  • of_type (str) – type of the installation

Return type:

None

tox.plugin.spec.tox_register_tox_env(register)

Register new tox environment type. You can register:

  • run environment: by default this is a local subprocess backed virtualenv Python

  • packaging environment: by default this is a PEP-517 compliant local subprocess backed virtualenv Python

Parameters:

register (ToxEnvRegister) – a object that can be used to register new tox environment types

Return type:

None

A plugin can define its plugin module a:

def tox_append_version_info() -> str:
    return "magic"

and this message will be appended to the output of the --version flag.

Adoption of a plugin under tox-dev Github organization

You’re free to host your plugin on your favorite platform, however the core tox development is happening on Github, under the tox-dev org organization. We are happy to adopt tox plugins under the tox-dev organization if:

  • we determine it’s trying to solve a valid use case and it’s not malicious (e.g. no plugin that deletes the users home directory),

  • it’s released on PyPI with at least 100 downloads per month (to ensure it’s a plugin used by people).

What’s in for you in this:

  • you get owner rights on the repository under the tox-dev organization,

  • exposure of your plugin under the core umbrella,

  • backup maintainers from other tox plugin development.

How to apply:

Migration from tox 3

This section explains how the plugin interface changed between tox 3 and 4, and provides guidance for plugin developers on how to migrate.

tox_get_python_executable

With tox 4 the Python discovery is performed tox.tox_env.python.virtual_env.api._get_python that delegates the job to virtualenv. Therefore first define a new virtualenv discovery mechanism and then set that by setting the VIRTUALENV_DISCOVERY environment variable.

tox_package

Register new packager types via tox_register_tox_env.

tox_addoption

Renamed to tox_add_option.