How I use `mise` to manage my dev environment
Papercuts, papercuts everywhere
I work with different programming languages, and each one has its own installation method and its own toolchain.
Now thankfully, all the languages I have worked in have some form of a version manager:
These tools work fine, actually. What I get are all these tiny papercuts:
- You spend some time learning to use one of these, and then proceed not to touch them for the next 6 - 9 months
- They all work just different enough that you need to refer to the documentation, since this is not something you use often.
- If you use different machines, ensuring you have all these tools installed is a bit of a chore.
All these accumulated papercuts are starting to bother me. What I need is:
- A single tool to rule them all
- I should be able to use this to install a specific version of a tool I need
- Scoping the tool to a single project/repository. That way, I do not need to manually find the right version of a tool and activate it for the project
- It needs to work with my IDE (in my case, VSCode)
Mise to the rescue
Introducing: mise
mise
sells itself as a "front-end to your dev env". The getting-started flow is simple enough:
- Install
mise
. - Use
mise
to runnode
# Try running node
# Command 'node' not found, but can be installed with:
# sudo apt install nodejs
# This downloads node and runs it
# Expected output: v22.14.0
# Try running it again:
# Command 'node' not found, but can be installed with:
# sudo apt install nodejs
So what happened here is:
- I do not have
node
installed on my system (Ubuntu LTS running on WSL) - I asked
mise
to run a specific version ofnode
- It downloaded it and ran it
- Crucially, it is not directly added to my $PATH unless I asked it to, which will be important later when you want to scope a tool's version to a specific repository.
Using it in a real project
Let's say you have a simple Nodejs project, that looks like this:
├── README.md
├── node_modules
├── package-lock.json
├── package.json
├── sql
├── src
├── tsconfig.json
└── wrangler.toml
You would do one of the following:
- In the README, specify the
node
version required, and leave it up to the reader to get it themselves
OR
- Have something like an
.nvmrc
that specifies whichnode
version this project accepts, and leave it to the reader to get it themselves.
Instead, let's have mise
handle this for us.
Using an LTS node version for the project
Let's say I want to use an LTS version of node
for the project:
This does 2 things:
- It creates a
mise.toml
. You can commit this file to source control to ensure that other people working on your project will also get the exact same version and tool you use.
[tools]
node = "lts"
mise
will download and installnode
, if it already does not exist. It modifies your $PATH to ensure it will use thenode
that it has downloaded.
# /home/kklee/.local/share/mise/installs/node/22.14.0/bin/node
# Welcome to Node.js v22.14.0.
# Type ".help" for more information.
>
Now the setup guide of the project becomes:
- Get
mise
- Activate
mise
- Clone the project
mise install
, this installs all the tools specified inmise.toml
- ????
- Profit
You might be thinking to yourself: "Is this any different than managing it with nvm
"?
The answer is: No.
But nvm
only works with node
projects. If you have other languages you need to work in, mise
really shines. You can now use one CLI to manage them all in a consistent fashion.
Using it with a Python project
Same as before:
Check the python version and path before doing anything:
# /home/kklee/.local/share/mise/installs/python/3.13.3/bin/python
# Python 3.13.3
Always create a virtualenv before doing anything:
And that is all, really.
Side Note:
I know
poetry
anduv
exists. These are a little out of the scope of this post, maybe a topic for another day. But for now, the old school venv + pip combo is good enough for a simple demo.
Is that all mise
can do?
I am barely scratching the surface of what mise
can do:
- Installing (and updating) other tools, pinned to a specific version. At $DAYJOB, the
aws
and AWS SAM CLI comes to mind. You can find all the toolsmise
can install here: registry - This blog is written inzola
and of couse,mise
supports it - Incremental adoption. Already have a
.nvmrc
or.python-version
in your repo? No problem,mise
handles it. - Environment variables, secrets for local development?
- Using it with CI?
Hotel? Trivago
What if I have a project/team/company that does not want to adopt mise
(yet)?
So you want to use mise
, but other people are not so keen about it, what to do?
The easiest way is to have a mise.toml
in the project directory but not commit it.
This is, unfortunately, an error waiting to happen.
So instead, what I do is:
mise
recommends using amise.local.toml
file for "local config, this should not be committed to source control". https://mise.jdx.dev/configuration.html#mise-toml- You can have a global
.gitignore
file that ignoresmise.local.toml
1. Here is how you can set up a global.gitignore
on your machine: https://gist.github.com/subfuzion/db7f57fff2fb6998a16c - Voila! Now you can happily use
mise
and not have the risk of accidentally commiting amise.toml
into your PR.