devAlice
← Mac

Mac-Sprach-Toolchain — ein mise statt nvm + pyenv + rbenv + goenv

nvm, pyenv, rustup-light, goenv und rbenv durch ein einziges Tool ersetzen. Projektweises automatisches Umschalten, Shell-Integration und Migrationspfade.

Im ersten Jahr installierst du nvm für Node. Im zweiten kommt pyenv dazu. Im dritten haben sich rustup, goenv und rbenv übereinander gestapelt, und deine .zshrc ist um 30 Zeilen angewachsen. Jeder Shell-Hook beißt sich mit den anderen, und das Setup auf einem neuen Gerät zu reproduzieren wird zur Mühe.

mise (früher rtx) konsolidiert das in einer einzigen Binärdatei: asdf-kompatibel, in Rust geschrieben, schnell und schlank. Dieser Leitfaden zeigt mise für Node · Python · Rust · Go · Ruby mit einem einheitlichen Workflow.

TL;DR

  1. Ein mise ersetzt jeden sprachspezifischen Versionsmanager
  2. Projektweise Versionen in .mise.toml fixieren (oder .tool-versions)
  3. Automatisches Umschalten bei cd — kein manueller use-Befehl nötig
  4. Ein mise install rehydriert jede Sprache/Version auf einem neuen Gerät
  5. nvm/pyenv/rbenv deinstallieren — Überschneidungen sind schädlich

Voraussetzungen

  • macOS 12+ mit Homebrew (Mac-Ersteinrichtung)
  • Optional: bestehender nvm/pyenv-Zustand — siehe Migrationsabschnitt

1. Warum mise

Was es ersetzt

  • Node.js (nvm, n, fnm, volta)
  • Python (pyenv)
  • Rust (teilweise — rustup für ernsthafte Rust-Arbeit behalten, siehe §10)
  • Go (goenv)
  • Ruby (rbenv, rvm)
  • Java (jenv)
  • Weitere — Elixir, Erlang, Lua, Bun, Deno, Terraform, kubectl, …

Stärken

  • Schnell — einzelne Rust-Binärdatei; unterstützt shim-losen PATH-only-Modus
  • asdf-kompatibel.tool-versions-Dateien funktionieren wie gehabt
  • Auto-Switchcd allein ändert Versionen; kein use nötig
  • Global vs. Projektmise use --global vs. mise use

Schwächen

  • Einige rustup-Funktionen fehlen — Toolchain-Kanäle (stable/nightly/beta) und Komponenten (clippy, rustfmt, rust-analyzer) sind in rustup reibungsloser. mise ist in Ordnung, wenn du eine einzelne Rust-Version fixierst.
  • Kein vollwertiges Sprach-Tool — gelegentliche Sonderfälle (z. B. Pythons python-build-Optionen).

2. Installation

brew install mise

Shell-Integration (an .zshrc anhängen):

eval "$(mise activate zsh)"

Ein neues Terminal öffnen und mit mise --version bestätigen.

bash: mise activate bash. fish: mise activate fish.

3. Erste Nutzung — Node installieren

# Verfügbare Versionen durchsuchen
mise ls-remote node
 
# Global installieren
mise use --global node@22
 
# …oder LTS
mise use --global node@lts

Verifizieren:

node --version    # v22.x
which node        # ~/.local/share/mise/installs/node/22/bin/node

4. Projektweise Versionen fixieren

Im Projektordner:

cd ~/work/my-app
mise use node@20.18.0    # dieses Projekt fixiert Node 20.18.0

Dies erstellt .mise.toml:

[tools]
node = "20.18.0"

Oder die asdf-kompatible Form (.tool-versions):

node 20.18.0
python 3.12.7

.mise.toml hat Vorrang. .tool-versions für asdf-Kompatibilität oder bei der Migration bestehender Projekte verwenden.

Automatisches Umschalten

cd allein veranlasst mise, .mise.toml aufzugreifen und Versionen umzuschalten. node --version wechselt sofort.

5. Mehrsprachiges Projekt

cd ~/work/fullstack
mise use node@22
mise use python@3.12
mise use go@1.23

.mise.toml:

[tools]
node = "22"
python = "3.12"
go = "1.23"

mise install — installiert alle fehlenden Versionen in einem Schritt.

6. Global vs. Lokal

mise use --global node@22     # ~/.config/mise/config.toml
mise use node@20              # .mise.toml im aktuellen Verzeichnis

Priorität (höchste zuerst):

  1. Umgebungsvariable MISE_NODE_VERSION
  2. .mise.toml / .tool-versions aufwärts vom aktuellen Verzeichnis
  3. Global ~/.config/mise/config.toml
  4. Standard-PATH des Systems

7. Tägliche Befehle

# Alle installierten Versionen
mise ls
 
# Verfügbare Remote-Versionen eines Tools
mise ls-remote python
 
# Alles installieren, was in Lock-Dateien deklariert ist
mise install
 
# Ein einzelnes Tool aktualisieren
mise upgrade node
 
# Eine Version deinstallieren
mise uninstall node@18
 
# Umgebung inspizieren
mise env
 
# Einmaliger Aufruf
mise exec -- node --version
mise x -- npm test

8. .envrc / direnv-Integration

mise 0.30+ unterstützt Umgebungsvariablen direkt in .mise.toml:

[tools]
node = "22"
 
[env]
DATABASE_URL = "postgresql://localhost/myapp"
NODE_ENV = "development"

Eine separate direnv-Konfiguration wird damit überflüssig — mise exportiert die Umgebung automatisch beim cd-Wechsel.

9. Migration von nvm/pyenv

nvm → mise

# Welche Node-Version verwendest du?
nvm current
# v20.18.0
 
# Dieselbe Version unter mise installieren
mise use --global node@20.18.0
 
# nvm entfernen
brew uninstall nvm
# oder
rm -rf ~/.nvm
 
# Die nvm-Hook-Zeilen aus .zshrc löschen

pyenv → mise

pyenv versions
# Verwendete Versionen bestätigen
 
mise use --global python@3.12.7
 
# pyenv entfernen
brew uninstall pyenv pyenv-virtualenv
rm -rf ~/.pyenv
 
# .zshrc bereinigen

asdf → mise

# Bestehende .tool-versions funktionieren einfach
brew uninstall asdf
brew install mise
 
# Die asdf-Zeile in .zshrc durch die mise-activate-Zeile ersetzen

mise ist für die meisten Plugins asdf-plugin-kompatibel. Über mise plugins ls-remote prüfen.

10. Rust — mise vs. rustup

Rusts Toolchain-Konzept (stable, nightly) mit Komponenten (clippy, rustfmt, rust-analyzer) ist leistungsstark — und rustup handhabt das besser. mise für Rust verwenden, nur wenn das Fixieren einer einzigen Version genügt.

Empfehlungen:

  • Ernsthafte Rust-Entwicklung: rustup behalten. Andere Sprachen mit mise verwalten.
  • Gelegentliches Rust: mise mit einer einzigen stable-Version ist in Ordnung.

rustup behalten:

brew install rustup-init
rustup-init -y
# .zshrc aktiviert die rustup-Umgebung automatisch

Verifizierung

  1. mise --version — Installation OK
  2. cd ~/work/proj-a && node --version → fixierte Version von Projekt A
  3. cd ~/work/proj-b && node --version → Version von Projekt B (automatisch umgeschaltet)
  4. mise install — alles installieren, was in .mise.toml deklariert ist
  5. Neues Gerät: brew install mise && mise install → vollständige Rehydrierung

Problembehandlung

command not found: node

  • eval "$(mise activate zsh)" fehlt in .zshrc
  • Neues Terminal öffnen oder . ~/.zshrc

Automatisches Umschalten passiert nicht

  • .mise.toml oder .tool-versions sollte sich im Projektstammverzeichnis befinden
  • mise current zeigt, was aktiv ist
  • Vertrauensaufforderung — beim ersten Betreten eines neuen Verzeichnisses: einmalig mise trust

pip install-Berechtigungsfehler

mises Python ist benutzerlokaler Natur — nicht mit dem System-Python verwechseln. venv bevorzugen:

python -m venv .venv
source .venv/bin/activate
pip install ...

Node nativer Modul-Build schlägt fehl

  • mises Node verwendet vorgefertigte Binärdateien — npm rebuild oder node-gyp explizit aufrufen
  • macOS benötigt Xcode CLT: xcode-select --install

Asdf-Community-Plugin fehlt

Einige asdf-Community-Plugins (asdf-foo) sind nicht in der Kern-Pluginliste von mise enthalten. Manuell hinzufügen: mise plugins install foo https://github.com/....

Nicht-deterministische Builds

Exakte Versionen in .mise.toml fixieren (node = "20.18.0", nicht "20") — das fungiert als Lock-Datei für die Teamarbeit.

Referenzen

Changelog

  • 2026-05-12 — Erste Übersetzung (devAlice M3 i18n Seed)