TL;DR:
- mise (pronounced “meez”) is a single tool that replaces nvm, pyenv, rbenv, asdf, and direnv — managing Node, Python, Ruby, Go, Rust, and 500+ other tools from one CLI
- It’s written in Rust, significantly faster than asdf, and drops the shell shim approach in favour of PATH manipulation that works better in subprocesses and CI
.mise.tomlfiles let you pin tool versions per project and automatically activate the right environment when youcdinto a directory
If you’ve been meaning to replace the sprawl of nvm, pyenv, rbenv, and whatever else you’ve accumulated over the years, mise is worth an afternoon of your time. It’s one of those rare tools that actually does what it promises: one installation, one config format, and everything works consistently regardless of which language you’re in.
What mise Does
mise manages runtimes and development tools — Node.js, Python, Ruby, Go, Java, Rust, and several hundred more via plugins — from a single CLI. You install a tool version, you can set it globally or per-project, and it activates automatically based on your current directory.
That last part is the key. Drop a .mise.toml in your project root and every developer on the team who has mise installed will automatically use the right version of every tool when they cd into the project:
# .mise.toml
[tools]
node = "22.5.0"
python = "3.12.4"
go = "1.23.0"
terraform = "1.9.0"
awscli = "2.17.0"
No more “what version of Node are you on” debugging sessions.
Why It’s Better Than asdf
mise started as a rewrite of asdf in Rust (it was originally called rtx). The two share a similar philosophy, but mise diverges in some important ways.
Performance: mise is substantially faster than asdf. Activating an environment with asdf adds measurable shell startup time; mise is fast enough that you don’t notice it.
No shims (by default): asdf creates shim executables in your PATH for every managed tool. This works well in interactive shells but causes subtle failures in subprocesses, CI environments, and scripts that bypass the normal PATH resolution. mise uses PATH manipulation instead: it prepends the correct tool directory to PATH when you enter a directory. This means python in a subprocess finds the right version because PATH is inherited, not because there’s a shim intercepting the call.
Better .env and environment variable management: mise also replaces direnv for most purposes. You can set environment variables in your .mise.toml that activate automatically:
[env]
DATABASE_URL = "postgresql://localhost/myapp_dev"
NODE_ENV = "development"
AWS_PROFILE = "dev-account"
Plugin ecosystem compatibility: mise is compatible with asdf plugins, so tools that aren’t in the built-in registry (which covers the major runtimes) can still be installed via asdf-compatible plugins.
Getting Started
Install mise:
# macOS/Linux
curl https://mise.run | sh
# Or via Homebrew
brew install mise
# Or via cargo
cargo install mise
Add the activation to your shell profile (.bashrc, .zshrc, or fish.config):
# bash
eval "$(mise activate bash)"
# zsh
eval "$(mise activate zsh)"
# fish
mise activate fish | source
Install your first tools:
# Install and use globally
mise use --global node@22
mise use --global python@3.12
# Install for current project (writes to .mise.toml)
mise use node@22.5.0
mise use python@3.12.4
List what’s installed:
mise ls
Check which version is active:
mise current
Per-Project Configuration
The .mise.toml format is clean and explicit. Commit it to your repository:
[tools]
node = "22.5.0"
python = "3.12.4"
pnpm = "9.6.0"
[env]
# Set for this project only
PYTHONPATH = "src"
NODE_OPTIONS = "--max-old-space-size=4096"
When a teammate pulls this and cds into the project directory, mise prompts them to install the missing tools if they haven’t already:
mise: Some tools are not installed: node@22.5.0, python@3.12.4
Run `mise install` to install them
Running mise install (or mise i) brings everything in sync. This is the part that genuinely removes friction from team development — no README section about “install nvm, then run nvm install, then install pyenv, then…”
CI Integration
mise works well in CI. The recommended pattern for GitHub Actions:
- name: Install mise
uses: jdx/mise-action@v2
- name: Install tools
run: mise install
The mise-action reads your .mise.toml and installs the correct versions. Tools are cached between runs using GitHub Actions cache.
For other CI systems, installing mise and running mise install works without the action:
curl https://mise.run | sh
export PATH="$HOME/.local/bin:$PATH"
mise install
Managing Tasks
mise also includes a task runner that overlaps with Makefile and Taskfile workflows:
[tasks.test]
run = "pytest tests/"
description = "Run the test suite"
[tasks.lint]
run = "ruff check src/"
description = "Run linter"
[tasks.dev]
run = "uvicorn app.main:app --reload"
description = "Start development server"
Then run tasks via:
mise run test
mise run lint
mise run dev
This isn’t a full Makefile replacement for complex build graphs, but for common development tasks it reduces the number of separate tools you need.
Migrating from nvm and pyenv
Migration is mostly additive — you don’t need to uninstall nvm or pyenv immediately. mise will take precedence based on directory .mise.toml files; your global nvm and pyenv versions remain as fallbacks.
To migrate existing nvm Node versions:
# Install the version you currently use globally
mise use --global node@$(node --version | sed 's/v//')
To migrate pyenv Python versions:
# List what pyenv has
pyenv versions
# Install in mise
mise use --global python@3.12.4
Once mise is managing your versions reliably, you can remove nvm and pyenv from your shell profile to clean up startup time — but there’s no urgency.
The main friction point in migration is if you have shell scripts or CI configurations that explicitly source nvm or pyenv initialisation. Those need updating, but it’s usually a search-and-replace operation.
mise has become the de facto choice for developers who want one thing to manage instead of five. If you’ve been putting off cleaning up your version management setup, it’s a good time.