When to Let the Official Tool Win
The previous article made mise the single owner of Python versions and kept uv at the dependency layer. On the same machine, though, I let rustup own Rust even though mise can install Rust too.
The difference is not a special exception for Rust. Before assigning Layer 1—the runtime version—I ask one question: does this language have a strong, official sovereign tool?
What counts as a sovereign tool
Here, a sovereign tool means an official version and toolchain manager that belongs to the language project itself. rustup for Rust and Xcode for Swift are the clearest examples. If one exists and is strong, I leave the layer to it. If the official option is absent or too limited, mise fills the gap.
“Official” alone is not enough. I look for four things:
- It is part of the language project. It comes from the people shipping the compiler, rather than a third party trying to catch up with it.
- It owns more than a version switch. That can include toolchain components, stable/beta/nightly channels, cross-compilation targets, and project pins recognized across the ecosystem. Merely selecting the active version is already something
misehandles well. - The community has converged on it. “How do I install this language?” should have one routine, near-universal answer. Three competing answers mean there is no sovereign tool yet.
- Its contract is stable across upgrades. Giving a tool this layer for years only works if routine upgrades do not break existing projects.
rustup clears all four: it is part of Rust, manages toolchains, targets, and release channels, is the standard installation path, and has kept a stable contract for years. Go’s official dl installer is a useful counterexample. It fetches a particular Go version, but does little beyond that and has not become the accepted owner of version management. It is official, but it does not clear criteria 2 and 3, so I still treat it as weak.
Applying it to the languages I use
These judgments are all about Layer 1: the runtime version.
- Python: no sovereign tool.
pyenv,mise,uv, the system Python, and other approaches coexist. I therefore letmiseown Layer 1 and keepuvat Layer 2, as described in the Python article. - Rust:
rustupis the sovereign tool. It installs Rust on my machine;misedoes not. - Node.js:
nvm,fnm,volta, andmisecompete, with no official answer. I usemise. - Java: there is no sovereign tool, and Java also comes in multiple distributions. I use
misewith Temurin as the default, a neutral choice that avoids reopening the distribution question for every project. - Swift / iOS: Xcode owns the toolchain, SDK, and build system and is shipped by Apple. On macOS, installing Swift through another manager means working against the platform, so I defer completely.
- Go: the official option is too weak to own the layer. I am comfortable putting Go under
mise, as many other users do. - Ruby:
rbenv,rvm,chruby, andmiseall exist; none is sovereign. When I need Ruby,miseowns its version.
mise can be a proxy
Deferring to rustup does not necessarily mean typing rustup for every operation. A project can still declare Rust in mise.toml:
[tools]rust = "1.78"mise delegates to rustup; it does not reimplement Rust toolchain management. I think of this as mise as proxy: it provides the shared interface while rustup remains the owner and source of truth.
That leaves two sensible arrangements:
rustup-native: a Rust-only project talks torustupdirectly. There is no polyglot setup to unify.miseas the project interface: a polyglot project already pinning Python and Node inmise.tomlcan addrust = "1.78". Thenmise installprovisions the project through one declaration while delegating Rust torustup.
The trap is mixing these arrangements inside one project until neither file is authoritative. The interface may be mise or rustup, but ownership of the Rust toolchain must remain with rustup.
The answers can change
I used the same test when looking at Zig. At the time, it did not have a strong official manager with community consensus, so mise or a simple manual installation was reasonable. Mojo falls into the same young-ecosystem category. Haskell is a useful edge case: GHCup is strong enough that deferring to it makes sense. Lua has no consensus tool, so mise fills the gap.
These are current judgments, not permanent assignments. If Python eventually ships a strong official manager and the community converges on it, I would move Python out of mise and defer to that tool just as I defer to rustup today.
The first article said that each kind of resource should have one owner. This test decides who that owner is for runtime versions. The next article turns the resulting choices into a concrete stack, including the pitfalls, lockfiles, and gitignore patterns for each language.