docs/dev-tools/index.md
Install and switch between dev tools like node, python, cmake, terraform, and hundreds more, all from the same project config.
mise is a tool that manages installations of programming language runtimes and other tools for local development. For example, it can be used to manage multiple versions of Node.js, Python, Ruby, Go, etc. on the same machine.
Once activated, mise can automatically switch between different versions of tools based on the directory you're in. This means that if you have a project that requires Node.js 18 and another that requires Node.js 22, mise will automatically switch between them as you move between the two projects. See tools available for mise with in the registry.
To know which tool version to use, mise will typically look for a mise.toml file in the current directory and its parents. To get an idea of how tools are specified, here is an example of a mise.toml file:
[tools]
node = '24'
python = '3'
ruby = 'latest'
It's also compatible
with asdf .tool-versions files as well as idiomatic version files like .node-version and
.ruby-version. See configuration for more details.
When specifying tool versions, you can also refer to environment variables defined in your config hierarchy,
including values produced by env directives like _.source, _.file, or env modules. These are resolved
before tool version templates are rendered.
::: info
mise is compatible with asdf .tool-versions files and can still use asdf
plugins when needed. If you're migrating from asdf, see the
comparison guide.
:::
mise manages development tools through a sophisticated but user-friendly system that automatically handles tool installation, version management, and environment setup.
When you enter a directory or run a command, mise follows this process:
mise.toml, .tool-versions, etc.) and merges them hierarchicallynode@latest or python@3) to specific versions using registries and version listsPATH and environment variables to use the resolved tool versionsmise provides several ways to integrate with your development environment:
Automatic Activation: With mise activate, mise hooks into your shell prompt and automatically updates your environment when you change directories:
eval "$(mise activate zsh)" # In your ~/.zshrc
cd my-project # Automatically loads mise.toml tools
On-Demand Execution: Use mise exec to run commands with mise's environment without permanent activation:
mise exec -- node my-script.js # Runs with tools from mise.toml
Shims: mise can create lightweight wrapper scripts that automatically use the correct tool versions:
mise activate --shims # Creates shims instead of modifying PATH
mise modifies your PATH environment variable to prioritize the correct tool versions:
# Before mise
echo $PATH
/usr/local/bin:/usr/bin:/bin
# After mise activation in a project with node@20
echo $PATH
/home/user/.local/share/mise/installs/node/20.11.0/bin:/usr/local/bin:/usr/bin:/bin
This ensures that when you run node, you get the version specified in your project configuration, not a system-wide installation.
mise supports nested configuration that cascades from broad to specific settings:
~/.config/mise/config.toml # Global defaults
~/work/mise.toml # Work-specific tools
~/work/project/mise.toml # Project-specific overrides
~/work/project/.tool-versions # Legacy asdf compatibility
Each level can override or extend the previous ones, giving you fine-grained control over tool versions across different contexts.
Tool options allow you to customize how tools are installed and configured. They support nested configurations for better organization, particularly useful for platform-specific settings.
The cleanest way to specify nested options is using TOML tables:
[tools."http:my-tool"]
version = "1.0.0"
[tools."http:my-tool".platforms]
macos-x64 = {
url = "https://example.com/my-tool-macos-x64.tar.gz",
checksum = "sha256:abc123",
}
linux-x64 = {
url = "https://example.com/my-tool-linux-x64.tar.gz",
checksum = "sha256:def456",
}
You can also use dotted notation for simpler nested configurations:
[tools."http:my-tool"]
version = "1.0.0"
platforms.macos-x64.url = "https://example.com/my-tool-macos-x64.tar.gz"
platforms.linux-x64.url = "https://example.com/my-tool-linux-x64.tar.gz"
simple_option = "value"
Any backend can use nested options for organizing complex configurations:
[tools."custom:my-backend"]
version = "1.0.0"
[tools."custom:my-backend".database]
host = "localhost"
port = 5432
[tools."custom:my-backend".cache.redis]
host = "redis.example.com"
port = 6379
Internally, nested options are flattened to dot notation (e.g., platforms.macos-x64.url, database.host, cache.redis.port) for backend access.
Run a command immediately after a tool finishes installing by adding a postinstall field to that tool's configuration. This is separate from [hooks].postinstall and applies only to when a specific tool is installed.
[tools]
node = { version = "22", postinstall = "corepack enable" }
Behavior:
MISE_TOOL_INSTALL_PATH pointing to the tool's install directory.postinstall command is not run.You can restrict tools to specific operating systems using the os field:
[tools]
# Only install on Linux and macOS
ripgrep = { version = "latest", os = ["linux", "macos"] }
# Only install on Windows
"npm:windows-terminal" = { version = "latest", os = ["windows"] }
# Works with other options
"cargo:usage-cli" = {
version = "latest",
os = ["linux", "macos"],
install_env = { RUST_BACKTRACE = "1" }
}
The os field accepts an array of operating system identifiers:
"linux" - All Linux distributions"macos" - macOS (Darwin). "darwin" is also accepted as an alias."windows" - Windows. "win" is also accepted as an alias.You can also restrict tools to specific OS and architecture combinations using the os/arch syntax:
[tools]
# Only install on macOS ARM64 and all Linux (skips macOS x86_64)
hk = { version = "latest", os = ["linux", "macos/arm64"] }
# Only install on Linux x86_64
mytool = { version = "latest", os = ["linux/x64"] }
Supported architecture identifiers:
"arm64" (or "aarch64")"x64" (or "x86_64" or "amd64")When an entry contains /, both the OS and architecture must match. When an entry is just an OS name, it matches any architecture on that OS.
If a tool specifies an os restriction and the current operating system is not in the list, mise will skip installing and using that tool.
You can declare explicit installation dependencies between tools using the depends field. This ensures that one tool is fully installed before another begins installing.
[tools]
python = "3.12.11"
"pipx:ruff" = { version = "latest", depends = ["python"] }
In this example, pipx:ruff will wait for python to finish installing before it starts.
The depends field accepts either a single string or an array of strings:
[tools]
# Single dependency
"pipx:ruff" = { version = "latest", depends = "python" }
# Multiple dependencies
"pipx:ruff" = { version = "latest", depends = ["python", "pipx"] }
User-specified depends adds ordering constraints for tools already in the current install set. Use it when one configured tool install must finish before another configured tool install starts, especially when installs would otherwise run in parallel.
depends in [tools] only adds install graph ordering. It does not by itself declare hook-time dependencies or add those tools to the PATH used while vfox install hooks run.
For vfox plugins, declare install-hook tool requirements on the PLUGIN table in metadata.lua:
PLUGIN = {
name = "example",
version = "1.0.0",
depends = { "go" },
}
Use tool names as they would appear in mise.toml. When matching tools are configured, mise uses those metadata entries to order current install jobs and to build the hook environment. See Tool plugin development.
mise uses intelligent caching to minimize overhead:
This ensures that mise adds minimal latency to your daily development workflow.
::: info After activating, mise will update env vars like PATH whenever the directory is changed or the prompt is displayed. See the FAQ. :::
After activating, every time your prompt displays it will call mise hook-env to fetch new
environment variables.
This should be very fast. It exits early if the directory wasn't changed or
mise.toml/.tool-versions files haven't been modified.
mise modifies PATH ahead of time so the runtimes are called directly. This means that calling a tool has zero overhead and commands like which node returns the real path to the binary.
Other tools like asdf only support shim files to dynamically locate runtimes when they're called which adds a small delay and can cause issues with some commands. See shims for more information.
Here are some of the most important commands when it comes to working with dev tools. Click the header for each command to go to its reference documentation page to see all available flags/options and more examples.
mise useFor some users, mise use might be the only command you need to learn. It will do the following:
PATH)mise.toml or .tool-versions)> cd my-project
> mise use node@26
# download node, verify signature...
mise [email protected] ✓ installed
mise ~/my-project/mise.toml tools: [email protected] # mise.toml created/updated
> which node
~/.local/share/mise/installs/node/26/bin/node
mise use node@26 will install the latest version of node-26 and create/update the
mise.toml
config file in the local directory. The resulting file looks like this:
[tools]
node = "26"
Anytime you're in that directory, that version of node will be used.
mise use -g node@26 will do the same but update the global config (~/.config/mise/config.toml) so
unless there is a config file in the local directory hierarchy, node-26 will be the default version
for
the user.
You can also edit mise.toml directly instead of using mise use — the effect is the same. Run mise install after editing to install any new tools.
mise installmise install will install but not activate tools—meaning it will download/build/compile the tool
into ~/.local/share/mise/installs but you won't be able to use it without "setting" the version
in a .mise-toml or .tool-versions file.
::: tip
If you're coming from asdf, there is no need to also run mise plugin add to first install
the plugin, that will be done automatically if needed. Of course, you can manually install plugins
if you wish or you want to use a plugin not in the default registry.
:::
There are many ways it can be used:
mise install [email protected] - install a specific versionmise install node@20 - install the latest version matching this prefixmise install node - install whatever version of node currently specified in mise.toml (or other
config files)mise install - install all plugins and tools specified in the config filesmise exec|mise xmise x can be used for one-off commands using specific tools. e.g.: if you want to run a script
with python3.12:
mise x [email protected] -- ./myscript.py
Python will be installed if it is not already. mise x will read local/global
.mise-toml/.tool-versions files
as well, so if you don't want to use mise activate or shims you can use mise by just prefixing
commands with
mise x --:
$ mise use node@20
$ mise x -- node -v
20.x.x
::: tip If you use this a lot, an alias can be helpful:
alias mx="mise x --"
:::
Similarly, mise run can be used to execute tasks which will also activate the mise
environment with all of your tools.
mise provides several mechanisms to automatically install missing tools or versions as needed. Below, these are grouped by how and when they are triggered, with relevant settings for each. All mechanisms require the global auto_install setting to be enabled (all auto_install settings are enabled by default).
mise x, mise r)When you run a command like mise x or mise r, mise will automatically install any missing tool versions required to execute the command.
mise x or mise r with a tool/version that is not yet installed.exec_auto_install (default: true)task_auto_install (default: true)If you type a command in your shell (e.g., node) and it is not found, mise can attempt to auto-install the missing tool version if it knows which tool provides that binary.
not_found_auto_install (default: true)::: tip
Disable auto_install for specific tools by setting auto_install_disable_tools to a list of tool names.
:::