mise - Development Environment Management
This skill activates when working with mise for managing tool versions, environment variables, and project tasks.
When to Use This Skill
Activate when:
-
Setting up development environments
-
Managing tool and runtime versions (Node.js, Python, Ruby, Go, etc.)
-
Configuring environment variables and secrets
-
Defining and running project tasks
-
Creating reproducible development setups
-
Working with monorepos or multiple projects
What is mise?
mise is a polyglot runtime manager and development environment tool that combines:
-
Tool version management - Install and manage multiple versions of dev tools
-
Environment configuration - Set environment variables per project
-
Task automation - Define and run project tasks
-
Cross-platform - Works on macOS, Linux, and Windows
Installation
macOS/Linux (using curl)
curl https://mise.run | sh
macOS (using Homebrew)
brew install mise
Windows
See https://mise.jdx.dev for Windows install instructions
Activate mise in your shell
echo 'eval "$(mise activate bash)"' >> ~/.bashrc # bash echo 'eval "$(mise activate zsh)"' >> ~/.zshrc # zsh echo 'mise activate fish | source' >> ~/.config/fish/config.fish # fish
Managing Tools
Tool Backends
mise uses different backends (package managers) to install tools. Understanding backends helps you install tools correctly.
Available Backends
-
asdf - Traditional asdf plugins (default for many tools)
-
ubi - Universal Binary Installer (GitHub/GitLab releases)
-
cargo - Rust packages (requires Rust installed)
-
npm - Node.js packages (requires Node installed)
-
go - Go packages (requires Go installed)
-
aqua - Package manager
-
pipx - Python packages (requires Python installed)
-
gem - Ruby packages (requires Ruby installed)
-
github/gitlab - Direct from repositories
-
http - Direct HTTP downloads
Verifying Tool Names
Always verify tool names using mise ls-remote before adding to configuration:
Check if tool exists in registry
mise ls-remote node
Check tool with specific backend
mise ls-remote cargo:ripgrep mise ls-remote ubi:sharkdp/fd
Search the registry
mise registry | grep <tool-name>
Installing Tools
List available tools in registry
mise registry
Install from default backend
mise install node@20.10.0 mise install python@3.12 mise install ruby@3.3
Install with specific backend
mise install cargo:ripgrep # From Rust crates mise install ubi:sharkdp/fd # From GitHub releases mise install npm:typescript # From npm
Install latest version
mise install node@latest
Install from .mise.toml or .tool-versions
mise install
Using Tools with mise use
The mise use command is the primary way to add tools to projects. It combines two operations:
-
Installs the tool (if not already installed)
-
Adds the tool to your configuration file
Key Difference: mise install only installs tools, while mise use installs AND configures them.
Basic Usage
Interactive selection
mise use
Add tool with fuzzy version (default)
mise use node@20 # Saves as "20" in mise.toml
Add tool with exact version
mise use --pin node@20.10.0 # Saves as "20.10.0"
Add latest version
mise use node@latest # Saves as "latest"
Add with specific backend
mise use cargo:ripgrep@latest mise use ubi:sharkdp/fd
Configuration File Selection
mise use writes to configuration files in this priority order:
-
--global flag: ~/.config/mise/config.toml
-
--path <file> flag: Specified file path
-
--env <env> flag: .mise.<env>.toml
-
Default: mise.toml in current directory
Global (all projects)
mise use --global node@20
Local (current project)
mise use node@20 # Creates/updates ./mise.toml
Environment-specific
mise use --env local node@20 # Creates .mise.local.toml
Specific file
mise use --path ~/.config/mise/custom.toml node@20
Important Flags
Pin exact version
mise use --pin node@20.10.0 # Saves "20.10.0"
Fuzzy version (default)
mise use --fuzzy node@20 # Saves "20"
Force reinstall
mise use --force node@20
Dry run (preview changes)
mise use --dry-run node@20
Remove tool from config
mise use --remove node
Version Pinning
Fuzzy (recommended) - auto-updates within major version
mise use node@20 # Uses latest 20.x.x
Exact - locks to specific version
mise use --pin node@20.10.0 # Always uses 20.10.0
Latest - always uses newest version
mise use node@latest # Always updates to latest
Best Practice: Use fuzzy versions for flexibility, mise.lock for reproducibility.
Setting Tool Versions
The mise use command automatically sets tool versions by updating configuration files.
.mise.toml Configuration
[tools] node = "20.10.0" python = "3.12" ruby = "3.3" go = "1.21"
Use latest version
terraform = "latest"
Backends - use quotes for namespaced tools
"cargo:ripgrep" = "latest" # Requires rust installed "ubi:sharkdp/fd" = "latest" # GitHub releases "npm:typescript" = "latest" # Requires node installed
Version from file
node = { version = "lts", resolve = "latest-lts" }
UBI Backend (Universal Binary Installer)
The ubi backend installs tools directly from GitHub/GitLab releases without requiring plugins. It's built into mise and works cross-platform including Windows.
Basic UBI Usage
Install from GitHub releases
mise use -g ubi:goreleaser/goreleaser mise use -g ubi:sharkdp/fd mise use -g ubi:BurntSushi/ripgrep
Specific version
mise use -g ubi:goreleaser/goreleaser@1.25.1
In .mise.toml
[tools] "ubi:goreleaser/goreleaser" = "latest" "ubi:sharkdp/fd" = "2.0.0"
UBI Advanced Options
Configure tool-specific options when binary names differ or filtering is needed:
[tools]
When executable name differs from repo name
"ubi:BurntSushi/ripgrep" = { version = "latest", exe = "rg" }
Filter releases with matching pattern
"ubi:some/tool" = { version = "latest", matching = "linux-gnu" }
Use regex for complex filtering
"ubi:some/tool" = { version = "latest", matching_regex = ".-linux-.\.tar\.gz$" }
Extract entire tarball
"ubi:some/tool" = { version = "latest", extract_all = true }
Rename extracted executable
"ubi:some/tool" = { version = "latest", rename_exe = "my-tool" }
UBI Supported Syntax
Three installation formats:
-
GitHub shorthand (latest): ubi:owner/repo
-
GitHub shorthand (version): ubi:owner/repo@1.2.3
-
Direct URL: ubi:https://github.com/owner/repo/releases/download/v1.2.3/...
Templates
The templates/ directory contains reusable configuration snippets for common mise patterns.
Multi-Architecture Tool Installation
When installing tools from GitHub releases that provide separate binaries for different platforms/architectures, use platform-specific asset patterns.
See templates/multi-arch.md for the pattern:
[tools."github:owner/repo"] version = "latest"
[tools."github:owner/repo".platforms] linux-x64 = { asset_pattern = "tool_linux_amd64.tar.gz" } macos-arm64 = { asset_pattern = "tool_darwin_arm64.tar.gz" }
Platform Keys
Common platform keys for mise:
-
linux-x64
-
Linux on x86_64/amd64
-
linux-arm64
-
Linux on ARM64/aarch64
-
macos-x64
-
macOS on Intel (x86_64)
-
macos-arm64
-
macOS on Apple Silicon (M1/M2/M3)
-
windows-x64
-
Windows on x86_64
Asset Pattern Wildcards
Use * as a wildcard in asset patterns to match version numbers or other variable parts of release asset names.
Example for a tool with releases like beads_1.0.0_darwin_arm64.tar.gz :
asset_pattern = "beads_*_darwin_arm64.tar.gz"
Cargo Backend
The cargo backend installs Rust packages from crates.io. Requires Rust to be installed first.
Cargo Prerequisites
Install Rust before using cargo backend:
Option 1: Install Rust via mise
mise use -g rust
Option 2: Install Rust directly
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Cargo Usage
Install from crates.io
mise use -g cargo:ripgrep mise use -g cargo:eza mise use -g cargo:bat
In .mise.toml - requires rust installed first
[tools] rust = "latest" # Install rust first "cargo:ripgrep" = "latest" # Then cargo tools "cargo:eza" = "latest" "cargo:bat" = "latest"
Cargo from Git Repositories
Specific tag
mise use cargo:https://github.com/username/demo@tag:v1.0.0
Branch
mise use cargo:https://github.com/username/demo@branch:main
Commit hash
mise use cargo:https://github.com/username/demo@rev:abc123
Cargo Settings
Configure cargo behavior globally:
[settings]
Use cargo-binstall for faster installs (default: true)
cargo.binstall = true
Use alternative cargo registry
cargo.registry_name = "my-registry"
Managing Installed Tools
List installed tools
mise list
List all versions of a tool
mise list node
Uninstall a version
mise uninstall node@18.0.0
Update all tools to latest
mise upgrade
Update specific tool
mise upgrade node
Tool Aliases
Create alias for a tool
mise alias node 20 20.10.0
Use alias
mise use node@20
Environment Variables
Setting Environment Variables
In .mise.toml
[env] DATABASE_URL = "postgresql://localhost/myapp" API_KEY = "development-key" NODE_ENV = "development"
Template values
APP_ROOT = "{{ config_root }}" DATA_DIR = "{{ config_root }}/data"
File-based env vars
[env] _.file = ".env" _.path = ["/custom/bin"]
Environment Templates
Use Go templates in environment variables:
[env] PROJECT_ROOT = "{{ config_root }}" LOG_FILE = "{{ config_root }}/logs/app.log" PATH = ["{{ config_root }}/bin", "$PATH"]
Secrets Management
Use with sops
mise set SECRET_KEY sops://path/to/secret
Use with age
mise set API_TOKEN age://path/to/secret
Use from command
mise set BUILD_ID "$(git rev-parse HEAD)"
Tasks
Defining Tasks
In .mise.toml
[tasks.build] description = "Build the project" run = "npm run build"
[tasks.test] description = "Run tests" run = "npm test"
[tasks.lint] description = "Run linter" run = "npm run lint" depends = ["build"]
[tasks.ci] description = "Run CI pipeline" depends = ["lint", "test"]
[tasks.dev] description = "Start development server" run = "npm run dev"
Running Tasks
Run a task
mise run build mise run test
Short form
mise build mise test
Run multiple tasks
mise run lint test
List available tasks
mise tasks
Run task with arguments
mise run script -- arg1 arg2
Task Dependencies
[tasks.deploy] depends = ["build", "test"] run = "npm run deploy"
Tasks run in order: build, test, then deploy
Task Options
[tasks.build] description = "Build the project" run = "npm run build" sources = ["src//*.ts"] # Only run if sources changed outputs = ["dist//*"] # Check outputs for changes dir = "frontend" # Run in specific directory env = { NODE_ENV = "production" }
[tasks.watch] run = "npm run watch" raw = true # Don't wrap in shell
Task Files
Create separate task files:
.mise/tasks/deploy
#!/bin/bash
mise description="Deploy to production"
mise depends=["build", "test"]
echo "Deploying..." npm run deploy
Make executable:
chmod +x .mise/tasks/deploy
Common Workflows
Node.js Project Setup
.mise.toml
[tools] node = "20"
[env] NODE_ENV = "development"
[tasks.install] run = "npm install"
[tasks.dev] run = "npm run dev" depends = ["install"]
[tasks.build] run = "npm run build" depends = ["install"]
[tasks.test] run = "npm test" depends = ["install"]
Setup and run
cd project mise install # Installs Node 20 mise dev # Runs dev server
Python Project Setup
.mise.toml
[tools] python = "3.12"
[env] PYTHONPATH = "{{ config_root }}/src"
[tasks.venv] run = "python -m venv .venv"
[tasks.install] run = "pip install -r requirements.txt" depends = ["venv"]
[tasks.test] run = "pytest" depends = ["install"]
[tasks.format] run = "black src tests"
Monorepo Setup
Root .mise.toml
[tools] node = "20" python = "3.12"
[env] WORKSPACE_ROOT = "{{ config_root }}"
[tasks.install-all] run = """ npm install cd services/api && npm install cd services/web && npm install """
[tasks.test-all] depends = ["install-all"] run = """ mise run test --dir services/api mise run test --dir services/web """
Multi-Tool Project
.mise.toml
[tools] node = "20" python = "3.12" ruby = "3.3" go = "1.21" terraform = "latest"
[env] PROJECT_ROOT = "{{ config_root }}" PATH = ["{{ config_root }}/bin", "$PATH"]
[tasks.setup] description = "Setup all dependencies" run = """ npm install pip install -r requirements.txt bundle install go mod download """
Lock Files
Generate lock files for reproducible environments:
Generate .mise.lock
mise lock
Use locked versions
mise install --locked
.mise.toml
[tools] node = "20"
[settings] lockfile = true # Auto-generate lock file
Shims
Use shims for tool binaries:
Enable shims
mise settings set experimental true mise reshim
Now tools are in PATH via shims
node --version # Uses mise-managed node python --version # Uses mise-managed python
Configuration Locations
mise reads configuration from multiple locations (in order):
-
.mise.toml
-
Project local config
-
.mise/config.toml
-
Project local config (alternative)
-
~/.config/mise/config.toml
-
Global config
-
Environment variables - MISE_*
IDE Integration
VS Code
Add to .vscode/settings.json :
{ "terminal.integrated.env.linux": { "PATH": "${env:HOME}/.local/share/mise/shims:${env:PATH}" }, "terminal.integrated.env.osx": { "PATH": "${env:HOME}/.local/share/mise/shims:${env:PATH}" } }
JetBrains IDEs
Use mise shims or configure tool paths:
Find tool path
mise which node mise which python
CI/CD Integration
GitHub Actions
name: CI
on: [push]
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- uses: jdx/mise-action@v2
- name: Run tests
run: mise run test
GitLab CI
test: image: ubuntu:latest before_script: - curl https://mise.run | sh - eval "$(mise activate bash)" - mise install script: - mise run test
Troubleshooting
Check mise status
Show configuration
mise config
Show environment
mise env
Show installed tools
mise list
Debug mode
mise --verbose install node
Clear cache
Clear tool cache
mise cache clear
Remove and reinstall
mise uninstall node@20 mise install node@20
Legacy .tool-versions
mise is compatible with asdf's .tool-versions :
.tool-versions
nodejs 20.10.0 python 3.12.0 ruby 3.3.0
Convert to mise:
mise auto-reads .tool-versions
Or convert to .mise.toml
mise config migrate
Best Practices
-
Use .mise.toml for projects: Better than .tool-versions (more features)
-
Pin versions in projects: Ensure consistency across team
-
Use tasks for common operations: Document and standardize workflows
-
Lock files in production: Use mise lock for reproducibility
-
Global tools for dev: Set global defaults, override per project
-
Environment per project: Keep secrets and config in .mise.toml
-
Commit .mise.toml: Share config with team
-
Don't commit .mise.lock: Let mise generate per environment
Key Principles
-
Reproducible environments: Lock versions for consistency
-
Project-specific config: Each project defines its own tools and env
-
Task automation: Centralize common development tasks
-
Cross-platform: Same config works on all platforms
-
Zero setup for team: Clone and mise install to get started