Saltar al contenido principal

mise — Gestor de versiones y entornos

⚠️ Verificar versiones antes de usar — la versión de mise y los runtimes mencionados aquí pueden estar desactualizados. Consultar mise ls-remote mise | tail -5 o mise.jdx.dev para la versión más reciente. Ver politicas-core.

Qué es

En una frase: mise instala automáticamente la versión correcta de cada programa que un proyecto necesita, para que todo el equipo use exactamente lo mismo sin instalar nada a mano.

mise es un gestor de versiones políglota y runner de tareas. Reemplaza a nvm, pyenv, rbenv, asdf y Makefile/npm scripts en un solo binario escrito en Rust. Activa automáticamente las versiones correctas de cada herramienta al entrar a un directorio.

Por qué lo usamos en Wiedii

La razón central es reproducibilidad sin fricción: cada desarrollador, en cualquier máquina, ejecuta exactamente las mismas versiones de bun, node y python que el resto del equipo — sin pasos manuales, sin scripts de setup, sin documentos de "antes de empezar".

Además reemplaza tres herramientas separadas:

  • nvm / pyenv / asdf → mise gestiona todos los runtimes en un solo lugar
  • npm scripts / Makefile → las tasks de mise son el runner estándar
  • dotenv / direnv → mise activa variables de entorno por directorio

Instalación

brew install mise

Activar en el shell (va en ~/.zprofile):

eval "$(mise activate zsh --shims)"

~/.zprofile se carga al abrir una terminal nueva (no en las ya abiertas). Después de editar este archivo, abre una terminal nueva para que tome efecto — o ejecuta exec zsh en el terminal actual.


Bondades clave

Activación automática por directorio

Al entrar a un directorio con mise.toml, mise activa las versiones declaradas sin ningún comando adicional. Al salir, las desactiva.

cd ~/Docker/proyecto-alpha
bun --version # 1.2.5 — del mise.toml del proyecto

cd ~/Docker/proyecto-beta
bun --version # 1.1.8 — diferente proyecto, diferente versión

cd ~
bun --version # 1.3.14 — del config global

Esto funciona mediante shims: mise intercepta los binarios y redirige a la versión correcta según el directorio. No requiere eval en cada directorio ni hooks de cd.

📄 Documentación: Dev Tools


mise-lock — reproducibilidad exacta entre máquinas

mise.lock fija las versiones resueltas exactas (con checksums y URLs) de todas las herramientas; se commitea al repo. Ojo: lockfile = true solo habilita que mise lea y escriba el lock — no lo crea. Hay que generarlo una vez con mise lock; después mise install/mise use/mise upgrade lo mantienen.

# ~/.config/mise/config.toml o mise.toml del proyecto
[settings]
lockfile = true # habilita el lock; el ARCHIVO se crea con `mise lock`
mise lock # crea mise.lock (una vez, al crear el repo)
mise lock --platform macos-arm64,linux-x64 # cubrir mac (dev) + linux (CI/Docker)
# mise.lock (commitear al repo)
[[tools.bun]]
version = "1.3.14"
backend = "core:bun"

Con el lockfile en git, mise install --yes en cualquier máquina instala exactamente la misma versión, sin drift entre desarrolladores. experimental no es necesario para el lockfile.

📄 Documentación: mise-lock


mise exec — ejecutar con versiones específicas sin activar el entorno

mise exec (o mise x) ejecuta un comando con las herramientas de mise activas, incluso desde contextos donde el entorno no está inicializado: hooks de git, scripts de CI, cron jobs.

# Ejecutar un comando con las versiones del mise.toml actual
mise exec -- bun run build
mise exec -- python script.py

# Abreviado
mise x -- taplo fmt mise.toml
mise x -- hadolint Dockerfile

# Con versión específica sin mise.toml
mise exec bun@1.2.5 -- bun test

Esto es especialmente útil en lefthook.yaml para garantizar que los hooks usen las versiones del proyecto aunque el shell no tenga el entorno activado:

# lefthook.yaml
pre-commit:
commands:
toml:
glob: '*.toml'
run: mise exec -- taplo fmt {staged_files}
hadolint:
glob: 'Dockerfile'
run: mise exec -- hadolint {staged_files}

