devAlice
← Mac

Cadena de herramientas de lenguajes Mac: un mise en lugar de nvm + pyenv + rbenv + goenv

Reemplaza nvm, pyenv, rustup-light, goenv y rbenv con una sola herramienta. Cambio automático por proyecto, integración con el shell y rutas de migración.

El primer año instalas nvm para Node. El segundo añades pyenv. Al tercero tienes rustup, goenv y rbenv apilados, tu .zshrc ha crecido 30 líneas y cada hook de shell compite con los demás. Reproducir la configuración en una máquina nueva se convierte en una tarea costosa.

Creo que lo que hace poderoso a mise no es que sea más rápido, sino que elimina la decisión de qué gestor usar por lenguaje. En lugar de recordar qué herramienta corresponde a cada lenguaje, un solo flujo de trabajo lo cubre todo.

mise (anteriormente rtx) consolida todo esto en un único binario. Compatible con asdf, escrito en Rust, rápido y pequeño. Esta guía se centra en mise para Node · Python · Rust · Go · Ruby con un flujo de trabajo consistente.

TL;DR

  1. Un mise reemplaza cada gestor de versiones por lenguaje
  2. Fija las versiones por proyecto en .mise.toml (o .tool-versions)
  3. Cambio automático en cd — sin comando use manual
  4. Un mise install rehidrata cada lenguaje/versión en una máquina nueva
  5. Desinstala nvm/pyenv/rbenv — la superposición es perjudicial

Requisitos previos

1. Por qué mise

Herramientas que reemplaza

  • Node.js (nvm, n, fnm, volta)
  • Python (pyenv)
  • Rust (parcialmente — mantén rustup para trabajo serio con Rust, ver §10)
  • Go (goenv)
  • Ruby (rbenv, rvm)
  • Java (jenv)
  • Otros — Elixir, Erlang, Lua, Bun, Deno, Terraform, kubectl, …

Fortalezas

  • Rápido — binario único en Rust; soporta modo PATH-only sin shims
  • Compatible con asdf — los archivos .tool-versions funcionan tal cual
  • Cambio automático — solo cd cambia las versiones; no se necesita use
  • Global vs proyectomise use --global vs mise use

Debilidades

  • Algunas funcionalidades de rustup no están disponibles: los canales de toolchain (stable/nightly/beta) y los componentes (clippy, rustfmt, rust-analyzer) se gestionan mejor con rustup. mise funciona bien cuando se fija una sola versión de Rust.
  • No es una herramienta oficial del lenguaje: pueden aparecer casos límite ocasionales (p.ej., opciones de python-build).

2. Instalar

brew install mise

Integración con el shell (añadir a .zshrc):

eval "$(mise activate zsh)"

Abre un nuevo terminal y confirma con mise --version.

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

3. Primer uso — instalar Node

# Explorar versiones disponibles
mise ls-remote node
 
# Instalar globalmente
mise use --global node@22
 
# …o LTS
mise use --global node@lts

Verificar:

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

4. Fijar versiones por proyecto

Dentro de la carpeta de tu proyecto:

cd ~/work/my-app
mise use node@20.18.0    # este proyecto fija Node 20.18.0

Esto crea .mise.toml:

[tools]
node = "20.18.0"

O la forma compatible con asdf (.tool-versions):

node 20.18.0
python 3.12.7

.mise.toml tiene prioridad. Usa .tool-versions para compatibilidad con asdf o al migrar proyectos existentes.

Cambio automático

Solo cd hace que mise recoja .mise.toml y cambie las versiones. node --version cambia inmediatamente.

5. Proyecto multi-lenguaje

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 — instala todas las versiones faltantes de una sola vez.

6. Global vs local

mise use --global node@22     # ~/.config/mise/config.toml
mise use node@20              # .mise.toml en el directorio actual

Prioridad (mayor a menor):

  1. Variable de entorno MISE_NODE_VERSION
  2. .mise.toml / .tool-versions subiendo desde el directorio actual
  3. Global ~/.config/mise/config.toml
  4. El PATH del sistema por defecto

7. Comandos diarios

# Todas las versiones instaladas
mise ls
 
# Versiones remotas disponibles de una herramienta
mise ls-remote python
 
# Instalar todo lo declarado en los archivos de configuración
mise install
 
# Actualizar una sola herramienta
mise upgrade node
 
# Desinstalar una versión
mise uninstall node@18
 
# Inspeccionar el entorno
mise env
 
# Ejecución puntual
mise exec -- node --version
mise x -- npm test

8. Integración con .envrc / direnv

mise 0.30+ soporta variables de entorno en .mise.toml:

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

Ya no se necesita una configuración separada de direnv — mise exporta automáticamente el env en cd.

9. Migrar desde nvm/pyenv

nvm → mise

# ¿Qué versión de Node estás usando?
nvm current
# v20.18.0
 
# Instala la misma versión bajo mise
mise use --global node@20.18.0
 
# Elimina nvm
brew uninstall nvm
# o
rm -rf ~/.nvm
 
# Elimina las líneas del hook de nvm de .zshrc

pyenv → mise

pyenv versions
# Confirma las versiones en uso
 
mise use --global python@3.12.7
 
# Elimina pyenv
brew uninstall pyenv pyenv-virtualenv
rm -rf ~/.pyenv
 
# Limpia .zshrc

asdf → mise

# Los .tool-versions existentes funcionan tal cual
brew uninstall asdf
brew install mise
 
# Reemplaza la línea de asdf en .zshrc por la línea de activación de mise

mise es compatible con los plugins de asdf para la mayoría. Verifica con mise plugins ls-remote.

10. Rust: mise vs rustup

La gestión de toolchains (stable, nightly) y componentes (clippy, rustfmt, rust-analyzer) de Rust es compleja; rustup la maneja mejor. Usa mise para Rust solo cuando basta con fijar una única versión.

Recomendaciones:

  • Desarrollo serio de Rust: mantén rustup. Gestiona otros lenguajes con mise.
  • Rust ocasional: mise con una versión stable está bien.

Para mantener rustup:

brew install rustup-init
rustup-init -y
# .zshrc activa automáticamente el entorno de rustup

Verificación

  1. mise --version — instalación OK
  2. cd ~/work/proj-a && node --version → versión fijada del proyecto A
  3. cd ~/work/proj-b && node --version → versión del proyecto B (cambio automático)
  4. mise install — instala todo lo declarado en .mise.toml
  5. Máquina nueva: brew install mise && mise install → rehidratación completa

Solución de problemas

command not found: node

  • Falta eval "$(mise activate zsh)" en .zshrc
  • Abre un nuevo terminal, o . ~/.zshrc

El cambio automático no ocurre

  • .mise.toml o .tool-versions debe estar en la raíz del proyecto
  • mise current muestra lo que está activo
  • Aviso de confianza — primera vez que entras a un nuevo directorio: mise trust una vez

Errores de permisos en pip install

El Python de mise es local al usuario. No lo confundas con el Python del sistema. Prefiere un venv:

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

Fallo en la compilación de módulos nativos de Node

  • El Node de mise usa prebuilds — npm rebuild o llama a node-gyp explícitamente
  • macOS necesita Xcode CLT: xcode-select --install

Plugin de comunidad de asdf faltante

Algunos plugins de comunidad de asdf (asdf-foo) no están en la lista principal de mise. Añádelos manualmente: mise plugins install foo https://github.com/....

Compilaciones no deterministas

Fija las versiones exactas en .mise.toml (node = "20.18.0", no "20"). Actúa como lock para trabajo en equipo.

Referencias

Historial de cambios

  • 2026-05-12: Versión inicial (semilla i18n devAlice M3)