mise

A polyglot runtime version manager and task runner — one tool to replace nvm, pyenv, rbenv, and more.

mise (pronounced "meez", from the French mise en place) is a polyglot runtime version manager and task runner written in Rust. It is a drop-in replacement for asdf, nvm, pyenv, rbenv, nodenv, and similar tools — managing all your language runtimes from a single unified interface, with a configuration file you can commit to your project.

Features

  • Polyglot — manages Node.js, Python, Ruby, Go, Java, Rust, and hundreds more via plugins
  • Project-local versions — a .mise.toml (or .tool-versions) file pins exact versions per project; switching directories automatically activates the right runtime
  • Shims or PATH patching — works in both shim-based and shell-hook-based modes
  • Task runner — define project tasks in .mise.toml, similar to just or make, co-located with your environment config
  • Fast — written in Rust, significantly faster than the original asdf shell implementation
  • asdf-compatible — reads .tool-versions files and supports the entire asdf plugin ecosystem
  • Environment variables — set project-specific env vars in .mise.toml that activate and deactivate with your shell

Installation

cargo install mise

Or via the install script (works on all Linux distros, including Debian, Ubuntu, and Fedora):

curl https://mise.run | sh

Or via package managers:

# macOS
brew install mise

# Arch Linux
pacman -S mise

# Windows (winget)
winget install mise

Setup

Add the shell hook to your shell config:

# ~/.bashrc
eval "$(mise activate bash)"

# ~/.zshrc
eval "$(mise activate zsh)"

# ~/.config/fish/config.fish
mise activate fish | source

Usage

# Install a runtime
mise install node@22
mise install python@3.13
mise install go@1.23

# Set the global default version
mise use --global node@22

# Set a local (project-level) version
mise use node@22

# List all installed runtimes
mise list

# Show currently active versions
mise current

# Run a command with a specific version without changing config
mise exec node@18 -- node --version

Project configuration

.mise.toml lives at your project root and can be committed to version control:

[tools]
node    = "22"
python  = "3.13"
go      = "1.23"

[env]
DATABASE_URL = "postgres://localhost/myapp_dev"
NODE_ENV     = "development"

[tasks.dev]
run = "npm run dev"
description = "Start the development server"

[tasks.test]
run = "pytest"
description = "Run the test suite"

Then your teammates just run:

mise install   # installs all pinned versions
mise run dev   # runs the dev task

Why mise over asdf?

mise is a direct spiritual successor to asdf — it reads the same .tool-versions config format and supports the same plugin ecosystem. The key differences are that it's written in Rust (making it dramatically faster), it adds first-class task running, per-project environment variables, and a richer TOML config format. If you already use asdf, migration is essentially frictionless.