Getting started

Introduction

mise installs and switches dev tool versions per project and manages env vars and tasks. This reference covers the CLI and mise.toml.

Install

curl -fsSL https://mise.run | sh   # → ~/.local/bin/mise
brew install mise               # works, installer preferred

# Debian/Ubuntu
sudo apt install -y extrepo
sudo extrepo enable mise && sudo apt update
sudo apt install -y mise

# installer only: not on PATH until activation
export PATH="$HOME/.local/bin:$PATH"
mise --version
mise doctor                     # diagnose shell/shim problems

The installer drops the binary in ~/.local/bin; activation adds it to PATH.

See: Installing mise

Activate

eval "$(mise activate zsh)"                # ~/.zshrc
eval "$(mise activate bash)"               # ~/.bashrc
eval "$(~/.local/bin/mise activate bash)"  # if mise is not on PATH

# fish
mise activate fish | source

Activation re-exports PATH and project env on every prompt. Put it in the interactive rc file — not ~/.profile/~/.zprofile — then restart the shell.

See: mise activate

Shims

eval "$(mise activate zsh --shims)"
export PATH="$HOME/.local/share/mise/shims:$PATH"   # equivalent
mise reshim                      # after external installs

Shims give editors and scripts a stable path; mise activate supports more features (env vars, hooks), so prefer it interactively.

See: Shims

Core commands

Tools

CommandGoal
mise use node@24Add a tool to the project
mise use -g node@24Set a personal default
mise installInstall config tools
mise exec -- node -vRun one command with tools

Inspect

CommandGoal
mise ls --currentShow active versions
mise config lsShow loaded config files
mise tasks lsList project tasks
mise doctorCheck the install

mise exec and mise run load tools and env without activation — use them in scripts and CI.

See: Getting started, Walkthrough

Update

mise self-update              # update the mise binary
mise outdated                 # newer versions in the current range
mise upgrade node             # upgrade within the request (24.x)
mise upgrade --bump node      # latest overall, rewrites mise.toml

mise settings self_update.auto=true keeps the mise binary current; package-manager installs update via their manager.

See: mise self-update, mise upgrade

Tools

Add tools

mise use node@24 python@3.13     # install + record in mise.toml
mise use -g ripgrep              # global default
mise use --pin node@24           # save the exact resolved version
mise use --path .tool-versions --pin node@24
mise use                         # interactive tool picker
[tools]
node = "24"
python = "3.13"

use writes to the lowest-precedence config in the nearest config directory. No version means latest; activation or mise exec picks it up.

See: mise use, dev tools

Install tools

mise install                     # everything in config
mise install node@20             # latest 20.x
mise install node@20.19.0        # exact version
mise install --include-task-tools
mise uninstall node@18.0.0       # remove installed version only

install downloads without touching mise.toml; uninstall removes a version, mise unuse edits the config.

See: mise install

Version requests

[tools]
node = "24"             # latest 24.x
python = "3.13.1"       # exact
ruby = "latest"
go = "prefix:1.19"      # latest 1.19.x
shfmt = "path:./shfmt"  # existing directory
"cargo:owner/tool" = "tag:v1.2.3"  # git ref build

A request is a range; an exact version is a pin. prefix: disambiguates a release named exactly 1.19. Aliases like lts are not universal.

See: Version requests

Inspect

mise ls                    # installed + requested versions
mise ls --current          # versions selected by config
mise ls-remote node@20     # available releases
mise latest node@20        # newest match, without installing
mise which node            # path of the executable in use
mise where node@20         # install directory

which explains a surprising node -v; where finds the install tree.

See: mise ls, mise which

Lock and prune

mise lock                  # write mise.lock (versions + checksums)
mise install --locked      # install from the lockfile
mise prune --dry-run       # show unused installed versions
mise ls --prunable

mise.lock records resolved versions for teammates and CI; prune deletes only versions unused by any tracked config or executed stub.

See: mise lock, mise prune

Backends

Registry shorthands

mise search jq             # search the registry
mise registry node         # → core:node
mise registry -b core      # all built-in tools

The registry maps names like node, terraform, or ripgrep to a backend, so you rarely need to name one. mise search --all queries package registries.

See: Tool registry

Backend prefixes

PrefixSource
core:built-in installers (core:python)
aqua:Aqua registry (aqua:aws/aws-cli)
github:GitHub releases (github:BurntSushi/ripgrep)
npm:npm packages (npm:prettier)
pypi:Python packages (pypi:black, also pipx:)
cargo:crates (cargo:starship)
go:Go modules (go:github.com/DarthSim/hivemind)
asdf:asdf plugins (asdf:owner/plugin)

Package backends need their runtime declared — e.g. mise use rust@stable cargo:starship.

See: Backends, Registry

Examples

mise use aqua:aws/aws-cli             # Aqua registry
mise use github:BurntSushi/ripgrep    # GitHub releases
mise use npm:prettier                 # npm package
mise use pypi:ruff                    # Python package
mise use cargo:starship               # crates.io crate

Add a version the same way: mise use github:BurntSushi/ripgrep@14.

See: Aqua, GitHub

One-off and session tools

mise exec node@20 -- node app.js    # alias: mise x
mise x -- node --version            # uses project config
mise exec --command "node -v"
mise shell node@20                  # this shell session only
mise shell --unset node

exec scopes tools and env to one command; shell exports them until the session ends and needs activation.

See: mise exec, mise shell

Configuration

mise.toml

