12k
All articles

Introducción a mise, el gestor de versiones multilenguaje

Vea cómo mise gestiona versiones de Node y Python por proyecto, archivos de versión existentes, bloqueo de herramientas, variables de entorno y compilaciones en local y CI.

OpenReplay Team
OpenReplay Team
Introducción a mise, el gestor de versiones multilenguaje

mise es una única herramienta de línea de comandos que instala y cambia versiones de Node, Python, Ruby y otros runtimes por directorio, leyéndolas de un archivo mise.toml en la raíz del proyecto.

Si tu repositorio tiene un frontend con Vite y un script de Python que genera contenido antes del build, probablemente estés usando nvm y pyenv en paralelo y esperando que la shell de cada compañero de equipo coincida con la de CI. Normalmente alguna no coincide.

Para una comparativa de mise, nvm, pyenv, rustup y SDKMAN!, consulta 5 Version Managers Every Developer Should Know. Este artículo omite la lista de funcionalidades. En su lugar, toma un repositorio y lo sigue a través de cd, los archivos .nvmrc existentes, el primer clon de un compañero, CI, una tarea de build con dos runtimes y las variables de entorno.

Puntos clave

  • Con la activación en la shell, al entrar en un directorio que tiene un mise.toml se añaden al PATH los runtimes fijados de ese proyecto, y al salir se restauran las versiones anteriores.
  • mise ignora .nvmrc y .python-version a menos que los actives por herramienta con el ajuste idiomatic_version_file_enable_tools.
  • mise run carga por sí mismo las herramientas y el entorno del proyecto e instala por defecto las herramientas que falten, por lo que funciona en CI sin activación en la shell.
  • jdx/mise-action@v4 instala mise y las herramientas de mise.toml. Si hay un mise.lock en el repositorio, instala con --locked.
  • La tabla [env] es texto plano que se sube al repositorio. Sirve para configuración, no para secretos.

El proyecto: un frontend con Vite y un paso de build en Python

El repositorio de ejemplo, docs-preview, tiene dos runtimes, un archivo de configuración y un workflow:

