docs/tasks/templates.md
::: warning
This feature is experimental and requires experimental = true in your settings.
:::
Task templates allow you to define reusable task definitions that can be extended by multiple tasks. This is particularly useful in monorepos or projects with similar task patterns across different components.
Templates are defined in the [task_templates.*] section of your mise.toml:
[settings]
experimental = true
[task_templates."python:build"]
description = "Build a Python project"
run = "uv build"
tools = { python = "3.12", uv = "latest" }
env = { PYTHONPATH = "src" }
[task_templates."python:test"]
description = "Run Python tests"
run = "pytest"
tools = { python = "3.12" }
depends = ["build"]
Tasks can extend templates using the extends field:
[tasks.build]
extends = "python:build"
[tasks.test]
extends = "python:test"
run = "pytest --cov" # Override run while keeping tools, depends
Templates use colon (:) separators for namespacing, similar to task naming conventions in monorepos:
python:buildpython:testrust:cargo:buildnode:npm:testWhen a task extends a template, fields are merged according to these rules:
| Field | Behavior |
|---|---|
run, run_windows | Local overrides completely |
tools | Deep merge (local tools added/override template) |
env | Deep merge (local env added/override template) |
depends, depends_post, wait_for | Local overrides completely (not merged) |
dir | Local overrides; defaults to config_root if not in template |
sources, outputs | Local overrides completely |
| Sandbox deny fields | Compose with task-local settings |
| Sandbox allow fields | Template and task-local values are combined |
description, shell, timeout, etc. | Local overrides template (if set) |
quiet, hide, raw | Not carried over (must be set explicitly in task) |
[task_templates."fullstack:build"]
tools = { python = "3.12", node = "18" }
[tasks.build]
extends = "fullstack:build"
tools = { node = "20" } # Override node, keep python from template
# Result: tools = { python = "3.12", node = "20" }
[task_templates."python:build"]
env = { PYTHONPATH = "src", DEBUG = "0" }
[tasks.build]
extends = "python:build"
env = { DEBUG = "1" } # Override DEBUG, keep PYTHONPATH from template
# Result: env = { PYTHONPATH = "src", DEBUG = "1" }
[task_templates."python:test"]
depends = ["lint", "typecheck"]
[tasks.test]
extends = "python:test"
depends = ["build"] # Completely replaces template depends
# Result: depends = ["build"] (lint and typecheck NOT included)
Templates support Tera templating, rendered with the using project's context:
[task_templates."python:build"]
description = "Build Python project"
dir = "{{ config_root }}" # Resolves to the PROJECT's directory
run = "uv build"
env = { PROJECT = "{{ config_root | basename }}" }
Available variables (same as regular tasks):
Task templates are especially useful in monorepos where multiple packages share similar build patterns:
# Root mise.toml
[settings]
experimental = true
experimental_monorepo_root = true
[task_templates."python:build"]
run = "uv build"
tools = { python = "3.12", uv = "latest" }
[task_templates."python:test"]
run = "pytest"
tools = { python = "3.12" }
depends = ["build"]
[task_templates."python:lint"]
run = "ruff check ."
tools = { python = "3.12", ruff = "latest" }
# packages/api/mise.toml
[tasks.build]
extends = "python:build"
[tasks.test]
extends = "python:test"
run = "pytest --cov" # Add coverage
[tasks.lint]
extends = "python:lint"
# packages/worker/mise.toml
[tasks.build]
extends = "python:build"
[tasks.test]
extends = "python:test"
[tasks.lint]
extends = "python:lint"
The following features are planned for future releases:
~/.config/mise/config.toml for use across all projectspython:* templates when pyproject.toml exists)