Install & Activate
Getting mise on your machine is a one-liner. Understanding the two ways it puts
tools on your PATH — and where it reads config from — is what separates “it works
on my laptop” from “it works everywhere.” This page covers both.
Install
Section titled “Install”curl https://mise.run | sh # → ~/.local/bin/miseThe simplest path. Pin a version or relocate the binary with env vars:
MISE_VERSION=v2026.6.4 MISE_INSTALL_PATH=/usr/local/bin/mise \ curl https://mise.run | shbrew install miseComplementary, not redundant — keep brew for system libs and casks; let mise pin your project toolchains.
pacman -S mise # Archapk add mise # Alpinednf install mise # Fedora (via the mise.en.dev RPM repo)scoop install mise # Windowswinget install jdx.mise # Windowssnap install mise # any snapd distroFor locked-down environments, install from the official
mise.en.dev host, which ships GPG-signed releases and
RPM repositories. Import the signing key and verify the download before running
it — the supply-chain-conscious option for servers and base images.
The installer drops a static binary and does nothing to your shell. That’s the next, crucial step.
Activate your shell
Section titled “Activate your shell”Activation is what makes cd-ing into a project swap your tools automatically. Add
the right line to your interactive rc file:
eval "$(mise activate bash)"eval "$(mise activate zsh)"mise activate fish | source(&mise activate pwsh) | Out-String | Invoke-ExpressionReload (exec $SHELL) and you’re live. The https://mise.run/bash (or /zsh,
/fish) endpoint even appends the activation line for you during install.
The one concept: PATH activation vs shims
Section titled “The one concept: PATH activation vs shims”mise can expose your tools two different ways, and almost every “why isn’t my tool found?” question comes down to which one you’re using.
PATH activation hooks your shell prompt. Before each prompt — and on every cd —
mise runs hook-env, which rewrites PATH (and [env] vars) to match the directory
you’re standing in.
sequenceDiagram participant U as You participant Sh as Shell participant M as mise hook-env participant P as PATH U->>Sh: cd ~/proj (has mise.toml: node = "22") Sh->>M: prompt hook fires -> mise hook-env M->>M: walk up, resolve config + tool versions M->>P: prepend ~/.local/share/mise/installs/node/22/bin P-->>Sh: node -> 22.x now first on PATH U->>Sh: node --version (=> v22.x) U->>Sh: cd ~ (leave project) Sh->>M: prompt hook fires -> mise hook-env M->>P: remove the project's bin entries P-->>Sh: PATH restored to global defaults
Shims are static wrapper scripts in ~/.local/share/mise/shims. You put that one
directory on PATH and forget it. Calling node runs the node shim, which asks
mise (at exec time) which version this directory wants, then execs it. No prompt hook,
no shell integration — which is exactly why they work where there is no shell.
eval "$(mise activate bash --shims)" # or just add the shims dir to PATHexport PATH="$HOME/.local/share/mise/shims:$PATH"| PATH activation | Shims | |
|---|---|---|
| How | prompt hook rewrites PATH per directory | static wrapper scripts on PATH |
Sets [env] vars | yes | no (env vars only via activation) |
| Needs an interactive shell | yes | no |
| Speed | fast; resolves once per prompt | tiny per-call exec overhead |
| New binary appears | picked up automatically | run mise reshim |
| Best for | your daily terminal | IDEs, CI, cron, Dockerfile, scripts |
A common gotcha: under PATH activation, which node reports the shim or installed
path your shell sees. To find the real resolved binary, use mise’s own resolver:
mise which node # → ~/.local/share/mise/installs/node/22.14.0/bin/nodemise where node # → the install dirmise reshim # regenerate shims after a tool adds a new binaryRun a tool without activating: mise exec
Section titled “Run a tool without activating: mise exec”Need a tool right now without touching config or your shell? mise exec (alias
mise x) resolves, installs if missing, and runs — in a one-off subshell.
mise exec node@22 -- node --version # ad-hoc, nothing written to configmise x python@3.13 -- python script.pymise x -- npm test # use the versions this dir already pinsThis is the right tool inside scripts, cron, systemd units, and CI steps where
you don’t want to depend on shell activation. (Pinning tools into a project with
mise use is page 2.)
Where mise reads config
Section titled “Where mise reads config”mise walks up from your current directory to the filesystem root, then layers in
your user and system config. Nearer files win, merged key by key — so a project
mise.toml overrides your global Node version without throwing away your global env.
flowchart TD
start["cwd: ~/work/api/svc"] --> walk{"walk up,<br/>collect every config"}
walk --> p1["~/work/api/svc/mise.toml"]
walk --> p2["~/work/api/mise.toml"]
walk --> p3["~/work/mise.toml"]
p1 --> user["user: ~/.config/mise/config.toml<br/>+ conf.d/*.toml"]
p2 --> user
p3 --> user
user --> sys["system: /etc/mise/config.toml"]
sys --> merge["merge all layers, key by key"]
merge --> win["nearer + project-local wins"]
win --> result["effective tools / env / tasks"]
Within a single directory, the precedence is (highest first):
| Order | File | Commit it? |
|---|---|---|
| 1 | mise.local.toml | no — gitignore |
| 2 | mise.<env>.local.toml | no — gitignore |
| 3 | mise.toml | yes |
| 4 | mise.<env>.toml | yes |
| 5 | mise/config.toml, .mise/config.toml | yes |
| 6 | .mise.toml (legacy dotted form) | yes |
| — | then user ~/.config/mise/config.toml, then system /etc/mise/ | — |
There’s also .miserc.toml — a new-in-2026 early-init settings file read before the
rest, for things like selecting the active environment.
.tool-versions vs mise.toml — pick mise.toml
Section titled “.tool-versions vs mise.toml — pick mise.toml”mise still reads asdf’s .tool-versions (lowest precedence) for backwards compat:
node 22.14.0python 3.13.2But it only carries tool versions — no [env], no [tasks], no [settings].
The equivalent mise.toml does all three, in one committed file:
[tools]node = "22" # fuzzy → latest 22.xpython = "3.13"
[env]DATABASE_URL = "postgres://localhost/dev"
[tasks.test]run = "npm test"You can now install mise, activate it (or drop in shims), run anything ad-hoc with
mise exec, and you know exactly which config file wins. Next: actually pinning tools —
versions, backends, and the lockfile — in Tools & Backends.