Context
Modern projects depend on a plethora of tools: node, python, terraform, go, cloudflare-cli, etc. Managing these dependencies presents several challenges:
- Documentation Rot: READMEs instructing users to "install Python 3.11" inevitably go out of date or fail to specify patch versions, leading to "it works on my machine" issues.
- Inconsistent Environments: Developers and CI/CD agents need to run in the exact same environment.
- Task Sprawl: Scripts for building, testing, and deploying are often scattered across
package.json,Makefile, shell scripts, or GitHub Actions workflow files.
I need a tool that:
- Codifies the Environment: The code itself should document exactly what tools and versions are required.
- Standardizes Tasks: A single interface to run common tasks (
build,test,deploy) regardless of the underlying language or toolchain. - Simplifies CI/CD: Reduce CI configuration to "install environment -> run task".
- Manages Configuration: Uniform handling of
.envfiles and environment variables across tools.
Decision
I decided to use mise for both tool version management and task running.
Mise replaces tools like asdf, nvm, pyenv, and Make. It uses a TOML configuration file to define the exact versions of tools required and the tasks available in the project.
Consequences
Pros
- Code as Documentation: The
mise.tomlfile is the source of truth. Runningmise installguarantees the correct environment, eliminating stale setup docs. - Standardized Interface: I can swap out the implementation of a task (e.g., changing from
npm run buildtoturbo build) without changing the developer command (mise run build). - Monorepo Tasks: Supports monorepo patterns where tasks can be defined globally and overridden or composed at the directory level.
- Environment Management: Built-in
.envfile support with hierarchical overrides allows for clean separation of secrets and config. - CI/CD Simplification: Pipelines become generic. Instead of custom actions for every tool, the workflow is simply
mise install && mise run ci. - Power & Modernity: It offers features superior to
Make(better argument handling, parallel execution) andTaskfile(integrated tool management).
Cons
- Abstraction Layer: It adds an extra layer. Developers might run
mise run buildwithout knowing if it's invokingpnpm,cargo, or a shell script. - Complexity: It introduces another tool to the stack, whereas
Makeis available almost everywhere by default. - Too New: LLMs aren't familiar with it, it is not broadly adopted, so coding agents regularly ignore it and try to focus on using the underlying tools it's abstracting, resulting in an inconsistent experience.