ez environment management with mise

đź•‘14:15, 8 Apr 2025

Like asdf (or nvm or pyenv but for any language), it manages dev tools like node, python, cmake, terraform, and hundreds more.

Recently, I found myself reformatting several servers and switching between development machines. I’ve been automating the setup of system packages, command line tools, and system settings using Ansible. With this, I could also install programming languages and other CLI tools that are not available via the system package manager (i.e. via network installers or shell scripts). However, I frequently run into a couple of problems:

To resolve the first problem, I’ve been using pyenv and nvm to manage different versions of Python and Node.js, respectively. However, this will quickly become unweildy if I need a version manager for each tool, and I use A LOT of tools. I eventually stumbled upon asdf, which is essentially “one manager to replace them all”.

However, this doesn’t solve the second problem, and asdf makes the terminal feel sluggish at times. I recently discovered mise, which solves both problems, doesn’t perceivably affect terminal interactions, and has a lot more supported tools through the mise registry. It also doubles as a task runner, though I prefer to use task for that, so I won’t cover that use case here.

mise is a polyglot tool version manager and is available for Linux, macOS, and Windows. For this post, I’ll be focusing on a WSL setup, since this is what I daily drive.

To install mise on WSL, simply run

curl https://mise.run | sh

If all goes well, running mise should print the help text. If you get an error along the lines of command not found, you need to add ~/.local/bin to your PATH:

# bash
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
. ~/.bashrc

# zsh
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
. ~/.zshrc

To enable the mise registry, you need to enable the experimental flag. Create a file at the location ~/.config/mise/config.toml if it does not yet exist and add the following:

[experimental]
enable = true

To see all available tools, run

mise registry

Now for the fun part, we can install specific versions of tools to be used globally. For example:

mise use -g python@latest node@latest go@latest

This is great to quickly get up and running with the latest versions of tools. However, one of mise’s powerful features is setting constraints for versions. Typically, you won’t always use the latest version because you need to wait for libraries to update and be compatible. You aren’t limited to specifying full version numbers - you can specify minor or major versions:

mise use -g [email protected] node@22 [email protected]

An even more powerful feature is specifying what I like to call a “variable version”. In my use case, for Python and Go, I want to stay one minor version behind the latest, and the LTS version for Node.js. I can do this as follows:

mise use -g [email protected]:latest node@lts [email protected]:latest

The sub-0.1:latest syntax basically translates to “the latest version minus 0.1”. As of writing, the latest minor version of Python is 3.13, so mise will install version 3.12. When 3.14 is released, mise will automatically upgrade to 3.13. mise will automatically check for tool version updates, and you can update all tools by running

mise up -y

How then does this become reproducible on multiple machines? mise stores the information about install tool versions in the same mise.toml file you created earlier. After running the above commands, your mise.toml file should look like this:

[settings]
experimental = true

[tools]
python = "sub-0.1:latest"
node = "lts"
go = "sub-0.1:latest"

You can then copy this to other machines by including mise.toml as part of your dotrepo, which deserves its own blog post.

How do we now use different versions of tools for different projects? So far, we’ve been installing tools globally, but we can install tools locally to a project by navigating to the project directory and running the same commands as above, but omitting the -g (global) flag. This will create a new mise.toml file in the project directory with the tool versions for that project, which should be committed to version control.

Keywords

tech
software