- mise replaces
nvm,pyenv,rbenv,rustup,go version manager, andSDKMAN— one tool for all runtimes and CLI tools mise install node@20 python@3.13 rust@stableinstalls specific versions.tool-versionsfile in a project directory auto-activates the right versions — no manualusecommandsmise use -g node@20sets a global version;mise use node@20in a project dir sets project version- Legacy version files support
.nvmrc,runtime-tools, and.ruby-versionfor backward compatibility - Works as a CLI tool manager too:
mise use -g docker-composeinstalls docker-compose globally
Quick reference tables
Installation
| Method | Command |
|---|---|
| macOS / Linux (curl) | `curl https://mise.run |
| Windows (Scoop) | scoop install mise |
| Homebrew | brew install mise |
| GitHub releases | Download binary and add to PATH |
| Upgrade | mise self-update |
| Verify | mise --version |
Core commands
| Command | What it does |
|---|---|
mise install node@20 | Download and install Node 20 |
mise use node@20 | Set Node 20 for current project (writes .tool-versions) |
mise use -g node@20 | Set Node 20 as global default |
mise use node@20 python@3.13 | Set multiple tools at once |
mise current | Show current active versions |
mise list | List all installed tools and versions |
mise list node | List available/installed Node versions |
mise ls | Short for mise list |
mise upgrade node | Upgrade Node to latest in current version |
mise upgrade --all | Upgrade all tools |
mise run node --version | Run a tool without activating it first |
mise shell node@20 | Temporarily activate Node 20 in current shell |
mise exec node@20 -- node -v | Run a command with a specific version |
Tool version notation
| Notation | Example | Meaning |
|---|---|---|
node@20 | mise use node@20 | Use Node 20.x latest |
node@20.3.1 | mise use node@20.3.1 | Exact version |
node@>=20 | mise use node@>=20 | Minimum version |
node@latest | mise use node@latest | Latest available |
node@lts | mise use node@lts | Latest LTS release |
node@stable | mise use node@stable | Alias for latest stable |
node@current | mise use node@current | Alias for latest release |
Project configuration
.tool-versions file
Place .tool-versions in your project root:
node 20.12.0
python 3.13.2
rust 1.80.1
go 1.22.5
docker-compose 1.29.2 When you cd into that directory, mise auto-activates those versions. Works with any shell.
mise.toml (advanced config)
For more control, use mise.toml in project root:
[tools]
node = "20"
python = ["3.12", "3.13"] # multiple versions
[tools.node]
version = "20"
patch = true # auto-update patch version
[env]
NODE_ENV = "development"
MY_CUSTOM_VAR = { value = "from-mise" } Legacy version file support
mise auto-reads these files (no conversion needed):
| File | Example |
|---|---|
.nvmrc | 20 |
.node-version | 20.12.0 |
.python-version | 3.13 |
runtime-tools | node-20 |
.ruby-version | 3.2.2 |
Gemfile | reads Ruby from Gemfile |
package.json | reads Node from engines field |
Shell activation
Automatic activation
Add to your ~/.zshrc (zsh), ~/.bashrc (bash), or ~/.config/fish/config.fish (fish):
# zsh / bash — add to ~/.zshrc or ~/.bashrc
eval "$(mise activate bash)"
# or
eval "$(mise activate zsh)"
# fish — add to ~/.config/fish/config.fish
# This is done automatically by the installer for fish With activation, cd into any project with a .tool-versions file and the right versions are active. No commands needed.
Manual activation
mise shell node@20 # Activate only in current shell session direnv integration
For per-directory environment variables:
# Add to ~/.zshrc
eval "$(direnv hook zsh)"
# In project root, create .envrc
eval "$(mise activate bash)" # Adds mise auto-activation via direnv
export DATABASE_URL="postgres://localhost/mydb" CLI tools management
mise handles CLI tools the same way it handles runtimes:
| Tool | Example |
|---|---|
| docker-compose | mise use -g docker-compose@1.29 |
| kubectl | mise use -g kubectl@1.30 |
| helm | mise use -g helm@3.15 |
| terraform | mise use -g terraform@1.9 |
| hadolint | mise use -g hadolint@2.12 |
| shellcheck | mise use -g shellcheck@0.10 |
| yamllint | mise use -g yamllint@1.35 |
| jq | mise use -g jq@1.7 |
| ruff | mise use -g ruff@0.4 |
Tools installed via mise are placed in ~/.local/bin/ (macOS/Linux) or %LOCALAPPDATA%\mise\bin\ (Windows).
Common workflows
Starting a new Node.js project
# Assuming mise is activated in your shell
cd ~/projects/myapp
mise use node@20 python@3.13 # Writes .tool-versions
node --version # 20.x.x — auto-activated
npm install
npm run dev Switching Python versions per project
# Project A — data science
cd ~/projects/data-science
mise use python@3.12 # Uses 3.12 via .tool-versions
python --version # 3.12.x
# Project B — web API
cd ~/projects/web-api
mise use python@3.13 # Uses 3.13 via .tool-versions
python --version # 3.13.x Running with a specific tool version (no activation)
mise exec node@20 -- node -v # Runs Node 20 without changing shell
mise exec python@3.11 -- python -c "print('hello')"
mise exec rust@stable -- cargo --version Upgrading tools
mise upgrade node # Upgrade to latest in 20.x
mise upgrade python # Upgrade to latest in 3.x
mise upgrade --all # Upgrade everything
mise upgrade node@22 # Pin to a new major version CI/CD
GitHub Actions
- name: Install mise
uses: mise-action/core@v3
with:
cache: true
args: node@20 python@3.13
- name: Run tests
run: |
node --version # 20.x
python --version # 3.13.x
npm ci
npm test Docker
FROM python:3.13-slim
RUN pip install mise
SHELL ["/usr/bin/env", "-c"]
RUN curl https://mise.run | sh
ENV PATH="/root/.local/bin:$PATH"
WORKDIR /app
COPY .tool-versions .
RUN mise use --internal-call python # Activate from .tool-versions
RUN mise exec python -- pip install -r requirements.txt Simpler approach — use mise as a dev tool, not in production Docker images:
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt GitLab CI
image: ubuntu:24.04
before_script:
- curl https://mise.run | sh
- eval "$HOME/.local/share/mise/bin/miseactivate"
- mise use node@20 python@3.13
test:
script:
- npm ci
- npm test Cross-platform notes
| Platform | Binary location | Config location |
|---|---|---|
| Linux | ~/.local/bin/ | ~/.config/mise/ |
| macOS | ~/.local/bin/ | ~/.config/mise/ |
| Windows | %LOCALAPPDATA%\mise\bin\ | %APPDATA%\mise\ |
On Linux/macOS, add ~/.local/bin to PATH:
export PATH="$HOME/.local/bin:$PATH" Troubleshooting
”command not found: mise"
# Check if mise is in PATH
which mise
# If not found, add to PATH
# For zsh/bash:
export PATH="$HOME/.local/bin:$PATH"
# Verify activation
mise --version "Node version not found"
mise list-remote node # Shows available Node versions
mise install node@20 # Install if missing
mise use node@20 # Activate "Wrong version after cd”
# Ensure mise is activated in your shell
eval "$(mise activate zsh)" # or bash
# Check if .tool-versions exists
cat .tool-versions
# Force refresh
mise reload Summary
- One tool replaces nvm + pyenv + rbenv + rustup + go + SDKMAN
.tool-versionsauto-activates the right versions per projectmise use -gfor global defaults;mise usefor project-levelmise execruns with a specific version without changing shell state- Works with CLI tools (kubectl, terraform, ruff) the same way
- GitHub Actions:
mise-action/core@v3handles everything in one step
FAQ
Does mise work with asdf plugins?
Yes. mise is a drop-in replacement for asdf. It uses asdf-format plugins, so any asdf plugin works with mise directly. Convert your asdf setup: asdf migrate exports to mise format.
How is mise different from Homebrew? Homebrew manages packages system-wide. mise manages multiple versions of the same tool and activates the right version per project context. They complement each other.
Can mise manage system Python or only managed Python? mise downloads its own Python builds (via python-build-standalone). It does not modify system Python by default. On macOS, this avoids SIP conflicts.
Does mise work in CI without caching?
Yes, but it’s slower. The GitHub Action mise-action/core handles caching automatically. For other CI systems, install mise and run mise use — it downloads tools on first run.
What is the difference between mise use and mise exec?
mise use activates a version in the current shell (writes .tool-versions by default). mise exec runs a command with a specific version without changing shell state — useful in scripts and CI.
What to read next
- uv Cheat Sheet — Python package management (works great alongside mise for Python version management)
- Git Cheat Sheet —
.tool-versionsbelongs in version control - GitHub Actions Cheat Sheet — run mise in CI pipelines
Related Articles
Deepen your understanding with these curated continuations.
Regex Cheat Sheet: Patterns, Groups & Real-World Examples
Master regular expressions with this guide to anchors, groups, lookaheads, and quantifiers. Includes real-world patterns for emails, URLs, and passwords.
Docker Cheat Sheet: Images, Containers, Compose & More
Complete Docker reference — pulling images, running containers, volumes, networks, exec, logs, Docker Compose commands, Dockerfile tips, and disk cleanup.
Ollama Cheat Sheet: Local LLMs, Models, API & Integration (2026)
Complete Ollama reference — pull and run local LLMs, API endpoints, Python/JS integration, multimodal models, model management, and GPU setup in 2026.