The Complete Guide to Mise: Replace asdf/nvm/pyenv — Manage Dev Environments 10x Faster

TL;DR — Mise is a multi-language version manager written in Rust, over 20x faster than asdf. One tool handles version switching for Node.js, Python, Ruby, Go, Java, and 50+ other dev tools. It also includes environment variable management and a task runner.

Why Do You Need Mise?

If you're a full-stack developer, your daily life probably looks like this:

  • Project A needs Node.js 18, Project B needs Node.js 20
  • Backend runs on Python 3.11, but that legacy project is stuck on Python 3.9
  • Every now and then you're writing Ruby, Go, or Rust

To manage all these versions, you've probably installed:

Tool Manages
nvm Node.js versions
pyenv Python versions
rbenv Ruby versions
gvm Go versions
asdf Universal version manager

The problem: each tool has its own config format, its own shell hooks, its own .tool-versions or .nvmrc files. The maintenance burden is huge. And most of these tools are written in Bash — painfully slow to start.

Mise (pronounced /miːz/, "meez") is here to end all of that.

What Is Mise?

Mise (French for "to put") is a dev tool manager written in Rust that combines the following into one:

  1. Multi-language version management — replaces asdf/nvm/pyenv/rbenv/gvm and more
  2. Environment variable management — replaces direnv
  3. Task runner — replaces Makefile/just/task

Key Advantages

Feature Mise asdf nvm + pyenv
Language Rust Bash Bash
Install speed ⚡ Blazing fast (parallel downloads) 🐢 Slow (cloning one by one) 🐢 Slow
Shell startup delay ~0ms (no shims needed) ~200-500ms ~100-300ms
.nvmrc support
.python-version support
.tool-versions (asdf) support
Environment variable management ✅ Built-in
Task runner ✅ Built-in
Auto-completion ✅ Auto-generated ❌ Manual setup

GitHub stats: 30,000+ Stars, 1,200+ Forks, MIT license, actively maintained.

Installing Mise

Mise is easy to install and supports all major platforms.

# One-liner install
curl https://mise.run | sh

# Or via Homebrew (macOS)
brew install mise

# Or via Cargo (Rust ecosystem)
cargo install mise

Activating Shell Integration

After installation, add the activation command to your shell config:

# Bash — add to ~/.bashrc
echo 'eval "$(mise activate bash)"' >> ~/.bashrc

# Zsh — add to ~/.zshrc
echo 'eval "$(mise activate zsh)"' >> ~/.zshrc

# Fish — add to ~/.config/fish/config.fish
echo 'mise activate fish | source' >> ~/.config/fish/config.fish

Reload your shell:

source ~/.bashrc  # or source ~/.zshrc

Verifying the Installation

mise --version
# Output similar to: mise 2026.x.x

mise doctor
# Checks installation status and displays all diagnostics

Quick Start: Manage Your First Tool in 5 Minutes

Installing Node.js

# Install the latest LTS version
mise use -g node@lts

# Install a specific version
mise use -g node@20

# List installed versions
mise ls node

-g means global install (writes to ~/.config/mise/config.toml). Without -g, it writes to .mise.toml in the current directory for project-level version pinning.

Installing Python

# Install Python 3.12
mise use -g python@3.12

# Verify
python --version
# Python 3.12.x

Installing Multiple Tools at Once

# Install multiple tools in one command
mise use -g node@20 python@3.12 go@1.22 ruby@3.3 rust@latest

# List all currently active tools
mise ls

Project-Level Version Pinning

Navigate to your project directory and create .mise.toml:

cd ~/projects/my-app

# Set Node.js 20 and Python 3.11 for this project
mise use node@20 python@3.11

This generates a .mise.toml file:

[tools]
node = "20"
python = "3.11"

Commit this file to Git. When teammates clone the repo, they just run mise install and all required versions are installed automatically.

Compatibility with Existing Config Files

Mise automatically recognizes these files — no extra configuration needed:

File Corresponding Tool
.nvmrc Node.js
.node-version Node.js
.python-version Python
.ruby-version Ruby
.go-version Go
.tool-versions asdf universal format
.mise.toml / mise.toml Mise native format

This means you can seamlessly replace asdf/nvm/pyenv without changing any existing project configuration.

Advanced Features

1. Environment Variable Management (direnv Replacement)

Mise has built-in environment variable management. It auto-loads/unloads env vars based on your current directory:

# .mise.toml
[env]
DATABASE_URL = "postgres://localhost:5432/myapp"
REDIS_URL = "redis://localhost:6379"
NODE_ENV = "development"
API_KEY = {value = "sk-test-xxx", redact = true}  # Auto-redacted in logs

Supports .env files:

[env]
_.file = ".env"           # Load from .env file
_.path = ["./bin", "./scripts"]  # Auto-add to PATH

Difference from direnv: Mise manages env vars and tool versions in the same file — no need for two separate configs.

2. Task Runner (Makefile Replacement)

Mise includes a powerful built-in task runner:

# .mise.toml
[tasks.build]
description = "Build the project"
run = "npm run build"

[tasks.test]
description = "Run tests"
run = ["npm test", "npm run lint"]

[tasks.dev]
description = "Start dev server"
run = "npm run dev"
depends = ["build"]  # Dependency: build runs first

