You've probably got a graveyard of version managers. nvm for Node, pyenv for Python, rustup for Rust, tfenv for Terraform — each one with its own install script, its own shims, its own idea of "just work." mise (formerly called rtx) wants to be the single tool that buries them all. It is a lot easier to use than it sounds.
What mise actually is
mise is a single Rust binary, written by Jeff Dickey, that does the job of three tools at once:
- A version manager for runtimes and CLIs — Node, Python, Go, the works — the way
asdf,nvm, orpyenvdo, but for any tool at all. - A per-directory env-var loader, like
direnv. Walk into a project folder and the rightPATH,DATABASE_URL, whatever, is already set. - A task runner, like a lightweight
make. Define build and test commands in the same file that pins your versions.
Everything lives in one config file, mise.toml, that you commit alongside your code.
(It was called rtx until January 2024, when it was renamed to avoid confusion with Nvidia's RTX graphics line. The name stuck.)
Installing mise in one line
curl https://mise.run | sh
That puts the binary at ~/.local/bin/mise. Then hook it into your shell so it can set versions and env vars when you cd around:
echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc
That line is the whole magic trick: mise tracks which directory you're in and applies that folder's config automatically.
Pin a tool version per project
Node is the easiest example. From your project root:
mise use node@24
That installs Node 24 if you don't have it, writes node = "24" into mise.toml, and puts the right node in your PATH — only inside that directory. Step into the folder, and node -v reports v24.x. Step out, and you're back to your default.
The version syntax is forgiving. Exact ("3.14.8"), prefix ("24" matches any 24.x, "3.14" matches 3.14.x but not 3.20), or "latest". Want two Pythons side by side? mise installs both and keeps the unversioned python on the first one:
[tools]
python = ["3.14", "3.13"]
Run mise exec -- python3.13 --version and 3.13 is there when you need it.
Env vars and tasks in the same file
Pin a database URL for a folder without touching your shell rc:
[env]
DATABASE_URL = "postgres://localhost/mydb"
And define commands as short tasks:
[tasks.test]
run = "pytest"