docs-preview/
├── content/*.md
├── scripts/build_content.py
├── src/
├── package.json          # vite in devDependencies
├── mise.toml
└── .github/workflows/build.yml

El script de Python usa solo la biblioteca estándar. Convierte los archivos Markdown en JSON que el frontend importa:

# scripts/build_content.py
import json, os, pathlib

src = pathlib.Path(os.environ.get("CONTENT_DIR", "content"))
out = pathlib.Path("src/generated/content.json")
out.parent.mkdir(parents=True, exist_ok=True)

items = [{"slug": p.stem, "body": p.read_text(encoding="utf-8")}
         for p in sorted(src.glob("*.md"))]
out.write_text(json.dumps(items, indent=2), encoding="utf-8")
print(f"wrote {len(items)} items to {out}")

Este es el mise.toml completo. Las secciones posteriores hacen referencia a él:

[tools]
node = "24"
python = "3.14"

[settings]
lockfile = true

[env]
CONTENT_DIR = "content"
VITE_SITE_NAME = "Docs Preview"

[tasks.install]
description = "Install JS dependencies"
run = "npm ci"

[tasks."build:content"]
description = "Convert content files to JSON for the frontend"
run = "python scripts/build_content.py"

[tasks.build]
description = "Generate content, then build the Vite app"
depends = ["install", "build:content"]
run = "npx vite build"

La tabla [tools] usa prefijos de versión (Node 24 LTS, Python 3.14). El lockfile, que se explica más adelante, registra las versiones de parche exactas a las que se resuelven.

Qué ocurre al entrar y salir con cd

Con mise activado, al entrar en un directorio que contiene un mise.toml se añaden a tu PATH los runtimes fijados de ese proyecto. Al salir, se restauran las versiones que estuvieran activas antes. Una vez que mise activate está en el archivo de inicio de tu shell, mise cambia herramientas y variables de entorno cada vez que cambias de directorio.

cd ~
node --version        # whatever your system or nvm provides
cd ~/code/docs-preview
node --version        # v24.x from mise.toml
python3 --version     # Python 3.14.x
echo "$CONTENT_DIR"   # content

El momento en que mise cambia de versión depende de la shell. Según la documentación sobre shims, bash, zsh, fish y xonsh cambian en cuanto ejecutas cd. Otras shells esperan hasta que aparece el siguiente prompt.

Cuando una versión fijada aún no está instalada

En una máquina recién configurada, ejecuta mise install en el directorio del proyecto. Es la solución explícita y predecible. Las tareas también se encargan de ello: las tareas de mise se ejecutan con las herramientas y variables de entorno del proyecto, y el ajuste auto_install, activado por defecto, instala las herramientas configuradas que falten cuando llamas a mise run. Python requiere cuidado si dependes de los shims. La referencia de ajustes explica que un shim que no puede resolver una versión gestionada por mise (por ejemplo, cuando la autoinstalación está desactivada) recurre al primer programa con el mismo nombre que encuentre en otro lugar del PATH. En una herramienta que el sistema operativo también incluye, como python3, eso significa que tu versión fijada nunca se ejecuta y no recibes ningún error.

Para fijar una versión distinta solo en un terminal, usa mise shell node@<version>. Esto requiere una shell en la que mise ya esté activado.

Archivos .nvmrc y .python-version existentes

mise no lee .nvmrc ni .python-version a menos que lo actives para cada herramienta con idiomatic_version_file_enable_tools. Las FAQ de mise confirman que estos archivos de versión idiomáticos están desactivados por defecto. Ese comportamiento por defecto llegó con mise 2025.10.0. Para activarlo:

[settings]
idiomatic_version_file_enable_tools = ["node", "python"]

La documentación de configuración incluye package.json entre los archivos que mise lee para node, por lo que al activar node también puede tener en cuenta ese archivo. Para omitir un archivo concreto, añade un par tool:filename, como node:package.json, al ajuste idiomatic_version_file_disable_files.

Una vez que mise.toml fija ambos runtimes, conserva .nvmrc solo para los compañeros que aún usan nvm y asegúrate de que ambos archivos coincidan. Si necesitas repasar cómo trata nvm ese archivo, consulta las guías para cambiar de versión de Node con nvm en macOS, Linux y Windows.

Compañeros de equipo y CI

Un portátil y un runner de CI leen el mismo mise.toml, pero añaden las herramientas al PATH de formas distintas:

PortátilGitHub Actions
Herramientas en el PATHHook de activación en la shelljdx/mise-action instala mise y las herramientas fijadas
Origen de las versionesmise.toml + mise.lockLos mismos archivos
Comando de buildmise run buildmise run build

El primer clon de un compañero:

  1. Instala mise: curl https://mise.run | sh
  2. Añade eval "$(~/.local/bin/mise activate zsh)" (o la línea correspondiente a tu shell) a tu archivo rc de la shell.
  3. Revisa mise.toml y luego ejecuta mise install.
  4. Ejecuta mise run build.

El modelo de confianza de mise requiere atención, porque los archivos de configuración pueden ejecutar código. Según la guía de primeros pasos, fuera de CI y del modo paranoico, cualquier comando que actúe sobre el proyecto, como mise install, mise exec o mise run, confía automáticamente en la configuración activa. Así que revisa mise.toml antes de ejecutar alguno y usa mise trust cuando quieras confiar en una configuración de forma explícita.

Bloquea las versiones exactas. El lockfile, mise.lock, se crea con mise lock o mediante el ajuste lockfile = true mostrado antes. Súbelo al repositorio. Con mise install --locked, la falta de una entrada en el lockfile se convierte en un error, de modo que mise nunca elige una versión nueva sin avisar.

Workflow de CI:

# .github/workflows/build.yml
name: build
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: jdx/mise-action@v4
      - run: mise run build

El paso de mise-action instala mise y las herramientas de mise.toml, por lo que el workflow usa las mismas versiones que los desarrolladores en local. Por defecto ejecuta mise install (install: true) y almacena en caché las herramientas (cache: true). Cuando existe mise.lock, instala con --locked. También pasa ${{ github.token }} automáticamente. En los portátiles, definir GITHUB_TOKEN o MISE_GITHUB_TOKEN ayuda si las instalaciones alcanzan los límites de peticiones, como se describe en la página sobre tokens de GitHub.

Cuando algo falla, tres comandos ayudan a acotar el problema:

SíntomaComando
La activación o la instalación parecen incorrectasmise doctor
Parece aplicarse un archivo de configuración equivocadomise config ls
Se ha seleccionado una versión incorrectamise ls --current

Una tarea real: mise run build con dos runtimes

Una tarea definida en mise.toml se ejecuta con las herramientas fijadas del proyecto y las variables de [env] ya aplicadas. Eso significa que mise run build usa el mismo Node y el mismo Python en un portátil y en CI, incluso sin activación en la shell.

La clave depends hace que build espere hasta que todas las tareas que enumera hayan terminado, de modo que el paso de Python haya escrito src/generated/content.json antes de que Vite lo lea. Las tareas enumeradas pueden ejecutarse de forma concurrente. La documentación de tareas indica que los prerrequisitos pueden ejecutarse en paralelo y que su orden en depends no establece una secuencia. Aquí es seguro porque npm ci escribe en node_modules y el script de Python escribe en src/generated, así que ningún paso toca la salida del otro. Si en algún momento un paso consume la salida del otro, haz que dependa directamente de ese paso.

mise tasks          # lists install, build:content, build
mise run build      # npm ci + Python step, then vite build

La guía de ejecución de tareas establece un límite por defecto de ocho trabajos en paralelo.

Variables de entorno por proyecto con mise

Los valores de la tabla [env] son texto plano en un archivo que se sube al repositorio. El entorno de mise es gestión de configuración, no gestión de secretos. En el ejemplo, el script de Python lee CONTENT_DIR mediante os.environ, y el frontend lee import.meta.env.VITE_SITE_NAME.

El prefijo VITE_ hace tangible el riesgo de los valores en texto plano de [env]. La documentación de variables de entorno de Vite explica que cualquier variable que empiece por VITE_ acaba en el bundle del cliente, con su valor incrustado en el código en tiempo de build. Cualquier valor VITE_ en mise.toml es público en cuanto se publica el sitio.

Una variable de build que falte no hace fallar el build. Obtienes un bundle que llama a la URL equivocada. El session replay puede mostrarlo desde el lado del usuario: ves cómo las peticiones van a una URL base undefined y luego rastreas el problema hasta el entorno en el que se ejecutó el build.

¿Cuándo merece la pena mise?

Si un proyecto solo necesita Node, nvm y un .nvmrc ya cumplen su función, y mise es opcional. Las guías de nvm cubren bien esa configuración. Merece la pena adoptar mise cuando un mismo repositorio fija dos o más runtimes y CI tiene que coincidir con cada portátil. Para probarlo en un repositorio que ya tengas, añade un mise.toml con versiones fijadas en [tools], ejecuta mise lock, sube ambos archivos al repositorio y cambia el paso de build de tu CI a mise run build.

Preguntas frecuentes

¿Dónde debo guardar los secretos si mise.toml se sube al repositorio?

Guarda los secretos en un mise.local.toml incluido en .gitignore, o decláralos en mise.toml con required = true, lo que hace que mise compruebe que la variable está definida sin almacenar ningún valor. Añadir redact = true enmascara los valores en la salida capturada de las tareas, pero mise env sigue mostrándolos en texto plano. Para secretos que deban subirse al repositorio, mise puede descifrar archivos SOPS cifrados con age (una funcionalidad experimental) para mise exec, las tareas y la activación en la shell.

¿Lee mise los archivos .tool-versions de asdf?

Sí. A diferencia de .nvmrc, mise lee .tool-versions sin ningún ajuste adicional. En Unix también puede ejecutar plugins de shell de asdf, aunque no se garantiza que funcionen todos los comandos o plugins de asdf. Si mise.toml y .tool-versions en el mismo directorio declaran la misma herramienta, prevalece mise.toml. La documentación de mise desaconseja compartir directorios de instalación entre asdf y mise, así que ejecuta mise install después de hacer el cambio.

¿Por qué mi editor o mi script usan una versión de Node distinta a la de mi terminal?

Los editores, los git hooks y los planificadores de tareas a menudo no cargan tu archivo rc interactivo, por lo que el hook de activación de mise nunca se ejecuta. Para solucionarlo, añade mise activate zsh --shims (o la línea correspondiente a tu shell) a un perfil de inicio de sesión que lea tu editor, como ~/.zprofile, y mantén mise activate sin opciones en ~/.zshrc. Para los scripts, usa mise exec -- comando o mise run. El modo shims omite algunas funcionalidades de la activación, como la mayoría de los hooks.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.