Mise : un outil pour les gouverner tous
Il y a trois ans (wow, c’est loin, je ne m’y attendais pas), j’écrivais sur les version managers comme un moyen de faire cohabiter plusieurs versions d’un langage, SDK et framework. C’est encore d’actualité, et je le recommande toujours. Là aujourd’hui, j’ai envie de m’étendre un peu plus sur une possibilité que j’avais discrètement glissée dans mon post sans aller plus loin : et s’il existait un seul outil pour gérer tous les autres ?
La réponse est oui, et j’en utilise un depuis bientôt deux ans maintenant. Il s’appelle mise-en-place, ou mise pour les intimes. Au départ, je l’ai adopté pour une raison très simple : j’en avais marre de chercher un nouveau version manager pour chaque écosystème.
nvm pour Node.js. pyenv pour Python. fvm pour Flutter. rustup pour Rust. chruby pour Ruby. Un autre pour je ne sais quel SDK qui arrive sur un projet. Vous avez la musique. Chaque outil est souvent très bien dans son coin, mais l’ensemble finit par créer une petite fatigue. Rien de dramatique, on va s’en remettre, mais le genre de friction qui revient souvent.
Installer. Mettre à jour. Changer de version. Expliquer à un collègue quoi installer. Retrouver où la version est déclarée. Se souvenir si cette commande s’applique globalement ou seulement dans le projet. La promesse de mise est assez agréable : apprendre une seule façon de faire, puis l’appliquer aux autres d’outils.
Un version manager généraliste
mise se place dans la famille des gestionnaires de versions généralistes, comme asdf ou vfox. L’idée n’est donc pas de gérer uniquement Node.js, Ruby ou Python, mais de fournir une interface commune pour tout un ensemble de langages, runtimes, SDK et outils de développement.
Dans un projet, je peux vouloir Python 3.12, Node.js 22, Flutter 3.32, Terraform, Bun, ou encore un outil CLI dont l’équipe a besoin. Plutôt que d’empiler les gestionnaires spécialisés, je peux demander à mise de s’en occuper. Derrière, il sait s’appuyer sur plusieurs sources et backends selon les outils. Honnêtement, au quotidien, je n’ai pas besoin d’y penser. Et c’est plutôt bon signe.
Ce n’est pas le seul outil capable de faire ça. J’avais déjà repéré asdf dans mon ancien article sur les version manager, et vfox existe aussi dans le même esprit. Pourquoi j’ai choisi mise ? Parce qu’il m’a semblé rapide, actif côté communauté, très fourni en outils supportés, et parce qu’il ne s’arrête pas au simple rôle de version manager. Je reviendrais dessus juste après.
Mais avant, commençons par le commencement. Installer mise. (Vérifiez tout de même le site officiel si la méthode a changé entre temps) :
curl https://mise.run | sh
Si je veux installer Node.js globalement (tout mon PC), la commande ressemble à ça :
mise use -g node@26
Si je veux installer Python pour un projet (un dossier et ses enfants) :
mise use python@3.13
À partir de là, quand j’entre dans le dossier du projet, python pointe vers la bonne version. Je tape python, pas mise python, pas pyenv exec python, pas une commande enveloppée avec un préfixe qui me sort du geste naturel. C’est un détail, mais je trouve que ça compte. Quand je lance flutter test, j’ai envie d’écrire flutter test, pas de me rappeler que sur ce projet précis je dois écrire fvm flutter test.
Le fichier mise.toml
Là où mise devient vraiment intéressant, c’est avec le fichier mise.toml.
Au début, on peut le voir comme un simple équivalent plus généraliste des fichiers .ruby-version, .node-version, .tool-versions, etc. On déclare les outils et les versions attendues par le projet, puis on versionne ce fichier avec le code. Comme ça, toute l’équipe partage la même configuration.
Un exemple très simple pourrait ressembler à ça :
[tools]
node = "26"
python = "3.13"
Ce n’est pas spectaculaire, mais c’est très pratique. Le projet dit explicitement “pour travailler ici, voici les outils et versions attendues”. Le nouveau collègue qui arrive, la machine fraîchement réinstallée, le runner de CI, le moi du futur qui aura tout oublié… tout le monde lit la même chose.
C’est la fin des discussions du style :
- Tu es sur quelle version de Node ?
- Attends, je croyais qu’on était passé en 26 ?
- Ah non, sur cette branche il faut encore la version 25.
- Pourquoi ça marche chez toi et pas chez moi ?
Bon, je m’emballe, cette dernière question ne disparaît jamais totalement malheureusement. Ce serait trop beau. Mais on passe tout de même d’un réglage individuel en un élément de projet versionnée.
Bien plus qu’un version manager
La surprise, pour moi, c’est que le fichier mise.toml ne s’arrête pas aux outils. On peut aussi y déclarer des variables d’environnement, et même des tâches. C’est là que mise a commencé à dépasser, chez moi, le rôle du “truc qui gère les versions” et où je me suis dis que j’allais le garder.
Les variables d’environnement, c’est le genre de chose qui finit souvent dans un .env, parfois un fichier différent par outils, ou pire dans une note. Avec mise, on peut les ajouter dans la configuration du projet. Pas les secrets, évidemment. Mais les valeurs non sensibles, les chemins, les réglages utiles au développement, oui.
Et puis il y a les tâches. On peut définir des commandes nommées, un peu comme on le ferait avec un Makefile ou des scripts maison. Sauf qu’elles vivent dans le même fichier que la déclaration des outils.
Par exemple :
[tasks.setup]
run = "mise install && npm install"
[tasks.test]
run = "npm test"
Je simplifie volontairement, mais l’idée est là. Sur un projet, il suffit de taper mise setup et cette commande prépare ce qu’il faut. Elle installe les outils attendus et prépare le terrain. C’est le genre de petite attention qui rend un projet plus accueillant. (et encore une fois, plus “future-proof” avec notre mémoire)
J’ai commencé à le faire sur tout mes nouveaux projets. Je crée un mise.toml, je le source, et petit à petit j’y mets les commandes que je rejoue souvent. Pas besoin de se demander si c’est make init, npm run setup, ./scripts/bootstrap.sh ou autre chose. Pour moi, de plus en plus, c’est mise run setup.
Même pour ce blog, j’ai une tâche new pour préparer un nouveau post. Créer le dossier, créer un fichier avec un template de post, mettre la date, puis l’ouvrir dans VS Code. Rien de révolutionnaire, mais j’aime beaucoup écrire de petits scripts pour éviter de répéter les mêmes opérations - je suis un flemmard.
Je vous ai parlé des alias ? Je peux faire encore plus court en tapant seulement setup ou new. Et ça marche pour tout, pas seulement pour les tâches - ce sont simplement des alias après tout.
[shell_alias]
new = "mise run new"
Attendez, ce n’est pas fini. On peut aller plus loin avec des hooks : des commandes qui se lanceront à chaque fois qu’on entre/sort du projet, avant ou après une installation, ou même faire du watch ! Quand je vous disais que cet outil allait les gouverner tous. Mon précieux, mon mise.
Ce qui se passe derrière
Sans rentrer dans un tutoriel complet, ça vaut le coup de comprendre grossièrement comment mise s’intègre au terminal.
Le principe de base est assez classique : mise installe les outils dans un de ses dossiers, puis modifie dynamiquement le contenu du PATH. Quand je suis dans un dossier avec un mise.toml, l’environnement actif change, et la commande node, python ou flutter pointe vers la version déclarée.
C’est aussi pour ça que l’expérience reste très rapide. En fait, elle est même inchangée. On ne lance pas un gros proxy à chaque commande. Le shell sait directement où chercher les exécutables.
Il existe aussi un mode avec des shims si on en a besoin, c’est-à-dire des petits exécutables intermédiaires qui redirigent vers la bonne version. Selon les environnements ou IDE, ça peut être utile. J’ai dû passer par les shims pour l’extension Flutter de VS Code par exemple.
Je trouve cette partie intéressante parce qu’elle répond à une inquiétude que j’avais avec certains version managers : est-ce que je vais ralentir mon terminal ? C’était par exemple le cas avec nvm qui est long à démarrer, même si on ne l’utilise pas.
Bref
Au départ, je cherchais surtout un version manager généraliste. Je voulais arrêter d’accumuler un outil par langage. mise m’a donné ça : une manière commune d’installer, mettre à jour et changer de version. Et il est même allé là où je ne l’attendais pas avec les variables d’environnement et les tâches.
Aujourd’hui, je n’installe quasiment plus de langage ou de SDK à la main. Flutter ? Via mise. Python ? Via mise. Les outils autour d'Ansible dont je parlais récemment ? Via mise aussi.
Quand je démarre un projet, mon premier réflexe est de créer et compléter le mise.toml au fur et à mesure pour réduire les frictions. À force, ça devient moins un outil de gestion de versions qu’un petit chef d’orchestre pour mon environnement de développement.