Managing Ruby and Rails with mise
My Ruby version management has been on a bit of a journey. It started with rbenv - I’ve written a few posts on it - then for a while I just installed Ruby straight from Homebrew (fine until two projects disagree), then asdf, which was the first tool to manage everything with one plugin system. Earlier this year I rebuilt my dotfiles and landed on mise, and this feels like the final stop. It’s asdf’s idea done properly - same .tool-versions compatibility, but a single fast binary, no plugins to install, and every version pinned in a config file that lives in my dotfiles repo.
Installing
curl https://mise.run | sh
Then activate it in your shell by adding this to the bottom of ~/.zshrc:
eval "$(~/.local/bin/mise activate zsh)"
Open a new terminal and mise --version should answer.
Ruby, globally
mise use --global [email protected]
which ruby # should be a mise shim path, NOT /usr/bin/ruby
ruby -v
That which ruby check matters - if it comes back with the system Ruby, mise isn’t activated in your shell yet. I learned this the hard way when my machine-setup script installed everything except the Ruby bits, because a freshly opened terminal mid-install didn’t have the shims in its PATH. If you’re scripting a setup, put the shims in PATH explicitly rather than relying on shell activation:
export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"
Rails on top
Once which ruby points at mise, gems work exactly as before:
gem install rails jekyll bundler
rails -v
No rbenv rehash dance - mise’s shims just pick new executables up.
Per-project versions
This is where it earns its keep. Inside any project:
mise use [email protected]
That writes a .mise.toml into the directory, and from then on cd-ing in switches Ruby automatically. It also reads plain .ruby-version files, so every existing project keeps working untouched.
Pin it in your dotfiles
My global versions live in ~/.config/mise/config.toml, which is stowed from my dotfiles repo:
[tools]
ruby = "4.0.6"
node = "24"
Upgrading a tool is now: edit that file, run mise install, commit. On any other machine it’s git pull && mise install and everything matches. No hunting through shell scripts for where a version was hardcoded.
The everyday commands
mise ls # everything installed
mise ls ruby # just Ruby versions
mise install # install whatever the config asks for
mise upgrade # upgrade mise itself
mise doctor # when something feels off
One tool, one config file, every language. If you’re still juggling rbenv and nvm side by side, this is your sign. And if you want to see where that config.toml lives and how the whole machine gets rebuilt around it, that’s covered in the dotfiles post.