Tasks#

Tasks are named shell commands that can live alongside workspace environment definitions or in a tasks-only manifest. They make common project commands discoverable, composable, and repeatable through conda task run.

Task commands#

task quickstart demo

A task’s cmd can be a simple string or a list of strings joined with spaces:

[tasks]
build = "python -m build"
build-alt = { cmd = ["python", "-m", "build", "--wheel"] }

Task dependencies#

depends-on demo

Tasks can depend on other tasks. Dependencies are resolved with topological ordering so everything runs in the right sequence:

[tasks]
compile = { cmd = "gcc -o main main.c", description = "Compile the program" }
test = { cmd = "./main --test", depends-on = ["compile"], description = "Run tests" }

[tasks.check]
depends-on = ["test", "lint"]
description = "Run all checks"

Running conda task run check resolves the full dependency graph and runs each task in order.

Task aliases#

Tasks with no cmd that only list dependencies act as aliases:

[tasks.check]
depends-on = ["test", "lint", "type-check"]
description = "Run all checks"

Hidden tasks#

Tasks prefixed with _ are hidden from conda task list but can still be referenced as dependencies or run explicitly:

[tasks]
_setup = "mkdir -p build/"

[tasks.build]
cmd = "make"
depends-on = ["_setup"]

Task arguments#

templates demo

Tasks can accept named arguments with optional defaults:

[tasks.test]
cmd = "pytest {{ test_path }} -v"
args = [
  { arg = "test_path", default = "tests/" },
]
description = "Run tests on a path"

Run with:

conda task run test src/tests/

Template variables#

Commands support Jinja2 templates with conda.* context variables:

Variable

Description

{{ conda.platform }}

Current platform (e.g. osx-arm64)

{{ conda.environment_name }}

Selected task environment name, or active environment name when none is selected

{{ conda.environment.name }}

Selected task environment name, or active environment name when none is selected

{{ conda.prefix }}

Selected task environment prefix, or active target prefix when none is selected

{{ conda.version }}

conda version

{{ conda.manifest_path }}

Path to the task file

{{ conda.init_cwd }}

Current working directory at rendering time

{{ conda.is_win }}

True on Windows

{{ conda.is_unix }}

True on non-Windows

{{ conda.is_linux }}

True on Linux

{{ conda.is_osx }}

True on macOS

When reading from pixi.toml, {{ pixi.platform }} etc. also work as aliases.

Each executable task renders these values from the environment in which it will run. This includes -e, default-environment, and an environment selector on a dependency. Dependency argument values and templated ad-hoc commands follow the same rule.

Task environment variables#

[tasks.test]
cmd = "pytest"
env = { PYTHONPATH = "src", DATABASE_URL = "sqlite:///test.db" }

Clean environment#

Run a task with only essential environment variables:

[tasks]
isolated-test = { cmd = "pytest", clean-env = true }

Or via CLI: conda task run test --clean-env

Task caching#

caching demo

When inputs and outputs are specified, tasks are cached and re-execution is skipped when inputs haven’t changed:

[tasks.build]
cmd = "python -m build"
inputs = ["src/**/*.py", "pyproject.toml"]
outputs = ["dist/*.whl"]

Tip

The cache compares SHA-256 fingerprints for declared inputs and outputs, favoring correctness over timestamp shortcuts. The selected environment prefix, or the current conda prefix when no environment is selected, is part of the cache identity, so switching environments reruns the task.

Platform-specific tasks#

platform overrides demo

Override task fields per platform using the target key:

[tasks]
clean = "rm -rf build/"

[target.win-64.tasks]
clean = "rd /s /q build"
[tasks]
clean = "{% if conda.is_win %}rd /s /q build{% else %}rm -rf build/{% endif %}"

Task environment targeting#

Changed in version 0.4.0: When a task is defined in a manifest that also declares workspace environments, conda task run now falls back to the workspace’s default environment instead of whatever conda environment happens to be active. Tasks without a workspace (tasks-only manifests) still use the current conda environment. -e <env> and a task’s default-environment key continue to take precedence.

Tasks defined alongside workspace environments run in the workspace’s default environment when it is installed. If that environment is not installed, the task runs in the current shell. Override with -e <env>:

conda task run test -e myenv

Tasks can also declare a default environment:

[tasks.test-legacy]
cmd = "pytest"
default-environment = "py38-compat"

Explicit environment selectors must name an installed workspace environment. This includes -e <env>, default-environment, and the environment field on a task dependency. A missing or uninstalled selected environment reports an error instead of silently running the command in the current shell. Tasks-only manifests do not define workspace environments, so these selectors require a workspace table.

Aliases have no command to run in an environment. When an alias is another task’s dependency, put environment or default-environment on each executable task inside the alias instead. Environment selectors on nested aliases are rejected rather than silently falling back to another shell. A target alias can still use default-environment as its invocation fallback.

User-level tasks#

Define tasks in ~/.config/conda/tasks.toml to make them available in every project without repeating definitions:

[tasks]
fmt = { cmd = "ruff format .", description = "Format Python files" }
clean = { cmd = "git clean -fdx -e .conda", description = "Remove untracked files" }
check = { cmd = "ruff check --fix .", description = "Lint and auto-fix" }

User tasks act as defaults. If a project defines a task with the same name, the project version takes precedence. conda task list marks user-sourced tasks with (user) so you can tell where each task comes from:

$ conda task list
  build    python -m build
  test     pytest tests/ -v
  fmt      ruff format .        (user)
  clean    git clean -fdx ...   (user)

User tasks work even outside a workspace. See User-level tasks for file location details and merge semantics.