Help us improve
Share bugs, ideas, or general feedback.
From all-skills
Guides on using mise to manage dev tool versions, environment variables, and project tasks. Activates when configuring reproducible development environments.
npx claudepluginhub vinnie357/claude-skills --plugin sbxHow this skill is triggered — by the user, by Claude, or both
Slash command
/all-skills:miseThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill activates when working with mise for managing tool versions, environment variables, and project tasks.
Manages development tool versions with Mise: installs specific/latest versions, pins in mise.toml, sets project/global/aliases for Node, Python, Rust, Go, Terraform, Deno, and more.
Generate production-ready mise.toml setups for local development, CI/CD pipelines, and toolchain standardization.
Share bugs, ideas, or general feedback.
This skill activates when working with mise for managing tool versions, environment variables, and project tasks.
Activate when:
Current stable: v2026.3.15
mise is a polyglot runtime manager and development environment tool that combines:
# 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
mise uses different backends (package managers) to install tools. Understanding backends helps you install tools correctly.
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 github:sharkdp/fd
# Search the registry
mise registry | grep <tool-name>
mise ls-remote <backend>:<target> returns all available versions for any backend. Run this BEFORE pinning a version in mise.toml to confirm the backend can actually see the tool.
# github backend — lists release tags from GitHub
$ mise ls-remote github:sharkdp/fd | head -5
7.0.0
7.1.0
7.2.0
7.3.0
7.4.0
# github backend — another tool
$ mise ls-remote github:goreleaser/goreleaser | head -5
2.8.1
2.8.2
2.9.0
2.10.0
2.10.1
# github backend — the GitHub CLI itself
$ mise ls-remote github:cli/cli | head -5
2.74.0
2.74.1
2.74.2
2.75.0
2.75.1
# cargo backend — lists versions from crates.io
$ mise ls-remote cargo:ripgrep | head -5
0.1.0
0.1.1
0.1.2
0.1.3
0.1.4
# go backend — requires Go installed (mise use go@latest)
$ mise ls-remote go:mvdan.cc/gofumpt | head -5
0.1.0
0.1.1
0.2.0
0.2.1
0.3.0
# npm backend — lists versions from the npm registry
$ mise ls-remote npm:typescript | head -5
0.8.0
0.8.1-1
0.8.1
0.8.2
0.8.3
Failure mode — the tool lives in a different repo than you expect. Sometimes the CLI binary is released from a different repository than the documentation or project homepage. Example:
# Returns no versions — wrong repo
$ mise ls-remote github:juxt/allium | head -5
(no output)
# Returns versions — correct repo for the CLI releases
$ mise ls-remote github:juxt/allium-tools | head -5
0.1.0
0.1.1
0.1.2
0.1.3
0.1.5
If ls-remote returns nothing, check whether the project publishes releases to a separate repository (e.g., a -tools, -cli, or -releases repo).
Don't pin a version you haven't verified ls-remote can see.
# 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 github: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
mise useThe mise use command is the primary way to add tools to projects. It combines two operations:
Key Difference: mise install only installs tools, while mise use installs AND configures them.
# 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 github:sharkdp/fd
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>.tomlmise.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
# 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
# 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.
The mise use command automatically sets tool versions by updating configuration files.
[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
"github:sharkdp/fd" = "latest" # GitHub releases
"npm:typescript" = "latest" # Requires node installed
"github:nushell/nushell" = "latest" # Nushell (structured shell)
# Version from file
node = { version = "lts", resolve = "latest-lts" }
The github backend installs tools directly from GitHub release assets without requiring plugins. It is built into mise, works cross-platform including Windows, and adds provenance verification and download progress over the older ubi backend.
Note: The ubi: prefix is deprecated (per upstream mise docs); migrate any existing ubi:owner/repo entries to github:owner/repo.
# Install from GitHub releases
mise use -g github:goreleaser/goreleaser
mise use -g github:sharkdp/fd
mise use -g github:BurntSushi/ripgrep
# Specific version
mise use -g github:goreleaser/goreleaser@2.10.0
# In .mise.toml
[tools]
"github:goreleaser/goreleaser" = "latest"
"github:sharkdp/fd" = "10.0.0"
Configure tool-specific options when binary names differ or asset filtering is needed:
[tools]
# When executable name differs from repo name
"github:BurntSushi/ripgrep" = { version = "latest", exe = "rg" }
# Filter release assets with a glob pattern
"github:some/tool" = { version = "latest", asset_pattern = "*-linux-gnu*" }
# Asset pattern with exact architecture
"github:some/tool" = { version = "latest", asset_pattern = "*_darwin_arm64.tar.gz" }
# Extract entire tarball
"github:some/tool" = { version = "latest", extract_all = true }
# Rename extracted executable
"github:some/tool" = { version = "latest", rename_exe = "my-tool" }
Two installation formats:
github:owner/repogithub:owner/repo@1.2.3The templates/ directory contains reusable configuration snippets for common mise patterns.
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" }
Common platform keys for mise:
linux-x64 - Linux on x86_64/amd64linux-arm64 - Linux on ARM64/aarch64macos-x64 - macOS on Intel (x86_64)macos-arm64 - macOS on Apple Silicon (M1/M2/M3)windows-x64 - Windows on x86_64Use * 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"
The cargo backend installs Rust packages from crates.io. Requires Rust to be installed first.
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
# 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"
# 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
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"
# 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
# Create alias for a tool
mise alias node 20 20.10.0
# Use alias
mise use node@20
[env]
DATABASE_URL = "postgresql://localhost/myapp"
API_KEY = "development-key"
NODE_ENV = "development"
# Template values
APP_ROOT = "{{ config_root }}"
DATA_DIR = "{{ config_root }}/data"
[env]
_.file = ".env"
_.path = ["/custom/bin"]
Use Go templates in environment variables:
[env]
PROJECT_ROOT = "{{ config_root }}"
LOG_FILE = "{{ config_root }}/logs/app.log"
PATH = ["{{ config_root }}/bin", "$PATH"]
# 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.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"
# 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
[tasks.deploy]
depends = ["build", "test"]
run = "npm run deploy"
# Tasks run in order: build, test, then deploy
[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
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
mise sandboxing is a lightweight process-isolation feature for mise exec and mise run that restricts filesystem, network, and environment-variable access using OS-level primitives — not a container, not a VM. Enable the feature flag before using any sandbox options:
mise settings experimental=true
| Platform | Filesystem | Network | Per-host net filter |
|---|---|---|---|
| Linux (kernel 5.13+) | Landlock | seccomp-bpf | No (all-or-nothing in v1) |
| macOS | Seatbelt | Seatbelt | Yes |
| Windows | unsupported | unsupported | unsupported |
Deny flags (apply to mise exec / mise run):
--deny-all — deny filesystem, network, and env by default--deny-read — deny all filesystem reads--deny-write — deny all filesystem writes--deny-net — deny all network access--deny-env — deny all environment variablesAllow flags (grant specific access back):
--allow-read=<path> — grant read access to a path--allow-write=<path> — grant write access to a path--allow-net=<host> — grant access to a specific host (macOS only for per-host filtering)--allow-env=<var> — grant access to an env var; supports globs (e.g. MYAPP_*)mise x --deny-all --allow-read=. --allow-write=./dist --allow-net=registry.npmjs.org -- npm install
Define sandbox policy inline in mise.toml:
[tasks.build]
run = "npm run build"
deny_net = true
allow_write = ["./dist"]
Task-level keys map 1:1 to CLI flags. CLI flags override task config when both are present.
mise settings experimental=true is required; without it, deny/allow flags are silently no-ops.templates/sandboxing.md — runnable examples for task-level and ad-hoc sandbox invocations.# .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
# .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"
# 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
"""
# .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
"""
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
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
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 configMISE_*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}"
}
}
Use mise shims or configure tool paths:
# Find tool path
mise which node
mise which python
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
test:
image: ubuntu:latest
before_script:
- curl https://mise.run | sh
- eval "$(mise activate bash)"
- mise install
script:
- mise run test
# Show configuration
mise config
# Show environment
mise env
# Show installed tools
mise list
# Debug mode
mise --verbose install node
# Clear tool cache
mise cache clear
# Remove and reinstall
mise uninstall node@20
mise install node@20
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
mise lock for reproducibilitymise install to get startedreferences/transitive-runtime-deps.md — mise exec does NOT auto-install transitive deps (Elixir-needs-Erlang failure mode); prefer portable secret-generation commands (openssl, python3, /dev/urandom)