mise installs and switches dev tool versions per project, manages environment variables, and runs tasks. This reference covers the CLI, mise.toml, and daily workflows.

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 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 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 set auto_update true keeps mise current automatically; 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"
erlang = "ref:master"   # build a git ref
go = "prefix:1.19"      # latest 1.19.x
shfmt = "path:./shfmt"  # custom install dir

A request is a range; an exact version is a pin. prefix: helps when 1.19 matches only 1.19. Aliases like lts are not universal.

See: Scopes

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)
pipx:Python apps (pipx:ruff)
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 pipx:ruff                    # Python app
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           # effective values + sources
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             # trust this tree + parents
mise untrust mise.toml
mise trust --ignore

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

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

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: 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; extra arguments go to watchexec.

See: mise watch

Also see

0 Comments for this cheatsheet. Write yours!