📄 Documentación: mise exec


Tasks — runner de tareas integrado

mise incluye un runner de tareas que reemplaza npm run, Makefile y scripts de shell. Las tasks se declaran en mise.toml y son auto-documentadas.

# mise.toml
[tasks.setup]
# ⚠️ Una sola cadena con `&&`, NO un array. El hook `toml` compartido formatea con
# taplo usando `reorder_arrays=true`, que reordena alfabéticamente CUALQUIER array TOML
# al hacer commit — incluido este `run` — y rompería el orden de ejecución. Ver [[wiedii-configs]].
run = "mise install --yes && mise lock && pkg=$(find . -maxdepth 2 -name 'package.json' ! -path '*/node_modules/*' | head -1) && { [ -n "$pkg" ] && bun install --cwd "$(dirname "$pkg")" || true; }"
description = "Configura el entorno completo del proyecto"

[tasks.dev]
run = "bun run dev"
description = "Arranca el servidor de desarrollo"

[tasks.test]
run = "bun test"
description = "Ejecuta los tests"

[tasks.lint]
run = "bun eslint . --cache"
description = "Lint del código fuente"
mise run setup # configuración completa con un comando
mise run dev # servidor de desarrollo
mise tasks # lista todas las tasks disponibles con descripción

⚠️ Arrays en run vs. el hook toml compartido. El hook toml de wiedii-configs formatea con taplo usando reorder_arrays=true, que reordena alfabéticamente cualquier array TOML al hacer commit (y con stage_fixed re-stagea el cambio). Para tareas multi-paso donde el orden importa —como setup— usa una sola cadena con && en lugar de un array: una cadena no es un array y taplo no la toca, así el orden de ejecución queda garantizado. Para arrays donde el orden es irrelevante, el array está bien.

📄 Documentación: Tasks


mise trust — modelo de seguridad

mise no activa un mise.toml a menos que el desarrollador lo haya marcado explícitamente como confiable. Esto evita la ejecución automática de código malicioso al entrar en un directorio clonado.

mise trust # confiar en el mise.toml del directorio actual
mise trust --all # confiar en todos los mise.toml del sistema (⚠️ úsalo solo en máquinas personales)

El workflow estándar en Wiedii:

git clone git@gitlab.wiedii.co:<namespace>/proyecto.git
cd proyecto
mise trust # explícitamente confiar en el proyecto
mise run setup # ahora se puede ejecutar el setup

📄 Documentación: Trusted configs


Backends múltiples

mise instala herramientas desde múltiples fuentes. Antes de agregar cualquier herramienta, verificar su backend disponible en mise-versions.jdx.dev.

Core tools (runtimes del lenguaje)node, bun, python, go, ruby, rust, deno, java, swift, zig, elixir, erlang — van con su nombre corto, sin prefijo (core: es redundante). Para el resto de herramientas (CLIs/binarios), el prefijo es obligatorio y la prioridad es:

PrioridadBackendEjemploCuándo usarlo
aquaterraform, golangci-lintPreferido siempre. Registro curado de mise con checksums verificados.
npmmise use npm:aws-cdkCLIs publicadas en npm que no van en el package.json del proyecto.
pipxmise use pipx:ruffCLIs de Python que no van en pyproject.toml.
cargomise use cargo:taplo-cliCLIs Rust no disponibles en aqua.
asdfplugins heredadosSolo si ningún otro backend funciona.

Regla clave: herramientas que pertenecen al ecosistema del lenguaje van en su gestor nativo (prettierpackage.json, ruffpyproject.toml), no en mise. Excepción: CLIs de Go siempre van en mise.toml porque go.mod solo registra librerías importadas en código, nunca executables. Ver gestion-herramientas-brew-mise para el árbol de decisión completo y la tabla de ejemplos.

📄 Catálogo de herramientas y backends 📄 Documentación: Registry 📄 Documentación: Backends


Configuración estándar de Wiedii

Config global (~/.config/mise/config.toml)

[tools]
bun = "1.3.14"
node = "24.16.0"
pnpm = "11.6.0"
python = "3.14.6"
uv = "0.11.21"

[settings]
lockfile = true