[tasks."db:migrate"]
description = "Run database migrations"
run = "python manage.py migrate"

Usage:

# Run tasks
mise run build
mise run test
mise run dev

# List all available tasks
mise tasks

# Run with arguments
mise run build -- --watch

3. Aliases and Shortcuts

# .mise.toml
[alias.node]
lts = "20"
latest = "22"

[alias.python]
myproj = "3.11.6"  # Pinned project version

4. Multi-Version Parallel and Auto-Switching

Mise's core magic is automatic version switching. When you cd into a different directory, Mise reads that directory's config and switches tool versions automatically:

# Project A needs Node 18
cd ~/projects/project-a
node --version  # v18.x.x (auto-switched)

# Project B needs Node 20
cd ~/projects/project-b
node --version  # v20.x.x (auto-switched)

All of this happens with zero delay — because Mise is written in Rust, there's no Bash script running on every cd like with nvm.

5. Backend System

Mise supports multiple install backends, giving you flexibility in where tools come from:

# Use official pre-built binaries (default, fastest)
[tools]
node = "20"

# Use asdf plugin ecosystem
[tools]
node = "asdf:mise-plugins/mise-node"

# Use ubi (universal binary installer)
[tools]
jq = "ubi:jqlang/jq"

# Use go install
[tools]
golangci-lint = "go:golang.org/x/tools/gopls@latest"

# Use npm global install
[tools]
typescript = "npm:typescript"

# Use pip install
[tools]
black = "pip:black"

# Use cargo install
[tools]
ripgrep = "cargo:ripgrep"

This means Mise doesn't just manage language runtimes — it manages any dev tool: linters, formatters, CLI utilities, and more.

Real-World Example: Setting Up a Full-Stack Dev Environment with Mise

Let's build a typical full-stack project (Next.js frontend + FastAPI backend) dev environment from scratch using Mise.

Step 1: Create Project Structure

mkdir ~/projects/fullstack-app && cd ~/projects/fullstack-app
mkdir frontend backend

Step 2: Root Directory Config

Create mise.toml in the project root:

# mise.toml
[tools]
node = "20"        # Frontend needs this
python = "3.12"    # Backend needs this

[env]
_.file = ".env"    # Global environment variables

[tasks.setup]
description = "Initialize the entire project"
run = [
    "cd frontend && npm install",
    "cd backend && pip install -r requirements.txt"
]

[tasks.dev]
description = "Start all services"
run = [
    "cd frontend && npm run dev &",
    "cd backend && uvicorn main:app --reload"
]

Step 3: One-Command Initialization

# Install all tools
cd ~/projects/fullstack-app
mise install

# Run the setup task
mise run setup

# Start the dev environment
mise run dev

Your entire team just needs git clone + mise install + mise run dev to get the dev environment running. No more "but it works on my machine" problems.

Step 4: CI/CD Integration

Use Mise directly in GitHub Actions:

# .github/workflows/ci.yml
name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install mise
        uses: jdx/mise-action@v2

      - name: Install tools
        run: mise install

      - name: Frontend tests
        run: cd frontend && npm test

      - name: Backend tests
        run: cd backend && pytest

mise-action reads mise.toml automatically and installs all required tools. No need to manually configure actions/setup-node, actions/setup-python, etc.

Migrating from asdf to Mise

If you're already an asdf user, migration is straightforward:

# Mise is fully compatible with .tool-versions files
# You don't even need to do anything — Mise reads them automatically

# But if you want to convert .tool-versions to mise.toml:
mise migrate asdf

# Remove asdf after migration (optional)
# Bash
sed -i '/asdf.sh/d' ~/.bashrc
# Zsh
sed -i '/asdf.sh/d' ~/.zshrc

Key advantages: - mise install is 20x+ faster than asdf install (parallel downloads + pre-built binaries) - No shim layer — zero shell startup delay - Better error messages and auto-completion - Built-in task runner and environment variable management

Mise vs. Other Tools — Summary

Scenario Traditional Approach Mise Approach
Managing 3 language versions Install 3 tools 1 tool
Team environment consistency Everyone installs manually mise install — one command
Shell startup speed ~300ms+ ~0ms
Environment variables direnv / manual export Built-in
Project tasks Makefile / package.json scripts Built-in tasks
CI configuration One action per language One mise-action

Conclusion

Mise is one of the most practical developer tools I've come across in recent years. It leverages Rust's raw performance to solve the pain points of version management, replacing the scattered collection of nvm, pyenv, rbenv, direnv, and Makefile with a single unified tool.

Why it's worth using:

  • Fast — Written in Rust, 20x faster than asdf
  • 🔧 Unified — One tool to manage all your dev tool versions
  • 🔄 Compatible — Fully compatible with .nvmrc, .tool-versions, and other existing configs
  • 🚀 Ecosystem — Supports 50+ languages and tools
  • 📦 Built-in task runner — No extra Makefile needed
  • 🌍 Environment variable management — No extra direnv needed
  • 🤝 Team collaboration — Commit mise.toml to Git; new members get set up with one command

Useful links:

If you're still running the nvm + pyenv + asdf combo, give Mise a serious try. You'll wonder how you ever managed without it.