Skip to content

Environment variables ​

Set project environment variables under [env] in mise.toml. mise applies them to commands run with mise exec, to tasks, to shims, and to shells where mise is activated.

For separate files per deployment, such as mise.production.toml, see Config environments. For values that only templates need, use [vars]. To keep secret values out of plaintext config, see Secrets.

Set and unset variables ​

mise.toml
toml
[env]
NODE_ENV = "production"

Check the value in a child process without changing your shell:

sh
mise exec -- sh -c 'echo "$NODE_ENV"'
# production

A value can be a string or an integer; true becomes the string "true". Set a variable to false to unset it, for example one that your shell or a parent directory's config sets:

mise.toml
toml
[env]
NODE_ENV = false

mise set and mise unset edit [env] from the command line:

sh
mise set NODE_ENV=development   # writes NODE_ENV = "development" under [env]
mise set NODE_ENV               # prints development
mise set                        # lists each variable, its value, and the file it comes from
mise unset NODE_ENV             # removes it

mise set writes to the nearest directory that has config. When that directory has both mise.toml and mise.local.toml, it writes mise.toml; see which file a write uses. Pass -E staging to write mise.staging.toml, -g to write the global config, and --prompt or --stdin to keep a value out of your shell history.

To print the resolved environment, including PATH entries and variables that tools set, run mise env. Add --json or --dotenv for other formats.

Where variables apply ​

How you run a commandReceives [env]
mise exec -- <command>Yes
mise run <task>Yes, plus the task's own env
A shell where mise is activatedYes, updated each time you change directories
A shimYes, for the program the shim runs
mise enYes, in a new shell that does not update when you change directories

Variables combine with tools in the same file:

sh
mise use node@24
mise set MY_VAR=123
mise exec -- node -p process.env.MY_VAR
# 123

Task-specific variables ​

A task's own env applies only to that task and accepts the same values and directives as [env]:

mise.toml
mise-toml
[tasks.print]
env = { MY_VAR = "my variable", _.file = ".env.print" }
run = "echo $MY_VAR"

See task env.

Defaults and required variables ​

Defaults ​

default sets a fallback and keeps a value that is already there:

mise.toml
toml
[env]
NODE_ENV = { default = "development" }

mise keeps NODE_ENV when it is already set to a non-empty value, either in the environment mise started with or by a lower-precedence config file such as the global config. Otherwise it sets NODE_ENV to development. A default must be a string or an integer.

Required variables ​

required = true declares a variable that something else must set. mise checks that it is set but never assigns it. The check passes when the variable is in the environment mise started with, or when any other config file sets it, such as mise.local.toml, a parent directory's config or the global config:

mise.toml
toml
[env]
DATABASE_URL = { required = true }
mise.local.toml
toml
[env]
DATABASE_URL = "postgres://localhost/app"

Give required a string instead of true to show help text when the variable is missing:

mise.toml
toml
[env]
DATABASE_URL = { required = "Set DATABASE_URL to your PostgreSQL connection string" }

When a required variable is missing, mise exec, mise run, mise env and mise set stop with an error that includes the help text. An activated shell prints a warning instead and keeps going, so a missing value does not break your prompt:

text
mise WARN  Required environment variable 'DATABASE_URL' is not defined. It must be set before mise runs or in a later config file. (Required in: ~/src/app/mise.toml)
Help: Set DATABASE_URL to your PostgreSQL connection string

required cannot be combined with value or default.

To mask a value in task output, including one a caller supplies for a required variable, mark it with redact = true; see Redaction and CI masking.

Reference other values ​

Values are Tera templates, and they also support shell-style $VAR expansion:

mise.toml
toml
[env]
PROJECT_LIB = "{{config_root}}/lib"
LD_LIBRARY_PATH = "{{env.PROJECT_LIB}}:${LD_LIBRARY_PATH:-}"

A value can use only variables defined above it in the same file, in a lower-precedence config file, or in the environment mise started with.

Templates ​

