Skip to main content

Managing Development Tool Versions with mise

· 6 min read
Haril Song
Owner, Software Engineer at 42dot

Overview

  • Do you use a variety of programming languages rather than just one?
  • Have you ever felt fatigued from memorizing commands for multiple package managers like sdkman, rvm, nvm, etc.?
  • Would you like to manage your development environment more quickly and conveniently?

With mise, you can use the exact version of any language or tool you need, switch between different versions, and specify versions for each project. By specifying versions in a file, you can reduce communication costs among team members about which version to use.

Until now, the most famous tool in this field was asdf1. However, after starting to use mise recently, I found that mise offers a slightly better user experience. In this post, I will introduce some simple use cases.

mise vs asdf

Not sure if it's intentional, but even the web pages look similar.

mise-en-place, mise

mise (pronounced 'meez') is a tool for setting up development environments. The name comes from a French culinary term that roughly translates to "setting" or "putting in place." It means having all your tools and ingredients ready before you start cooking.

Here are some of its simple features:

  • Supports almost all programming languages and tools as a package manager
  • Can be extended with plugins
  • Written in Rust, unlike asdf which is written in Shell
  • Provides features for setting environment variables like direnv

Installation

You can install it via brew.

brew install mise
# or
curl https://mise.run | sh
mise --version
# mise 2024.6.6

Activate mise

Follow the guide to run the activation command.

# bash
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc

# zsh
echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc

Use Cases

Managing Dependency Versions

Let's assume you've joined a new company and received a new machine. The new place primarily uses Java, so let's check if we can install the required version.

mise ls-remote java

mise version list

fuzzy finder, fzf

If too many versions are listed, you can use mise ls-remote java | fzf.

Let's install corretto-11.0.18.10.1 and set it as the default Java version.

mise use --global java@corretto-11.0.18.10.1

language select 1

language select 2

As of writing, the LTS version of Java is 21. Let's install version 21 and also the frequently used version 17.

mise install java@17 java@21

mise install java

After installation, you can check which languages are installed using the mise ls command.

mise ls

mise list

Suppose your team leader suggests using Java 21 for a new project. It would be good to use Java 21 only for that project.

mkdir project && cd project
touch .mise.toml
mise use java@21

When using mise, you specify which version to use in a file called .mise.toml2.

# ~/project/.mise.toml
[tools]
java = "21"

Running mise ls again will show the change in the Config Source and the applied Java version.

mise list 2

check language version

tip

If you've been using asdf and already have a .tool-versions file, you can continue to use tool-versions.

Now you can use different Java versions for different projects. By specifying the Java version in the .mise.toml file, you can minimize issues caused by differences in development environments among team members.

Thinking about it, Java 11 is no longer needed. Let's set 17 as the default and remove 11.

mise use --global java@17
mise uninstall java@corretto-11.0.18.10.1

Now that we've installed the languages needed for work, let's install some personal favorites.

I'm developing an Obsidian plugin called O2 using TypeScript. Let's install the latest stable version of node.

mise use node@lts

I also occasionally do data cleaning tasks using Python.

mise use python@3.12.3 # Python is sensitive to versions, so I use the most specific version possible.

I also create bots for work using golang and APIs for traffic experiments.

mise use go@latest

I also use Rust, Ruby, etc., but I'll skip those...

Wow, that's a lot. It would be nice to install everything at once.

After specifying them in ~/.config/mise/config.toml,

# ~/.config/mise/config.toml
[tools]
java = "corretto-11.0.18.10.1"
node = "lts"
go = "latest"
python = "3.12.3"

you can install all dependencies at once using mise install.

mise install

install all languages

Of course, you can also handle it all at once with a command. Languages not specified in ~/.config/mise/config.toml will be appended automatically.

mise use --global node@lts python@3.12.3 go@latest

install multiple languages with one command

install multiple languages with one command 2

tip

I usually only manage programming languages, but you can also manage other tools like gradle or awscli with mise.

Managing Environment Variables

mise = asdf + direnv

With mise, you can specify different environment variables for different projects. The user experience is identical to what you get with direnv. In fact, it's even more convenient since you don't have to manage a .envrc file.

Let's define a simple variable in .mise.toml.

[env]
HELLO = 'WORLD'
warning

To apply environment variables defined in .mise.toml, you need to confirm them using the mise trust command. This is to prevent security issues that could arise from automatically executing files downloaded from other projects.

You can verify that the environment variable is working correctly by using echo.

The information set in ~/project/.mise.toml is only valid within the ~/project directory. Once you leave this scope, the HELLO environment variable will be automatically unset.

You can also manage it via CLI without directly editing .mise.toml.

mise set HELLO=world
mise set HELLO
# world
mise set
# key value source
# HELLO WORLD ~/project/.mise.toml
mise unset HELLO
mise set
# key value source

Simple, right? If you need to manage environment variables globally, you can define them in ~/.config/mise/config.toml as mentioned earlier.

mise set -g GLOBAL='mise is insane!'
mise set
# key value source
# GLOBAL mise is insane! ~/.config/mise/config.toml

If you share the .mise.toml file containing the necessary information for a specific development environment, setting up the environment will be much easier. As mentioned earlier, mise can also manage package versions. While asdf is an excellent all-in-one tool, the ability to manage environment variables makes mise even more special.

Conclusion

This concludes the basic setup of the development environment. You might wonder if just installing languages is enough. For other aspects, refer to Managing Dotfiles. Since setting up a new development environment usually takes 1-2 hours, I'll spend the remaining time reading some development books.

image

Reference


Footnotes

  1. As of June 2024, GitHub Star 21k

  2. mise configuration