mise
repository·main·Indexed 12 days ago
https://github.com/jdx/miseA tool manager that prepares development environments by managing dev tools, environment variables, and tasks through a single mise.toml configuration file. Written in Rust, it provides tool management for runtimes like Node.js, Go, and Python, as well as a task runner and environment variable management.
What's inside mise
- mise plugins can access a set of built-in Lua modules to perform common operations. These modules are available in both backend plugins and tool plugins. They allow you to handle tasks like HTTP requests, JSON parsing, file system operations, and semantic versioning directly within your plugin logic.
What is mise and how does it work?
mainOverview
mise(pronounced "meez") is a development environment setup tool designed to provide a consistent way to set up and interact with projects regardless of the programming language used. It uses amise.tomlconfiguration file to manage project environments.Core Functionality
miseprovides three main categories of functionality:- Tool Management: Installs and manages development tools and runtimes (e.g.,
node,python,terraform). It allows you to specify different versions of these tools for different projects and supports hundreds of available tools via plugins. - Environment Variable Management: Manages environment variables (e.g.,
AWS_ACCESS_KEY_ID) that may vary between projects. It can also automatically activate tools like Python virtualenvs when you enter a project directory. - Task Running: Acts as a task runner to share common tasks within a project among developers and can execute tasks based on file changes.
- Tool Management: Installs and manages development tools and runtimes (e.g.,
Overview of mise oci commands
mainThe
mise ocisuite allows you to turn amise.tomlinto a container image with one OCI layer per installed tool. This architecture ensures that updating a single tool only invalidates its specific layer, maximizing cache reuse.Command Description mise oci buildProduces an OCI image layout on disk. mise oci runBuilds (or reuses) an image and runs a command inside it via podman/docker. mise oci pushBuilds (or reuses) an image and pushes it to a registry. Protect against SSH lockout during bootstrap
mainWhen running
mise bootstrapover SSH with an incoming policy ofdenyorreject, mise performs safety checks to prevent locking you out:- It checks the
SSH_CONNECTIONenvironment variable. - It verifies that at least one existing
incomingtcpallowrule covers both the connected peer address and the server port. - If these conditions aren't met, the application fails before applying changes.
Escape Hatch: If you are performing a deliberately out-of-band deployment and need to bypass this check, set
allow_lockout = truein your configuration.allow_lockout = true # Use to bypass SSH safety checks during deployment- It checks the
How mise manages development tools
mainmise is a tool manager that automates the installation, version management, and environment setup for programming language runtimes (like Node.js, Python, Ruby, Go) and other development tools.
Tool Resolution Flow
When you enter a directory or run a command, mise follows these steps:
- Configuration Discovery: Walks up the directory tree to find and merge configuration files (
mise.toml,.tool-versions, etc.). - Tool Resolution: Resolves version specs (e.g.,
node@latest) using registries. - Backend Selection: Chooses a backend (core, asdf, aqua, etc.) to handle the tool.
- Installation Check: Verifies if required versions are installed; installs missing ones automatically.
- Environment Setup: Configures
PATHand environment variables.
Configuration Hierarchy
Settings cascade from broad to specific:
~/.config/mise/config.toml(Global defaults)~/work/mise.toml(Work-specific)~/work/project/mise.toml(Project-specific overrides)~/work/project/.tool-versions(Legacy asdf compatibility)
- Configuration Discovery: Walks up the directory tree to find and merge configuration files (
Control task execution order
mainYou can manage the sequence and concurrency of tasks using
depends,wait_for, anddepends_post.Dependency Types
depends: Ensures the specified tasks run before the current task.wait_for: Does not add a dependency, but if the specified task is already running, the current task will wait for it to finish.depends_post: (Implicitly used for post-execution logic).
Complex Execution Flows
You can define a task that orchestrates other tasks in series or parallel using an array of task objects:
[tasks.one_by_one] run = [ { task = "example1" }, # Runs example1, waits for it to finish { tasks = ["example2", "example3"] }, # Runs example2 and example3 in parallel ][tasks.build] run = "echo 'build'" [tasks.test] run = "echo 'test'" depends = ["build"]Use `matching` and `matching_regex` for precise asset selection
mainIf a GitLab release contains multiple assets that autodetection cannot distinguish, use
matchingormatching_regexto narrow the selection.Important:
matchingandmatching_regexrefine the list of candidates after autodetection has already selected the correct OS and architecture. Ifasset_patternis also provided, it takes precedence andmatching/matching_regexare ignored.To install two different binaries from the same release, you must use distinct
tool_aliasentries so they reside in different install directories. Reusing the samegitlab:owner/repostring with different matching options will cause the second installation to overwrite the first.# Using matching to pick a specific binary from a multi-binary release "gitlab:owner/repo" = { version = "latest", matching = "mytool-cli" } # Using matching_regex for precise selection "gitlab:owner/repo" = { version = "latest", matching_regex = "^mytool-cli-" }Group file tasks into sub-directories
mainTasks placed in sub-directories of the default task folders are automatically prefixed with the directory name. This allows for logical grouping of related tasks.
Example structure:
mise-tasks ├── build └── test ├── _default ├── integration └── unitsResulting task names:
buildtest(fromtest/_default)test:integrationtest:units
Manage file snippets with Edit entries
mainEdit entries allow you to manage specific parts of a file without owning the whole file. They are keyed by
target_path/id.Blocks
A
blockis a multi-line snippet delimited by marker comments in the target file. The markers are named after the entry'sid.- Markers: The prefix is inferred from the file extension (e.g.,
#for shell,--for Lua,//for C-like). You can override this withcomment = "...". - Behavior: Applying a block replaces only the content between the markers or appends it if absent. Everything else in the file is untouched.
Lines
A
lineensures an exact single line exists in the file. It appends the line to the end if it is missing. It is idempotent and never modifies or removes other lines.Templates for Edits
To use a template for an edit entry, pair
sourcewithtemplate = "tera".[dotfiles] # A block in .zshrc "~/.zshrc/activate" = { block = 'eval "$(mise activate zsh)"' } # A multi-line block "~/.zshrc/aliases" = { block = ''' alias ll='ls -l' alias la='ls -la' ''' } # A single line in /etc/hosts "/etc/hosts/dev" = { line = "127.0.0.1 dev.local" } # A templated edit "~/.gitconfig/identity" = { source = "snippets/git-identity.tmpl", template = "tera" }- Markers: The prefix is inferred from the file extension (e.g.,
How Env Plugins declare cacheability
mainWhen developing environment plugins (vfox modules), you can control caching behavior by returning a configuration object from the
MiseEnvhook. To make a plugin cacheable and specify which files trigger an invalidation, return:{cacheable = true, watch_files = [...]}Create custom presets using mise tasks
mainYou can reduce boilerplate and automate project scaffolding by creating custom presets. Presets are implemented using mise tasks. By placing task scripts in
~/.config/mise/tasks/, you can define complex setup workflows that can be invoked from any directory.To create a preset, write a shell script and use special
#MISEdirectives to control the execution environment, such as setting the working directory (#MISE dir="{{cwd}}") or defining dependencies (#MISE depends=["preset:name"]).# Example of a preset task script #!/usr/bin/env bash #MISE dir="{{cwd}}" mise use python@latest mise config set env._.python.venv.path .venvUnderstand HTTP Backend caching behavior
mainThe HTTP backend uses an intelligent caching system to optimize disk usage and installation speed. Instead of storing files separately for every tool, mise downloads and extracts files into a central cache directory. Tool installations are then created as symlinks to this cached content.
Cache Location
Downloaded and extracted files are stored in
$MISE_CACHE_DIR/http-tarballs/. Default locations are:- Linux:
~/.cache/mise/http-tarballs/ - macOS:
~/Library/Caches/mise/http-tarballs/
Cache Key Generation
To ensure identical downloads are shared across different tools, cache keys are generated using:
- Blake3 hash of file content: Used when no checksum is provided.
- Extraction options: The
strip_componentsoption is included in the key because it changes the resulting directory structure.
Symlinked Installations
When a tool is installed via the HTTP backend, the installation directory is a symlink to the cached extracted content:
~/.local/share/mise/installs/http-my-tool/1.0.0 → ~/.cache/mise/http-tarballs/71f774.../extractedCache Metadata
Each cache entry contains a
metadata.jsonfile describing the content:{ "url": "https://example.com/releases/my-tool-v1.0.0.tar.gz", "checksum": "sha256:a1b2c3d4e5f6789...", "size": 1024000, "extracted_at": 1703001234, "platform": "macos-arm64" }- Linux: