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
miseto 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
nodeinstalled on my system (Ubuntu LTS running on WSL) - I asked
miseto 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
nodeversion required, and leave it up to the reader to get it themselves
OR
- Have something like an
.nvmrcthat specifies whichnodeversion 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"
misewill download and installnode, if it already does not exist. It modifies your $PATH to ensure it will use thenodethat 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
poetryanduvexists. 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
awsand AWS SAM CLI comes to mind. You can find all the toolsmisecan install here: registry - This blog is written inzolaand of couse,misesupports it - Incremental adoption. Already have a
.nvmrcor.python-versionin your repo? No problem,misehandles 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:
miserecommends using amise.local.tomlfile for "local config, this should not be committed to source control". https://mise.jdx.dev/configuration.html#mise-toml- You can have a global
.gitignorefile that ignoresmise.local.toml1. Here is how you can set up a global.gitignoreon your machine: https://gist.github.com/subfuzion/db7f57fff2fb6998a16c - Voila! Now you can happily use
miseand not have the risk of accidentally commiting amise.tomlinto your PR.