Task Configuration
This is an exhaustive list of the configuration options available for tasks in mise.toml or as file tasks.
Task properties
All examples use the toml-task format rather than file tasks, but they apply to both except where otherwise noted.
run
- Type:
string | (string | { task: string, args?: string[], env?: { [key]: string } } | { tasks: string[] })[]
The commands or execution steps to run. A task may instead use file, inherit its command through extends, or contain only dependencies to group other tasks. Each run entry finishes before the next starts; a { tasks = [...] } entry runs its listed tasks in parallel.
You can mix scripts with task references, and pass optional args and env to referenced tasks:
[tasks.grouped]
run = [
{ task = "t1" }, # run t1 (with its dependencies)
{ task = "build", args = ["--release"], env = { RUSTFLAGS = "-C opt-level=3" } },
{ tasks = ["t2", "t3"] }, # run t2 and t3 in parallel (with their dependencies)
"echo end", # then run a script
]{ task } and { tasks } are execution steps for this task, not depends. They still run with their own dependencies. mise tasks deps does not include them as graph edges. See mise tasks deps.
Simple forms still work and are equivalent:
tasks.a = "echo hello"
tasks.b = ["echo hello"]
tasks.c.run = "echo hello"
[tasks.d]
run = "echo hello"
[tasks.e]
run = ["echo hello"]run_windows
- Type:
string | (string | { task: string, args?: string[], env?: { [key]: string } } | { tasks: string[] })[]
A Windows-specific variant of run that supports the same structured syntax:
[tasks.build]
run = "cargo build"
run_windows = "cargo build --features windows"file
- Type:
string
Execute an external script instead of an inline run command. Relative paths are resolved from the directory containing the task's config file. The path supports Tera templates.
[tasks.release]
description = "Cut a new release"
file = "scripts/release.sh"file also accepts HTTP(S) URLs and git:: sources. See Using a file or remote script for the supported formats and security considerations.
description
- Type:
string
A description of the task. This is used in (among other places) the help output, completions, mise run (without arguments), and mise tasks.
[tasks.build]
description = "Build the CLI"
run = "cargo build"alias
- Type:
string | string[]
An alias for the task so you can run it with mise run <alias> instead of the full task name.
[tasks.build]
alias = "b" # run with `mise run b`
run = "cargo build"depends
- Type:
string | (string | string[] | { task: string, args?: string[], env?: { [key]: string }, optional?: bool })[]
Tasks that must run before this task, given as a list of task names or aliases. Arguments can be passed to a dependency, e.g.: depends = ["build --release"]. If multiple tasks share a dependency, that dependency runs only once. mise runs whatever it can in parallel (up to --jobs) based on depends and related properties.
mise tasks deps visualizes this declared graph (depends, wait_for, depends_post), not task references inside run.
[tasks.build]
run = "cargo build"
[tasks.test]
depends = ["build"]
run = "cargo test"Passing environment variables to dependencies
You can pass environment variables to specific dependencies using two syntaxes:
Shell-style inline:
[tasks.test]
depends = ["NODE_ENV=test setup"]
run = "npm test"
[tasks.setup]
run = 'echo "Setting up for $NODE_ENV"'Structured object format:
[tasks.test]
depends = [
{ task = "setup", env = { NODE_ENV = "test", DEBUG = "true" } }
]
run = "npm test"The structured format also supports combining env vars with arguments:
[tasks.deploy]
depends = [
{ task = "build", args = ["--release"], env = { RUSTFLAGS = "-C opt-level=3" } }
]
run = "./deploy.sh"String and structured dependencies can be mixed in the same array:
[tasks.check]
depends = [
"lint",
{ task = "test", env = { CI = "true" } },
]
run = "echo checks complete"These environment variables are passed only to the specified dependency, not to the current task or other dependencies.
Optional dependencies
Set optional = true on a structured dependency to run matching tasks when they exist, without failing when the task name or pattern matches nothing. Invalid task patterns still produce an error.
[tasks.test]
depends = [
{ task = "//...:test", optional = true },
{ task = "//...:test:*", optional = true },
]Passing parent task arguments to dependencies
You can forward a parent task's arguments to its dependencies using {{usage.*}} templates. Both the parent and child tasks must define a usage spec for the arguments they accept:
[tasks.build]
usage = 'arg "<app>"'
run = 'echo "building {{usage.app}}"'
[tasks.deploy]
usage = 'arg "<app>"'
depends = [{ task = "build", args = ["{{usage.app}}"] }]
run = 'echo "deploying {{usage.app}}"'Running mise run deploy myapp passes "myapp" to both deploy and its build dependency.
This also works with the string syntax:
[tasks.deploy]
usage = 'arg "<app>"'
depends = ["build {{usage.app}}"]
run = 'echo "deploying {{usage.app}}"'And with flags:
[tasks.compile]
usage = 'flag "--target <target>"'
run = 'echo "compiling for $usage_target"'
[tasks.package]
usage = 'flag "--target <target>"'
depends = [{ task = "compile", args = ["--target", "{{usage.target}}"] }]
run = 'echo "packaging for $usage_target"'Arguments flow through dependency chains — if A depends on B which depends on C, each task can forward its resolved arguments to its own dependencies.
depends_post
- Type:
string | (string | string[] | { task: string, args?: string[], env?: { [key]: string }, optional?: bool })[]
Like depends, but these tasks run after this task and its dependencies complete. For example, you may want a postlint task that you can run individually without also running lint:
[tasks.lint]
run = "eslint ."
depends_post = ["postlint"]
[tasks.postlint]
run = "echo 'linting complete'"Supports the same argument, environment variable, and optional dependency syntax as depends. Dependencies of a depends_post task also wait until the parent task finishes, so an entire cleanup chain runs after the main work. mise runs the full subtree if the parent started, even when the parent fails, but skips it when a regular dependency fails before the parent can start. The same task may be referenced by both depends and depends_post; in that case it runs once before the parent and once afterward.
wait_for
- Type:
string | (string | string[] | { task: string, args?: string[], env?: { [key]: string }, optional?: bool })[]
Like depends, this waits for the listed tasks to complete before running. Unlike depends, wait_for does not add matching tasks to the run; it only waits for them when they are already scheduled. To allow a task name or pattern to have no configured matches, use optional = true.
[tasks.lint]
wait_for = ["render"] # creates some js files, so if it's running, wait for it to finish
run = "eslint ."Supports the same argument, environment variable, and optional dependency syntax as depends.
wait_for matches tasks differently depending on whether args or env vars are specified:
wait_for = ["setup"]— matches by name, regardless of args or env overrides. If another task runsdepends = ["DEBUG=1 setup"], this will still match and wait for it.wait_for = ["setup arg1"]orwait_for = ["DEBUG=1 setup"]— matches only tasks running with that exact args/env configuration.
env
- Type:
{ [key]: string | int | bool }
Environment variables specific to this task. These are not passed to depends tasks.
[tasks.test]
env.TEST_ENV_VAR = "ABC"
run = [
"echo $TEST_ENV_VAR",
"mise run some-other-task", # running tasks like this _will_ have TEST_ENV_VAR set of course
]vars
- Type:
{ [key]: string | int | bool | directive }
Variables specific to this task. Task-local vars override config vars while rendering the task, but are not exported to the task process as environment variables.
[vars]
mode = "headless"
[tasks.test]
vars = { mode = "headed" }
run = "./scripts/test-e2e.sh --{{ vars.mode }}"See configuration variables for supported directives, precedence, and redaction.
tools
- Type:
{ [key]: string }
Tools to install and activate before running the task. This is useful for tasks that require a specific tool or a different version of a tool. These tools apply only to that task, not to its dependencies.
[tasks.build]
tools.rust = "1.50.0"
run = "cargo build"Run mise lock to resolve task-specific tools into the owning config's lockfile before running the task. This reads the task definition without executing the task or installing its tools.
Run mise install --include-task-tools to install tools for every task in the current scope without executing task commands or dependencies. This is useful for preparing CI caches or container images; combine it with --monorepo to include every configured monorepo root.
dir
- Type:
string - Default:
"{{ config_root }}"- the directory containingmise.toml, or for a path like~/src/myproj/.config/mise.toml,~/src/myproj.
The directory to run the task from. Most commonly, this is used to run the task in the user's current directory:
[tasks.test]
dir = "{{cwd}}"
run = "cargo test"hide
- Type:
bool - Default:
false
Hide the task from help, completion, and other output like mise tasks. Useful for deprecated or internal tasks you don't want others to easily see.
[tasks.internal]
hide = true
run = "echo my internal task"confirm
- Type:
string|{ message: string, default: string }
A message to show before running the task. This is useful for tasks that are destructive or take a long time to run. The user is prompted to confirm before the task's own run command executes.
WARNING
confirm only guards the task's own run command. Dependencies (depends) execute before the confirmation prompt appears. If you need confirmation before dependencies run, add confirm to the dependency tasks themselves, or use run = [{ task = "..." }] instead of depends.
[tasks.release]
confirm = { message = "Are you sure you want to cut a release?", default = "no" }
description = 'Cut a new release'
file = 'scripts/release.sh'The confirm message supports Tera templates and can reference usage arguments:
[tasks.deploy]
usage = '''
arg "<environment>" help="Environment to deploy to"
flag "--force" help="Force deployment"
'''
confirm = "Deploy to {{ usage.environment }}?{% if usage.force %} (forced){% endif %}"
run = "deploy.sh ${usage_environment}"raw
- Type:
bool - Default:
false
Connects the task directly to the shell's stdin/stdout/stderr. This is useful for tasks that need to accept input or output in a way that mise's normal task handling doesn't support.
A raw command holds an exclusive lock for as long as it runs, so mise will not run another command alongside it and you do not have to keep other tasks out of the way yourself. The lock is taken per command rather than per task, so two raw tasks can still take turns between their individual commands. If you need a whole task to run without interruption, search for or file a ticket requesting a property like single = true.
raw_args
- Type:
bool - Default:
false
When true, mise does not parse arguments to the task at all — every argument is passed through verbatim to the underlying command, including --help/-h. Use this for tasks that act as a thin proxy for a tool that already has its own argument parser (e.g. next build, Django manage.py, Python scripts using argparse):
[tasks.manage]
raw_args = true
run = 'python manage.py'mise run manage --help # forwarded to manage.py, not intercepted by mise
mise run manage migrate --fake # all flags reach manage.py unchangedWithout raw_args, mise intercepts --help and prints its own task help. As an ad-hoc alternative for individual invocations, you can also use mise run task -- --help — the -- separator bypasses mise's usage parser for --help/-h. Arguments after that separator belong to the task, so mise run task -- -- --help forwards -- --help to the task.
interactive
- Type:
bool - Default:
false
Connects the task directly to the shell's stdin/stdout/stderr. Interactive tasks acquire an exclusive lock, ensuring sole access to standard I/O — while an interactive task is running, all other tasks (both interactive and non-interactive) are blocked. Non-interactive tasks can still run in parallel with each other. This is more targeted than raw, which takes its exclusive lock per command, and than mise run --raw, which goes further and forces single-threaded execution globally (by setting jobs = 1).
sources
- Type:
string | string[]
Files or directories that this task uses as input. If both this and outputs are defined, mise skips the task when the modification time of the oldest output file is newer than the modification time of the newest source file. This is useful for tasks that are expensive to run and only need to run when their inputs change.
The task definition itself is automatically added as a source, so editing the definition also causes the task to run.
mise watch also uses sources to know which files and directories to watch.
Entries can be relative paths and/or glob patterns, e.g.: src/**/*.rs. Brace alternatives such as src/**/*.{js,ts} are supported by freshness checks, mise watch, and task_source_files(). Don't go overboard with globs that match a huge number of files, though—mise has to scan each and every one to check its timestamp.
[tasks.build]
run = "cargo build"
sources = ["Cargo.toml", "src/**/*.rs"]
outputs = ["target/debug/mycli"]Running the above executes cargo build only if mise.toml, Cargo.toml, or any ".rs" file in the src directory has changed since the last build.
Relative entries are resolved from the task directory (the task's dir, or the project root when it has none) and may use .. to reach files above it, such as a node_modules directory shared at the root of a monorepo:
[tasks.build]
dir = "packages/web"
run = "npm run build"
sources = ["src/**/*.ts", "../../node_modules/**"]
outputs = ["dist"]Use the task_source_files function to iterate over a task's sources within its template context.
Excluding sources
Entries in sources prefixed with ! are excluded, matching the convention used by gitignore, watchexec, and rsync. Exclusions affect the freshness check, the task_source_files template function, and which files mise watch watches for changes.
[tasks.build]
sources = ["src/**/*.ts", "!src/**/*.test.ts", "!src/**/*.spec.ts", "tsconfig.json"]
run = "npm run build"Entries are evaluated in order, and the latest matching entry wins. A later non-negated entry can re-include a file an earlier ! excluded — for example, ["src/**/*.ts", "!src/**/*.test.ts", "src/keep.test.ts"] excludes all *.test.ts files except src/keep.test.ts.
To include a literal path that begins with !, escape the prefix as \! (e.g. "\\!important.txt" in TOML).
Reusable and global inputs experimental
Use [task_config.input_groups] to define source patterns once and reuse them across tasks. Reference a group from sources with @group:<name>. Groups can reference other groups; undefined references and cycles are configuration errors.
Group entries are resolved relative to the config file that defines them, even when a task uses a different dir. Ordinary entries written directly in sources remain relative to the task directory.
[settings]
experimental = true
[task_config.input_groups]
toolchain = ["rust-toolchain.toml", "Cargo.lock"]
rust = ["Cargo.toml", "src/**/*.rs", "@group:toolchain"]
[tasks.build]
run = "cargo build"
sources = ["@group:rust"]
outputs = ["target/debug/mycli"]
[tasks.test]
run = "cargo test"
sources = ["@group:rust"]
outputs = []task_config.global_inputs adds source patterns to every task in the config scope. This is useful for repository-wide configuration and lockfiles that should invalidate all cacheable tasks without being repeated in each task's sources. Global inputs may also reference named groups.
[task_config]
global_inputs = ["mise.toml", ".github/tool-versions", "@group:lockfiles"]
[task_config.input_groups]
lockfiles = ["Cargo.lock", "pnpm-lock.yaml"]Dependency invalidation
When a task depends on another task that also has sources defined, and the dependency runs because its sources changed, the dependent task also re-runs — even if the dependent's own sources haven't changed. This is useful for monorepo workflows where downstream tasks should be invalidated by upstream changes:
[tasks."core:build"]
run = "tsc -p packages/core"
sources = ["packages/core/src/**/*.ts"]
outputs = ["packages/core/dist/**/*.js"]
[tasks."frontend:build"]
run = "tsc -p packages/frontend"
sources = ["packages/frontend/src/**/*.ts"]
outputs = ["packages/frontend/dist/**/*.js"]
depends = ["core:build"]If a file in packages/core/src/ changes, both core:build and frontend:build run. If nothing changes, both are skipped.
Dependencies without sources (which always run) do not trigger this invalidation — otherwise sources on the dependent task would be effectively useless.
watch
- Type:
{ no_vcs_ignore = bool } - Default:
{ no_vcs_ignore = false }
Options used when the task runs through mise watch. By default, mise watch respects VCS ignore files such as .gitignore, even when an ignored path is listed in sources. Set watch.no_vcs_ignore for tasks that need to watch generated or intermediary files that are intentionally excluded from version control:
[tasks.generate]
run = "process generated/output.json"
sources = ["generated/output.json"]
watch = { no_vcs_ignore = true }This is equivalent to passing --no-vcs-ignore to watchexec. Because watchexec applies ignore options to the entire watch process, watching multiple tasks together disables VCS ignores for all of them if any selected task enables this option. Keep sources narrowly scoped: disabling VCS ignores for broad build, distribution, or dependency directories may substantially increase filesystem scanning.
outputs
- Type:
string | string[] | { auto = true } - Default:
{ auto = true }
The counterpart to sources: the files or directories that the task creates or modifies when it runs.
Entries prefixed with ! exclude matching outputs. As with sources, entries are evaluated in order, a later entry can re-include a path, and \! escapes a literal leading bang. Output globs also support brace alternatives such as dist/{client,server}/**.
[tasks.build]
run = "npm run build"
sources = ["src/**"]
outputs = ["dist", "!dist/**/*.map", "!dist/.vite/**"]Excluded files do not participate in output freshness checks and are not stored in task-cache artifacts. If excluded files already exist beneath an output directory when a cached artifact is restored, mise preserves them.
auto = true is an alternative to specifying output files manually. In that case, mise touches an internally tracked file based on the hash of the task definition (stored in ~/.local/state/mise/task-outputs/<hash> if you're curious). This is useful if you want mise run to execute when sources change but don't want to touch a file manually for sources to work.
[tasks.build]
run = "cargo build"
sources = ["Cargo.toml", "src/**/*.rs"]
outputs = { auto = true } # this is the default when sources is definedcache experimental
- Type:
{ enabled = bool, audit = bool, env = string[], command_inputs = string[] } - Default:
{ enabled = false, audit = false, env = [], command_inputs = [] }
Cache a successful task result by its declared inputs. A cache hit restores explicit outputs and replays captured logs. Requires experimental features, matching sources, and explicit output paths or outputs = [].
See Task caching for setup, input declarations, debugging, remote service configuration, and cache retention. outputs = { auto = true } supports freshness checks but cannot store artifacts.
External dependencies and lockfiles
See external dependencies and lockfiles.
Per-run cache access
See per-run cache access.
Remote cache and sensitive data
See remote cache and sensitive data.
Cache correctness and deterministic tasks
See cache correctness and deterministic tasks.
rust_cache deprecated
- Type:
boolean | table - Default:
false
This setting no longer enables Rust compiler action caching. mise accepts it temporarily as a deprecated no-op so existing task configurations continue to run. Enabled values print a migration warning; disabled values are silent.
Use mbx for Rust action caching instead. Install it globally with mise use -g mr-boxington, or add it to the project tools. To keep existing task commands unchanged, configure mise's cargo command wrapper:
[tools]
mr-boxington = "latest"
[wrappers.cargo]
command = "mbx"
env = { MBX_CARGO_SHIM_MODE = "1" }
[tasks.build]
run = "cargo build"Run mise reshim after adding the wrapper, then remove rust_cache. The compatibility field is scheduled for removal in mise 2027.8.14.
shell
- Type:
string - Default:
task_config.shellwhen set (config-scoped); otherwiseunix_default_inline_shell_args/windows_default_inline_shell_args(global-only). - Note: Only applies to toml-tasks.
The shell used to run the task. This is useful if you want a task to use a shell other than the default, such as fish, zsh, or pwsh. Generally, though, a shebang is recommended instead because it lets IDEs with mise support show syntax highlighting and linting for the script.
When the shell is PowerShell (pwsh or powershell), mise passes -NoProfile so your PowerShell profile is not loaded, matching the non-interactive behavior of sh -c/zsh -c. This prevents profiles that mutate PATH (for example, a mise activation snippet) from shadowing a task's own installed tools. Set windows_powershell_no_profile to false if your tasks depend on side effects from your profile.
[tasks.hello]
run = '''
#!/usr/bin/env node
console.log('hello world')
'''timeout
- Type:
string - Default: unset
Maximum execution time for this task. The value accepts durations such as 30s, 5m, or 1h and supports Tera templates. The task fails if it does not complete within the configured duration.
[tasks.integration-test]
run = "./scripts/integration-test.sh"
timeout = "10m"This limits the individual task. Use mise run --timeout or the task.timeout setting to limit the entire task run. When both a global timeout and a per-task timeout are set, the shorter of the two wins: a per-task timeout cannot extend beyond the global timeout. The --timeout CLI flag overrides the global setting.
deny_all
- Type:
bool - Default:
false
Block filesystem reads, filesystem writes, network access, and environment inheritance for this task. Specific allow_* properties can add exceptions.
[tasks.lint]
run = "eslint ."
deny_all = true
allow_read = ["."]
allow_write = ["./node_modules/.cache"]
allow_env = ["NODE_*"]Sandbox support and implicit system access vary by platform. See Sandboxing for the complete behavior and limitations.
deny_read
- Type:
bool - Default:
false
Block filesystem reads except for the system and mise paths required to execute the task. Use allow_read to add task-specific exceptions.
deny_write
- Type:
bool - Default:
false
Block filesystem writes except for implicitly writable system paths such as the temporary directory. Use allow_write to add task-specific exceptions.
deny_net
- Type:
bool - Default:
false
Block network access for this task. Use allow_net for host-specific exceptions on platforms that support them.
deny_env
- Type:
bool - Default:
false
Block inherited environment variables except for essential variables such as PATH, HOME, USER, SHELL, TERM, and LANG. Use allow_env or pass_through_env to preserve additional variables.
allow_read
- Type:
string[] - Default:
[]
Allow reads from the listed paths and block other filesystem reads. Relative paths are resolved from the task's effective working directory.
allow_write
- Type:
string[] - Default:
[]
Allow writes to the listed paths and block other filesystem writes. Allowed write paths are also readable. Relative paths are resolved from the task's effective working directory.
allow_net
- Type:
string[] - Default:
[]
Allow network access to the listed hosts and block other network access. Per-host network filtering is platform-dependent; see Platform Support.
allow_env
- Type:
string[] - Default:
[]
Allow the listed environment variable names and block other inherited environment variables. Entries support * wildcards, such as MYAPP_*.
pass_through_env experimental
- Type:
string[] - Default:
[]
Preserve the listed ambient environment variables when environment inheritance is denied without including their values in the task cache key. Entries support * wildcards. This property does not enable environment sandboxing by itself and has no effect unless environment sandboxing is active, including through allow_env, deny_env, deny_all, or an equivalent CLI or global sandbox option.
Use pass_through_env for values such as short-lived credentials that must not affect the cache key. Do not use it for values that affect generated outputs or logs. Use cache.env instead when changes to a variable should invalidate the task cache.
quiet
- Type:
bool - Default:
false
Suppress mise's own output for the task, such as the command being run, e.g.: [build] $ cargo build. When this is set, mise shows nothing other than what the script itself outputs. To hide the task's own output as well, use silent.
quiet is a verbosity setting and is independent of the output style: it does not force un-prefixed output, so output = "prefix" together with quiet = true keeps the task-name prefixes while hiding mise's own messages.
silent
- Type:
bool | "stdout" | "stderr" - Default:
false
Suppress all output from the task. If set to "stdout" or "stderr", only that stream is suppressed.
output
- Type:
string - Default: unset (inherits the global
task.outputsetting)
Output style for this task: prefix, interleave, keep-order, replacing, timed, quiet, or silent. This is the per-task equivalent of the global task.output setting and is orthogonal to the quiet/silent verbosity fields, so styles and quietness combine freely (e.g. output = "prefix" + quiet = true). The quiet/silent values are kept for backwards compatibility and bundle a style with that verbosity.
Deprecated
The quiet output value is deprecated. Warnings begin in mise 2026.9.3, and support will be removed in 2027.9.3. Use output = "interleave" with quiet = true instead. For a global task default, use task.output = "interleave" with task.quiet = true under [settings].
usage
- Type:
string
TIP
For comprehensive information about task arguments and the usage field, see the dedicated Task Arguments page.
More advanced usage specs can be added to the task's usage field. This only applies to toml-tasks.
[tasks.test]
usage = '''
arg "<file>" help="The file to test" default="src/main.rs"
'''
run = 'cargo test ${usage_file?}'Environment Variable Support for Args and Flags
Both args and flags in usage specs can specify an environment variable as an alternative source for their value. This lets task arguments be provided through environment variables when they are not specified on the command line.
The precedence order is:
- CLI arguments/flags (highest priority)
- Environment variables (middle priority)
- Default values (lowest priority)
For positional arguments:
[tasks.deploy]
usage = '''
arg "<environment>" env="DEPLOY_ENV" help="Target environment" default="staging"
arg "<region>" env="AWS_REGION" help="AWS region" default="us-east-1"
'''
run = '''
echo "Deploying to ${usage_environment?} in ${usage_region?}"
'''Usage examples:
# Using CLI args (highest priority)
mise run deploy production us-west-2
# Using environment variables
export DEPLOY_ENV=production
export AWS_REGION=us-west-2
mise run deploy
# Using defaults (lowest priority)
mise run deploy # deploys to staging in us-east-1
# CLI overrides environment variable
export DEPLOY_ENV=staging
mise run deploy production # deploys to productionFor flags:
[tasks.build]
usage = '''
flag "-p --profile <profile>" env="BUILD_PROFILE" help="Build profile" default="dev"
flag "-v --verbose" env="VERBOSE" help="Verbose output"
'''
run = '''
echo "Building with profile: ${usage_profile?}"
echo "Verbose: ${usage_verbose:-false}"
'''Usage examples:
# Using CLI flags
mise run build --profile release --verbose
# Using environment variables
export BUILD_PROFILE=release
export VERBOSE=true
mise run build
# Mixed usage - env var provides one, CLI provides another
export BUILD_PROFILE=release
mise run build --verboseFile tasks (tasks defined as executable files in mise-tasks/ or .mise/tasks/) also support the env attribute:
#!/usr/bin/env bash
#USAGE arg "<input>" env="INPUT_FILE" help="Input file to process"
#USAGE flag "-o --output <file>" env="OUTPUT_FILE" help="Output file" default="out.txt"
echo "Processing ${usage_input?} -> ${usage_output?}"Required arguments:
Environment variables can satisfy required argument checks. If an argument is marked as required (using angle brackets <arg>), providing its value through the environment variable specified in the env attribute fulfills that requirement:
[tasks.deploy]
usage = '''
arg "<api-key>" env="API_KEY" help="API key for deployment"
'''
run = 'deploy --api-key ${usage_api_key?}'# This will fail - no API_KEY provided
mise run deploy
# This succeeds - API_KEY provided via environment
export API_KEY=secret123
mise run deploy
# This also succeeds - provided via CLI
mise run deploy secret123Vars
Top-level configuration vars are available when rendering TOML tasks. Tasks can also define task-local vars that override config vars for that task:
[tasks.test]
vars = { e2e_args = "--headed" }
run = './scripts/test-e2e.sh {{vars.e2e_args}}'[task_config] options
Options available in the top-level mise.toml [task_config] section. These apply to all tasks that are included by that config file or share the same root directory, e.g.: ~/src/myproject/mise.toml's [task_config] applies to file tasks like ~/src/myproject/mise-tasks/mytask. Set cascade = true to also apply the section to tasks owned by descendant config roots.
task_config.cascade
Cascade this config's [task_config] values to descendant config roots. Descendant values override individual inherited fields. A descendant can set cascade = false to stop inheriting the section.
[task_config]
cascade = true
shell = "bash -c"This applies to dir, shell, cache, rust_cache, global_inputs, input_groups, and includes. Inherited include paths and task inputs remain relative to the config root where they were defined.
A descendant's non-empty global_inputs replaces the inherited value. Descendant input_groups merge with inherited groups by name; the nearest definition wins when the same name appears more than once. This also applies to group references in inherited global_inputs. Each group remains relative to the config root where it was defined.
task_config.dir
Change the default directory tasks are run from.
[task_config]
dir = "{{cwd}}"task_config.shell
Set the default shell for tasks in this config scope. A task's explicit shell setting takes precedence, including a shell inherited from a task template. With task_config.cascade = true, descendant config roots inherit this default and may override it with their own task_config.shell.
[task_config]
shell = "bash -c"Unlike the global-only unix_default_inline_shell_args and windows_default_inline_shell_args settings, this default is scoped to project tasks and cannot change the interpreter used by hooks, tool installation, or tasks from another config root.
task_config.cache experimental
Sets the default artifact-cache configuration for tasks in this config scope. The default is only inherited by cache-eligible tasks with sources and either explicit output paths or outputs = []. Task-local and task-template cache configuration takes precedence, including cache = { enabled = false }.
[task_config.cache]
enabled = true
env = ["NODE_ENV", "CI"]
command_inputs = ["node --version"]task_config.rust_cache deprecated
This deprecated compatibility setting no longer enables Rust action caching. An effective enabled value warns once while tasks continue normally. Remove it and run Rust build commands through mbx instead. The wrappers.cargo configuration lets existing tasks keep invoking cargo without modification.
[task_config]
rust_cache = truetask_config.global_env experimental
Adds ambient environment variable names to the cache key of every cache-enabled task in the config scope. These values compose with task-local cache.env rather than acting as defaults.
[task_config]
global_env = ["CI", "NODE_ENV"]task_config.global_pass_through_env experimental
Preserves ambient environment variables when environment inheritance is denied, without adding their values to task cache keys.
[task_config]
global_pass_through_env = ["CI_JOB_TOKEN"]task_config.global_inputs experimental
Adds config-root-relative source paths and glob patterns to every task in this config scope. Entries may reference a named input group with @group:<name>.
[task_config]
global_inputs = ["mise.toml", "@group:lockfiles"]task_config.input_groups experimental
Defines reusable, config-root-relative source groups. Tasks reference them from sources with @group:<name>. Groups may reference other groups.
[task_config.input_groups]
lockfiles = ["Cargo.lock", "pnpm-lock.yaml"]
rust = ["Cargo.toml", "src/**/*.rs", "@group:lockfiles"]task_config.includes
Set the toml files and file-task directories mise should search when looking for tasks.
[task_config]
includes = [
"tasks.toml", # a task toml file
"mytasks" # a directory containing file tasks
]When task_config.includes is set, it replaces the default file-task directories for that config scope instead of adding to them. Include entries are rendered as Tera templates, so they can reference values such as config_root, env, and resolved vars.
The default file-task directories are:
mise-tasks.mise-tasks.mise/tasks.config/mise/tasksmise/tasks
If you want to keep the defaults and add another directory, include the defaults explicitly:
[task_config]
includes = [
"mise-tasks",
".mise-tasks",
".mise/tasks",
".config/mise/tasks",
"mise/tasks",
"mytasks",
"tasks.toml",
]For local and monorepo task discovery, mise uses the nearest config file that defines task_config.includes. When the parent has task_config.cascade = true, its includes are inherited until a child defines its own. A child config's includes replaces both the defaults and any inherited includes for that directory. User-global config files form one config scope, as do system config files. Within each scope, the highest-precedence config that defines task_config.includes replaces lower-precedence includes and the default directories. User-global and system scopes remain independent. User-global tasks replace same-named system tasks without inheriting system task metadata, while system tasks with other names remain available.
Entries are evaluated in order, and when more than one include defines a task with the same name the last entry in the list wins. This applies uniformly to directory, toml-file, and git:: includes, so to override a task coming from a git:: include with a local one, list the local directory after the git:: entry (see the example below).
[task_config]
includes = [
"git::https://github.com/myorg/shared-tasks.git//tasks", # remote task…
".mise/tasks", # …is overridden by the local one with the same name
]An inline [tasks.<name>] command takes precedence over a same-named task from an included TOML file when it comes from the config that selected the include or a higher-precedence config. An inline block without run, run_windows, or file instead overlays metadata such as description, environment, and dependencies. For executable file tasks, the script also remains the task's command and the inline definition overlays its metadata.
The same overlay rule applies across layered inline task definitions. For example, a metadata-only task in mise.local.toml overlays the nearest lower-precedence command-bearing definition in mise.toml. A higher-precedence definition with its own command still replaces the lower task. All metadata-only definitions above the selected command-bearing base contribute in precedence order, while definitions below it do not contribute metadata.
Included task toml files have a different format than mise.toml: they are simply a list of tasks. The file uses the same format as the [tasks] section of mise.toml but without the [tasks] prefix:
task1 = "echo task1"
task2 = "echo task2"
task3 = "echo task3"
[task4]
run = "echo task4"
vars = { target = "linux" }For auto-completion and validation in included toml task files, use the following JSON schema: https://mise.jdx.dev/schema/mise-task.json
Remote Git Includes experimental
You can include directories or individual task toml files from git repositories using the git:: URL syntax:
[task_config]
includes = [
"git::ssh://[email protected]/myorg/shared-tasks.git//tasks?ref=v1.0.0",
"git::ssh://[email protected]/myorg/shared-tasks.git//tasks/release.toml?ref=v1.0.0",
][task_config]
includes = [
"git::https://github.com/myorg/shared-tasks.git//tasks?ref=main",
"git::https://github.com/myorg/shared-tasks.git//tasks/release.toml?ref=main",
]URL format: git::<protocol>://<url>//<path>?ref=<ref>
Required fields:
protocol: The git protocol (ssh or https).url: The git repository URL.path: The path to a directory or a.tomltask file in the repository.
Optional fields:
ref: The git reference (branch, tag, commit). Defaults to the repository's default branch.
When path points at a directory, mise loads both executable file tasks and any .toml task files inside that directory. When path points at a single .toml file, only that file is loaded.
Included .toml files use the task toml file format (the keys are task names — there is no [tasks.…] prefix). The repository is cloned and cached in MISE_CACHE_DIR/remote-git-tasks-cache. Tasks from the include are loaded as if they were local. You can disable caching with MISE_TASK_REMOTE_NO_CACHE=true or the --no-cache flag.
task_config.excludes
Set paths or glob patterns to exclude from file-task discovery. Relative entries resolve from the config root and may exclude a file, an entire directory, or files matched by a glob:
[task_config]
excludes = [
".mise/tasks/python/pyproject.toml",
".mise/tasks/generated",
".mise/tasks/**/fixtures/*.toml",
]The closest config that defines task_config.excludes replaces inherited exclusions. Set it to an empty array to clear exclusions inherited through task_config.cascade = true. Exclusions apply to both the default task directories and paths selected by task_config.includes.
Task directories are searched recursively. Executable files are loaded as file tasks, and every .toml file that is not a mise configuration file is loaded using the included task TOML format. Use task_config.excludes when other TOML files, such as pyproject.toml or Cargo.toml, must live inside a task directory.
Monorepo Support
mise supports monorepo-style task organization with target path syntax. Enable it by setting monorepo_root = true in your root mise.toml.
For complete documentation on monorepo tasks including:
- Task path syntax and wildcards
- Tool layering from parent configs
- Performance tuning
- Best practices and troubleshooting
See the dedicated Monorepo Tasks documentation.
redactions experimental
- Type:
string[]
Redactions hide sensitive information from task output. This is useful for API keys, passwords, and other secrets that you don't want to leak accidentally in logs or other output.
A list of environment variables to redact from the output.
redactions = ["API_KEY", "PASSWORD"]
[env]
API_KEY = "s3cr3t"
[tasks.show-key]
run = 'echo "key: $API_KEY"'Running mise run show-key will output key: [redacted] instead of the value of API_KEY.
You can also specify these as a glob pattern, e.g.: redactions = ["SECRETS_*"].
[vars] options
See Variables.
Task Configuration Settings
The following settings control task behavior. Set them under [settings] in ~/.config/mise/config.toml. Settings that are not marked global-only can also be set per project in mise.toml:
task
task.auto_infer
- Type:
string[] - Env:
MISE_TASK_AUTO_INFER - Default:
[]
List the workspace provider languages whose ecosystem tasks mise should import. For example,
["node"] imports scripts from Node workspace package.json files. Inferred tasks use stable
provider-scoped names and monorepo path aliases. Task inference is opt-in because ecosystem commands
may overlap with explicit mise tasks.
task.cache.audit_report
- Type:
string(optional) - Env:
MISE_TASK_CACHE_AUDIT_REPORT - Default:
None
Write the complete report produced by cache.audit to this
file as JSON Lines, one {"task", "kind", "path"} object per undeclared path. Console warnings
remain limited to the first 20 paths per task.
Truncation happens once per mise invocation: the first audited task in each invocation truncates
the file and later audited tasks in that invocation append to it, so one file holds that run's
report for every audited task and a later run replaces it rather than adding to it. Cached tasks do
not execute and write nothing, leaving an earlier report in place. Relative paths resolve against
mise's working directory.
task.cache.remote_mode
- Type:
string - Env:
MISE_TASK_CACHE_REMOTE_MODE - Default:
read-write - Choices:
read-writeread-onlywrite-only
Control access to the remote cache used by task result and action caching:
read-writereads remote misses and uploads successful local results.read-onlyreads remote misses without uploading results.write-onlyuploads results without reading remote entries.
The per-run --task-cache=local-only mode disables remote task-result access. Action-cache adapters
may further restrict this mode. Remote writes are allowed only from protected-branch push pipelines
in GitHub Actions and GitLab CI; pull requests, unprotected branches, other CI systems, and local
developer runs are read-only. The server must independently enforce the same policy from verified
OIDC claims.
task.cache.remote_namespace
- Type:
string(optional) - Env:
MISE_TASK_CACHE_REMOTE_NAMESPACE - Default:
None
Opaque repository or organization namespace used to isolate remote build-cache entries. This
setting is required when task.cache.remote_url is configured.
task.cache.remote_oidc_audience
- Type:
string(optional) - Env:
MISE_TASK_CACHE_REMOTE_OIDC_AUDIENCE - Default:
None
Acquire a short-lived OIDC token for this audience when running in a supported workload identity environment. GitHub Actions is supported through its OIDC request environment variables. This setting is global-only so shared project configuration cannot choose a token audience.
task.cache.remote_token
- Type:
string(optional) - Env:
MISE_TASK_CACHE_REMOTE_TOKEN - Default:
None
Authenticate remote build-cache requests with an HTTP Authorization: Bearer header. Prefer the
MISE_TASK_CACHE_REMOTE_TOKEN environment variable or a protected global configuration file; this
setting is global-only so shared project configuration cannot supply credentials.
task.cache.remote_token_file
- Type:
string(optional) - Env:
MISE_TASK_CACHE_REMOTE_TOKEN_FILE - Default:
None
Read the remote build-cache bearer token from this file before each request. This supports rotating credentials such as Kubernetes projected service account tokens. This setting is global-only so shared project configuration cannot select a credential file.
task.cache.remote_url
- Type:
string(optional) - Env:
MISE_TASK_CACHE_REMOTE_URL - Default:
None
Enable the versioned HTTP remote build-cache protocol at this base URL. Remote access also requires
task.cache.remote_namespace. Leave unset to use only local caches.
task.cache.stats_report
- Type:
string(optional) - Env:
MISE_TASK_CACHE_STATS_REPORT - Default:
None
Write a versioned JSON report describing Rust action-cache activity, transfer volume, restored
outputs, and phase timings. Timing values use nanoseconds. Concurrent phase timings are cumulative
work time and can exceed the end-to-end session_duration_ns; prefetch_duration_ns is the sum of
wall-clock durations for each task prefetch run.
This is intended for CI qualification and benchmarking. Relative paths resolve against mise's
working directory. The report is replaced atomically after each mise run invocation that creates
an action-cache session.
task.cache_dir
- Type:
string(optional) - Env:
MISE_TASK_CACHE_DIR - Default:
None
Store task output cache artifacts in this directory instead of
MISE_CACHE_DIR/task-artifacts. mise stores the current artifact format in a
versioned subdirectory and includes custom locations in mise cache clear and
manual and automatic cache pruning.
task.cache_max_age
- Type:
string(optional) - Env:
MISE_TASK_CACHE_MAX_AGE - Default:
None
Remove task output cache entries that have not been accessed within this duration after a new entry
is stored. This limit applies only to the task output cache and is independent of
cache_prune_age. Set to 0s or leave unset to disable the age limit.
task.cache_max_size
- Type:
string(optional) - Env:
MISE_TASK_CACHE_MAX_SIZE - Default:
None
Keep the task output cache at or below this size by removing least-recently-accessed entries after a
new entry is stored. Values accept SI or IEC units such as 500MB or 2GiB. Set to 0 or leave
unset to disable the size limit.
task.disable_paths
- Type:
string[] - Env:
MISE_TASK_DISABLE_PATHS - Default:
[]
Paths that mise will not look for tasks in.
Relative paths set in a config file are resolved from that file's config root. Relative paths from the environment are resolved from the invocation's working directory.
Paths are separated by the OS path separator when using the environment variable,
mise settings set, or mise settings add (: on Unix, ; on Windows).
task.disable_spec_from_run_scripts
- Type:
boolean - Env:
MISE_TASK_DISABLE_SPEC_FROM_RUN_SCRIPTS - Default:
false
When enabled, arg(), option(), and flag() Tera functions in run scripts will not contribute
to the task's usage spec—only the explicit usage field is used.
This is useful for:
- Skipping the extra template pass over run scripts (performance)
- Avoiding two-pass parsing quirks where template functions return empty strings during spec collection
- Early opt-out before Tera template arguments are removed in 2026.11.0
task.monorepo_depth
- Type:
integer - Env:
MISE_TASK_MONOREPO_DEPTH - Default:
5
When using monorepo mode (monorepo_root = true), this controls how deep mise will search for task files in subdirectories.
Depth levels:
- 1 = immediate children only (monorepo_root/projects/)
- 2 = grandchildren (monorepo_root/projects/frontend/)
- 5 = default (5 levels deep)
Performance tip: Reduce this value if you have a very large monorepo and notice
slow task discovery. For example, if your projects are all at projects/*, set to 2.
Example:
[settings]
task.monorepo_depth = 3 # Only search 3 levels deep
Or via environment variable:
export MISE_TASK_MONOREPO_DEPTH=3
task.monorepo_exclude_dirs
- Type:
string[] - Env:
MISE_TASK_MONOREPO_EXCLUDE_DIRS(comma separated) - Default:
[]
If empty (default), uses default exclusions: node_modules, target, dist, build. If you specify any patterns, ONLY those patterns will be excluded (defaults are NOT included). For example, setting to [".temp", "vendor"] will exclude only those two directories.
task.monorepo_respect_gitignore
- Type:
boolean - Env:
MISE_TASK_MONOREPO_RESPECT_GITIGNORE - Default:
true
When enabled, mise will skip directories that are ignored by .gitignore files when discovering tasks in a monorepo.
task.output
- Type:
string(optional) - Env:
MISE_TASK_OUTPUT - Default:
None - Choices:
prefix– (default if jobs > 1) print by line with the prefix of the task nameinterleave– (default if jobs == 1 or all tasks run sequentially) print output as it comes inkeep-order– stream one task's output live while buffering others, printing in definition order as tasks completereplacing– replace stdout each time a line is printed-this uses similar logic asmise installtimed– only show stdout lines that take longer than 1s to completequiet– deprecated: interleave task output and suppress mise's own messages. Useinterleavewith the appropriate quiet setting or flag.silent– print nothing from tasks or mise (nulls stdout and stderr)
Change output style when executing tasks. This controls the output of mise run.
This is the output style axis. Verbosity is a separate axis controlled by
task.quiet/silent (as settings, --quiet/--silent flags, or per-task
fields), so a style can be combined with quietness — e.g. output = "prefix"
together with task.quiet = true keeps the task-name prefixes while suppressing
mise's own task messages. The quiet and silent values below are kept for
backwards compatibility and bundle a style with that verbosity.
::: warning Deprecated
The quiet output value is deprecated. Warnings begin in mise 2026.9.3, and
support will be removed in 2027.9.3. For a global task default, use
task.output = "interleave" with task.quiet = true. For an individual task,
use output = "interleave" with quiet = true. On the command line, use
--output interleave --quiet.
:::
task.quiet
- Type:
boolean - Env:
MISE_TASK_QUIET - Default:
false
Suppress mise's own output while executing tasks without affecting other mise
commands. Task stdout and stderr remain visible. This setting is independent of
the task.output style, so it can be combined with prefix, interleave, or
another output style.
task.remote_no_cache
- Type:
boolean(optional) - Env:
MISE_TASK_REMOTE_NO_CACHE - Default:
None
Mise will always fetch the latest tasks from the remote, by default the cache is used.
task.run_auto_install
- Type:
boolean - Env:
MISE_TASK_RUN_AUTO_INSTALL - Default:
true
Automatically install missing tools when executing tasks.
task.show_full_cmd
- Type:
boolean - Env:
MISE_TASK_SHOW_FULL_CMD - Default:
false
Disable truncation of command lines in task execution output. When true, the full command line will be shown.
task.skip
- Type:
string[] - Env:
MISE_TASK_SKIP - Default:
[]
Tasks to skip when running mise run.
task.skip_depends
- Type:
boolean - Env:
MISE_TASK_SKIP_DEPENDS - Default:
false
Run only specified tasks skipping all dependencies.
task.source_freshness_equal_mtime_is_fresh
- Type:
boolean - Env:
MISE_TASK_SOURCE_FRESHNESS_EQUAL_MTIME_IS_FRESH - Default:
false
When source mtime equals output mtime, consider sources fresh (use <=). Default false uses strict < comparison.
task.source_freshness_hash_contents
- Type:
boolean - Env:
MISE_TASK_SOURCE_FRESHNESS_HASH_CONTENTS - Default:
false
Use content hashing (blake3) instead of metadata for source freshness. More accurate but slower.
task.timeout
- Type:
string(optional) - Env:
MISE_TASK_TIMEOUT - Default:
None
Sets a global default timeout for all tasks. Individual tasks can also specify their own timeout.
When both a global timeout and a per-task timeout are set, the shorter of the two always wins—a
per-task timeout cannot extend beyond the global timeout. The --timeout CLI flag overrides this
global setting.
task.timings
- Type:
boolean(optional) - Env:
MISE_TASK_TIMINGS - Default:
None
Show completion message with elapsed time for each task on mise run. Default shows when output type is prefix.