[tools]
node = "24"

[env]
NODE_ENV = "development"

[tasks.hello]
run = "echo hello"
mise config ls      # files mise loaded, in order
mise ls --current

Commit mise.toml; put machine-local overrides in mise.local.toml and gitignore it.

See: Configuration

Config files

mise.toml                    # project config, committed
mise.local.toml              # local overrides, gitignored
~/.config/mise/config.toml   # global defaults (mise use -g)
/etc/mise/config.toml        # system defaults
.tool-versions               # asdf file, read when present

Parent directories cascade; the closest file wins per key, and [tools]/[env] merge additively.

See: mise.toml

Idiomatic version files

mise settings add idiomatic_version_file_enable_tools node
mise settings add idiomatic_version_file_enable_tools python
mise settings add idiomatic_version_file_enable_tools ruby

.nvmrc, .python-version, and .ruby-version are ignored until their tool is listed.

See: Idiomatic version files

Settings

mise settings ls --all           # every setting's value
mise settings set jobs 4         # global config
mise settings set --local jobs 2 # project override
mise settings unset --local jobs
# ~/.config/mise/config.toml
[settings]
idiomatic_version_file_enable_tools = ["node"]
trusted_config_paths = ["~/work/trusted"]

Settings control mise itself; project env vars belong in [env]. Settings with no --local write to the global config.

See: Settings

Environment variables

VariableEffect
MISE_NODE_VERSION=20override one tool's version
MISE_ENV_FILE=.envload a dotenv file (cwd + parents)
MISE_JOBS=4parallel install jobs
MISE_PARANOID=1require explicit trust
MISE_LOCKED=1require lockfile installs
MISE_LOG_LEVEL=debugtrace/debug/info/warn/error
MISE_CEILING_PATHS=~/srcstop config search upwards

MISE_NO_CONFIG=1, MISE_NO_ENV=1, and MISE_NO_HOOKS=1 skip config, env, and hooks for one invocation.

See: Environment variables

Trust

mise trust --show            # trust status of nearby configs
mise trust                   # trust the local config
mise trust --all             # dir, parents, subdirs
mise untrust mise.toml
mise trust --ignore

Config files can run code through tasks and hooks. Normal mode auto-trusts the active config on mise run, mise install, mise exec, and mise watch.

Simple tool-only files need no trust; paranoid mode requires explicit, content-bound trust for non-global files.

See: mise trust, paranoid mode

Environments

Set variables

[env]
NODE_ENV = "production"
RUST_TEST_THREADS = "1"
CACHE_DIR = false              # unset it
LOG_LEVEL = { default = "info" }
mise set NODE_ENV=development
mise env                        # print exported variables
eval "$(mise env -s zsh)"

[env] reaches activated shells, mise exec, and tasks. mise set writes to mise.toml.

See: Environments

Load .env files

[env]
_.file = ".env"                # a single file
[env]
_.file = [                     # or several
  ".env",
  { path = ".secrets.yaml", redact = true },
]

Dotenv, JSON, YAML, and TOML are supported, and paths resolve against the config root. MISE_ENV_FILE=.env autoloads from the current directory upwards.

See: Environments

PATH

[env]
_.path = "./node_modules/.bin"  # one entry
[env]
_.path = ["tools/bin", "{{config_root}}/bin"]  # or several
mise env --paths                # PATH entries mise manages

Relative entries resolve against the config root, so they keep working from subdirectories.

See: Environments

Secrets and validation

redactions = ["SECRET_*", "*_TOKEN"]

[env]
DATABASE_URL = { required = true }
API_KEY = { value = "sk-...", redact = true }

required fails mise env when unset; redact masks the value in task output. Secrets do not belong in committed config — mise.local.toml is still plaintext.

See: Secrets, Environments

Tasks

Define tasks

[tasks]
build = "npm run build"

[tasks.test]
description = "Run unit tests"
run = ["npm run lint", "npm test"]
depends = ["build"]
alias = "t"

Tasks run with the project's tools and env, so no activation is needed.

See: TOML tasks

Run tasks

mise run build              # also: mise build
mise run test -- --watch    # forward args after --
mise run build ::: test     # run several tasks
mise tasks ls
mise tasks info test

mise run with no task opens a picker (or runs default), and installs missing tools first.

See: Running tasks

Dependencies

[tasks.ci]
depends = ["build", "lint"]
wait_for = ["render"]
run = "npm test"

[tasks.deploy]
depends_post = ["notify"]

[tasks.build-rs]
run = "cargo build"
sources = ["src/**/*.rs", "Cargo.toml"]
outputs = ["target/debug/app"]

depends runs first and only once; depends_post runs after; sources/outputs skip a task whose outputs are newer.

See: Task config

File tasks

mise-tasks/build

#!/usr/bin/env bash
#MISE description="Build the CLI"
#MISE depends=["lint"]
#MISE sources=["src/**/*.rs"]
#MISE alias="b"
#USAGE flag "-p --profile <profile>" default="dev"
cargo build --profile "$usage_profile"

Scripts live in mise-tasks/, .mise/tasks/, or mise/tasks/, must be executable (chmod +x), and #USAGE defines flags as usage_* env vars.

See: File tasks

Watch

mise use -g watchexec@latest   # mise watch needs watchexec
mise watch build               # rerun on source changes
mise watch test --clear

Watches the task's sources; arguments after -- go to the task.

See: mise watch

Also see

0 Comments for this cheatsheet. Write yours!