{{config_root}} is the project directory and {{env.NAME}} reads a variable. See Tera templates for the full context and filters.

Shell-style expansion ​

SyntaxResult
$VARThe value of VAR
${VAR}The same; use it before letters or digits, as in ${VAR}_suffix
${VAR:-default}default when VAR is unset or empty
${VAR:-}An empty string when VAR is unset, without a warning

Expansion runs after template rendering, so a value can mix both. A variable that is not defined and has no default stays as written, and mise prints a warning. Turn expansion off with env_shell_expand = false.

Use values that tools set ​

mise resolves [env] before it loads tools, so values can configure tool installation, for example CFLAGS for a source build. To use something a tool provides, such as its version or its PATH entries, add tools = true. mise then resolves that entry after tools load:

mise.toml
toml
[env]
NODE_VERSION = { value = "{{ tools.node.version }}", tools = true }
_.path = { path = "{{env.GEM_HOME}}/bin", tools = true }

tools = true works on variables, _.file, _.path, _.source and plugin directives. _.python.venv always resolves after tools and does not accept the option.

Precedence ​

When several config files set the same variable, the more specific file wins:

  • mise.local.toml wins over mise.toml.
  • With MISE_ENV=dev, mise.dev.toml wins over mise.toml, mise.local.toml wins over mise.dev.toml, and mise.dev.local.toml wins over all three.
  • A project's config wins over a parent directory's config.
  • Any project config wins over the global config (~/.config/mise/config.toml).

See config files for the full list of locations.

mise evaluates config files from the lowest precedence to the highest, and the entries in each file in the order you write them, so each value can reference anything set before it. A value in [env] replaces a variable of the same name in the environment mise started with; default and required are the exceptions described above.

Env directives ​

Directives load variables from files and scripts and add PATH entries. They live in a table named _, because a variable cannot contain a nested table. _.file, _.path and _.source each take a path, a table with path and options, or an array of either:

mise.toml
toml
[env]
_.file = ".env"
_.path = ["bin", "node_modules/.bin"]
_.source = { path = "scripts/env.sh", redact = true }

Relative paths resolve against the project directory, even when the config file is in .config/mise/ or .mise/ (see config_root). Paths can use templates, $VAR and ~. Directives run in the order you write them, so _.path can use a variable that _.source set above it; _.python.venv always runs last.

Option_.file_.source_.pathEffect
pathYesYesYesOne path or a list of paths
toolsYesYesYesResolve after tools load (details)
redactYesYesNoMark every loaded value as sensitive
expandYesNoNoLet the file use values loaded before it

env._.file ​

Load variables from a file:

mise.toml
toml
[env]
_.file = ".env"
  • The extension selects the format. .json, .yaml and .toml files are parsed as structured files whose top-level keys become variables. Any other name, including .yml and .env, is parsed as dotenv.
  • The path can be a glob pattern such as .env.*; every matching file is loaded.
  • A path that matches no file is skipped without an error, so _.file can point at an optional, untracked .env.
  • Values from the file replace variables already in the environment.
mise.toml
toml
[env]
_.file = [
  ".env.json",
  "~/.config/myapp/.env",
  { path = ".secrets.yaml", redact = true },
]

Dotenv files use KEY=value lines, with # comments and quoted values. Quoting works as in a shell: single-quoted text is literal, and quoted and unquoted parts next to each other are joined with their quotes removed, so 'it'\''s' is it's. A quote with no partner later on its line, as in O'Brien, is kept as written. A partner in a trailing comment still counts, so write NAME="O'Brien" # owner's name. Single-quote a value that must keep its own quotes, such as JSON: CONFIG='{"debug": true}'. A dotenv value can reference variables assigned earlier in the same file, then variables from the environment mise started with. JSON, YAML and TOML values are read literally, so a $ stays a $. Set expand = true to let a file of any format reference values loaded before it, from earlier files or earlier [env] entries:

mise.toml
toml
[env]
BASE = "/opt/project"
_.file = { path = ".env.json", expand = true }