Config de proyecto (mise.toml en la raíz del repo)

[tools]
bun = "1.3.14" # versión específica del proyecto — sobreescribe global
lefthook = "2.1.9"

[settings]
lockfile = true

[hooks]
# instala lefthook tras `mise install` (no en la task de setup); se salta en CI
postinstall = "[ -z "$CI" ] && lefthook install || true"

[tasks.setup]
# ⚠️ Una sola cadena con `&&`, NO un array. El hook `toml` compartido formatea con
# taplo usando `reorder_arrays=true`, que reordena alfabéticamente CUALQUIER array TOML
# al hacer commit — incluido este `run` — y rompería el orden de ejecución. Ver [[wiedii-configs]].
run = "mise install --yes && mise lock && pkg=$(find . -maxdepth 2 -name 'package.json' ! -path '*/node_modules/*' | head -1) && { [ -n "$pkg" ] && bun install --cwd "$(dirname "$pkg")" || true; }"
description = "Configura el entorno completo del proyecto"

[env] — variables privadas para herramientas Go del registro interno

Cuando el mise.toml declara una herramienta con backend go: desde el registro interno de Wiedii (gitlab.wiedii.co/... — el caso típico es wietoo, ver wietoo-cli), el bloque [env] del propio mise.toml debe declarar GOPRIVATE cubriendo ese host:

[env]
GOPRIVATE = "gitlab.wiedii.co/*" # wiedii-registry es un grupo interno, no público

[tools]
"go:gitlab.wiedii.co/wiedii-registry/wietoo-cli/cmd/wietoo" = "vX.Y.Z"

Sin GOPRIVATE, el backend go: (que por dentro corre go install) intenta el proxy y sumdb públicos, que no pueden resolver un módulo privado, y el setup falla. Declararlo en [env] — no con un go env -w manual — hace que con solo mise trust && mise run setup la variable quede activa para ese directorio, coherente con la filosofía de mise (sin pasos manuales).

Como además el grupo es interno, cada máquina necesita una sola vez el rewrite de Git para autenticarse por SSH en vez de HTTPS anónimo (esto es config de host, no del proyecto):

git config --global url."git@gitlab.wiedii.co:".insteadOf "https://gitlab.wiedii.co/"

Si mise run setup falla bajando wietoo con un error de red o autenticación y el [env].GOPRIVATE ya está presente, casi siempre falta este paso. Detalle completo (incluida la variante para CI) en modulos-go y wietoo-cli.


Comandos clave

# Gestión de versiones
# Para el config global, debes estar en el directorio correcto:
cd ~/.config/mise && mise install --yes # instalar runtimes globales
cd -

# Para instalar las herramientas del proyecto (desde la raíz del repo):
mise install --yes # instalar herramientas del mise.toml del proyecto

mise use bun@1.3.14 # agregar herramienta al mise.toml del proyecto
mise use --global bun@1.3.14 # agregar al config global
mise ls # listar herramientas activas en el directorio
mise ls --current # solo las herramientas activas ahora
mise outdated # ver qué herramientas tienen versión más nueva

# Ejecución
mise run setup # ejecutar task 'setup'
mise tasks # listar todas las tasks disponibles
mise exec -- <comando> # ejecutar comando con el entorno de mise activo

# Config y confianza
mise trust # confiar en el mise.toml actual
mise config # ver config efectivo del directorio actual

📄 Referencia completa de CLI


Troubleshooting rápido

mise run setup falla con "not trusted":

mise trust && mise run setup

Herramienta no se activa al entrar al directorio:

mise ls # verificar que está declarada en mise.toml
mise trust # verificar que el directorio está en trusted
eval "$(mise activate zsh)" # verificar que la activación está en el shell

Versión incorrecta (el global sobreescribe al proyecto):

# La activación de mise debe ir al FINAL de tu config de shell para tener máxima
# prioridad. En el setup estándar de Wiedii va en ~/.zprofile (ver configuracion-zsh):
tail -3 ~/.zprofile # debe terminar con la activación de mise / los shims en el PATH
# Si moviste la línea, recarga: exec zsh (en cada terminal abierta)

Conflicto con versión global:

mise ls --current # ver qué versión está activa y de dónde viene

Referencias