991 words
5 minutes
English

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:

  1. 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.
  2. 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 mise handles well.
  3. 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.
  4. 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.

Decision tree: does the language have a strong sovereign tool? Strong, official sovereign tool? part of the language · owns toolchain · consensus · stable Yes No / weak Defer to the sovereign tool it owns Layer 1 rustup → Rust Xcode → Swift mise fills the gap mise owns Layer 1 Python · Node · Java Ruby · Go (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 let mise own Layer 1 and keep uv at Layer 2, as described in the Python article.
  • Rust: rustup is the sovereign tool. It installs Rust on my machine; mise does not.
  • Node.js: nvm, fnm, volta, and mise compete, with no official answer. I use mise.
  • Java: there is no sovereign tool, and Java also comes in multiple distributions. I use mise with 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, and mise all exist; none is sovereign. When I need Ruby, mise owns 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:

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 to rustup directly. There is no polyglot setup to unify.
  • mise as the project interface: a polyglot project already pinning Python and Node in mise.toml can add rust = "1.78". Then mise install provisions the project through one declaration while delegating Rust to rustup.

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.

When to Let the Official Tool Win
https://www.shiinayane.com/en/posts/sovereignty/
Author
YANKAI WANG
Published at
2026-05-30
License
CC BY-NC-SA 4.0