expand = true has no effect when env_shell_expand is false.

mise decrypts SOPS-encrypted JSON, YAML and TOML files as it loads them; see SOPS files.

To load a dotenv file from the current directory and every parent directory, set the env_file setting, for example MISE_ENV_FILE=.env. Unlike _.file, which resolves paths against the config file that declares it, env_file searches upward from the current directory, and a closer file wins.

env._.path ​

Add directories to PATH, ahead of the directories already in it:

mise.toml
toml
[env]
_.path = [
  "bin",
  "{{config_root}}/node_modules/.bin",
  "~/.local/share/mytool/bin",
]

Use _.path for PATH. A PATH key in [env] is ignored by mise exec, mise env and activated shells.

env._.source ​

Run a bash script and take the variables it exports:

mise.toml
toml
[env]
_.source = "scripts/env.sh"

mise runs the script with bash, as if you ran source scripts/env.sh, and ignores its shebang. For another language, use a task or an environment plugin.

  • Variables the script exports or changes are added, and variables it unsets are removed.
  • The path can be a glob pattern, and a path that matches no file is skipped, as with _.file.
  • The script runs each time mise computes the environment, so keep it fast and safe to run more than once.
  • Safe mode never runs it, not even from the global config.

A script can prepend to PATH:

sh
export PATH="/new/bin:$PATH"

mise ignores other PATH changes, such as appending, removing or reordering entries, because it manages PATH entries itself so it can remove them cleanly when you leave the directory. Relative prepended entries resolve against the project directory, and empty entries are ignored.

On Windows, _.source needs a POSIX bash such as Git for Windows or MSYS2. mise finds it the same way it does for bash tasks, including common install locations that are not on PATH; set MISE_BASH_PATH to choose one. mise never uses the WSL launcher at C:\Windows\System32\bash.exe, because WSL cannot read Windows script paths. PATH entries the script prepends in /c/... or /cygdrive/c/... form are converted to Windows form.

env._.python.venv ​

Create and activate a Python virtual environment:

mise.toml
toml
[env]
_.python.venv = { path = ".venv", create = true }

See Automatic virtualenv activation for all options.

Directives from plugins ​

An environment plugin adds its own directive. Install the plugin, then name it under _ with the options the plugin documents:

mise.toml
toml
[env]
_.my-env-plugin = { api_url = "https://api.example.com" }

tools and redact also work on plugin directives. If the plugin is not installed and mise has no source to install it from, mise warns and skips the directive. To write an environment plugin, see Environment plugins.

Variables that configure mise ​

mise reads MISE_* variables such as MISE_DATA_DIR when it starts, before it loads [env], so setting one in [env] does not change how that mise process behaves. Set them in your shell or CI environment, or use [settings]. See MISE_* variables.

The SOPS key variables are the exception: mise reads MISE_SOPS_AGE_KEY and MISE_SOPS_AGE_KEY_FILE from [env] to decrypt encrypted files listed after them; see SOPS files.

Turn off config env ​

mise --no-env, MISE_NO_ENV=1 or the no_env setting skips [env] and env directives from every config file.

In safe mode (MISE_SAFE=1), mise ignores [env] and env directives from project config, and never runs _.source.

Next steps ​

  • Secrets: encrypt values or fetch them from a secret manager, and mask them in output.
  • Config environments: switch sets of values with MISE_ENV.
  • Hooks: run commands when you enter or leave a project.
  • Tera templates: the functions and filters values can use.

Deprecated syntax ​

DeprecatedUse insteadRemoved in
env.mise.*env._.*2026.12.0
value or values in a _.file, _.path or _.source tablepath2026.12.0
Top-level env_file or dotenvenv._.file2027.4.0
Top-level env_pathenv._.path2027.4.0

The value and values rule also applies to directives under vars._. It does not affect value in an ordinary variable table, such as SECRET = { value = "...", redact = true }, or the options of plugin directives.

MIT LicenseCopyright © 2026jdx.dev