Pixi Task Operator¶
Use the PixiTaskOperator to run a task
defined in the [tasks] of a Pixi manifest, as pixi run <task> does on the
command line. It is built on the Pixi Bash Operator and accepts its arguments, except
bash_command.
Using the operator¶
Given a project with tasks:
# /repo/pixi.toml
[tasks]
train = "python train.py"
[tasks.report]
args = ["day", { arg = "format", default = "html" }]
cmd = "python report.py --day {{ day }} --format {{ format }}"
run one of them with task, and pass its arguments with task_args:
from airflow.providers.pixi.operators.task import PixiTaskOperator
PixiTaskOperator(
task_id="report",
pixi_project_path="/repo",
lock_mode="locked",
task="report",
task_args=["{{ ds }}", "pdf"],
)
The command is
pixi run --manifest-path <manifest> [--environment <env>] [--locked | --frozen] <task> <task_args...>
It runs through BashOperator's bash -c, with each argument shell-quoted, so each argument reaches
pixi unchanged: bash does not split it at spaces or expand $ in it. What pixi does with an argument
then depends on the task, see Task arguments.
- Environment:
pixi_project_pathorpixi_toml_path, withenvironmentandlock_mode, as for the Pixi Operator. An inline manifest (dependencies,pypi_dependencies) cannot define tasks and is rejected when the DAG is parsed. - Return value: the last line of output is the task's XCom (
output_processoranddo_xcom_pushwork as forBashOperator). - Exit codes: exit code 99 skips the task (
skip_on_exit_code), any other non-zero code fails it, including pixi's own failures, such as an environment that cannot be solved. - Dependencies: tasks in the task's
depends-onrun first, in the same Airflow task and log. - Environment variables:
env,append_env,env_vars,env_from_variables,env_from_connections,pixi_conn_idand the cache directory Variables work as for the Pixi Bash Operator, with the same precedence.
Task arguments¶
Pixi matches task_args against the task's definition, as described in
pixi's task arguments:
- A task that declares
argsgets them in the order they are declared, and uses them in itscmdas{{ name }}. Arguments with adefaultcan be left out. More arguments than declared fail the run, unless the extra ones follow--: everything after--is passed to the command unchanged. - A task without
argsgets the arguments appended to its command,--included, each as one argument.
Values of declared args are interpreted by pixi's task shell
Pixi puts the value of a declared argument into cmd as plain text, without quoting, and then runs
cmd with its task shell. A value with a space becomes two words, and ;, |, && or $ in a
value are interpreted: with cmd = "python report.py --day {{ day }}", the value
2026-01-01; rm -rf data runs rm -rf data. Don't pass values that someone else controls, such as
dag_run.conf, Params a user can set when triggering, or the output of a task that reads outside
input, to a task that declares args. Validate them first, or use a task without args, or pass
them after --, where they arrive unchanged. Quoting the placeholder in cmd ('{{ day }}') keeps
spaces together, but a value that contains ' still breaks out of it.
# python train.py --epochs 3
PixiTaskOperator(task_id="train", pixi_project_path="/repo", task="train", task_args=["--epochs", "3"])
# python report.py --day 2026-01-01 --format html --verbose
PixiTaskOperator(
task_id="report",
pixi_project_path="/repo",
task="report",
task_args=["{{ ds }}", "--", "--verbose"],
)
task and task_args are templated. task_args must be a list; it can also be the output of
another task that returns a list:
@task
def arguments() -> list[str]:
return ["--epochs", "3"]
PixiTaskOperator(task_id="train", pixi_project_path="/repo", task="train", task_args=arguments())
A task_args item that ends with .sh or .bash is an argument, not a template file to load.
Working directory¶
Pixi runs a task in the workspace root, the directory of the manifest, or in the task's own cwd
relative to it. The operator's cwd (default: the manifest's directory) is where pixi itself starts,
so it matters only for names that are not tasks.
Names that are not tasks¶
As on the command line, pixi run runs a name that is not a task as a command of the environment, so
task="pytest" runs pytest from the environment when the manifest has no pytest task. A
misspelled task name therefore fails with a "command not found" error from the run rather than an
error that the task is missing.
No TaskFlow decorator¶
There is no @task.pixi_task. A decorated function would only return the task's arguments; pass them
as task_args instead, from a template or from another task's output as shown above.
Templated fields¶
task, task_args, env, cwd, pixi_project_path, pixi_toml_path, environment, lock_mode,
pixi_cache_dir_variable, uv_cache_dir_variable and pip_cache_dir_variable. env_vars,
env_from_variables, env_from_connections and pixi_conn_id are not templated.
Reference¶
For the full list of parameters, see the
PixiTaskOperator API reference.