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.
- mise documentation (mise.jdx.dev)
- GitHub repository (github.com)
- Tool registry (mise.jdx.dev)
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
| Command | Goal |
|---|---|
mise use node@24 | Add a tool to the project |
mise use -g node@24 | Set a personal default |
mise install | Install config tools |
mise exec -- node -v | Run one command with tools |
Inspect
| Command | Goal |
|---|---|
mise ls --current | Show active versions |
mise config ls | Show loaded config files |
mise tasks ls | List project tasks |
mise doctor | Check 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.
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
| Prefix | Source |
|---|---|
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.
Examples
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.
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
| Variable | Effect |
|---|---|
MISE_NODE_VERSION=20 | override one tool's version |
MISE_ENV_FILE=.env | load a dotenv file (cwd + parents) |
MISE_JOBS=4 | parallel install jobs |
MISE_PARANOID=1 | require explicit trust |
MISE_LOCKED=1 | require lockfile installs |
MISE_LOG_LEVEL=debug | trace/debug/info/warn/error |
MISE_CEILING_PATHS=~/src | stop config search upwards |
MISE_NO_CONFIG=1, MISE_NO_ENV=1, and MISE_NO_HOOKS=1 skip config, env,
and hooks for one invocation.
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
0 Comments for this cheatsheet. Write yours!