github jdx/mise v2026.3.0
v2026.3.0: Smarter prepare, task-backed hooks, and per-task vars

9 hours ago

This release brings a major upgrade to mise prepare with content-hash freshness, dependency ordering, and better diagnostics. Hooks and watch files can now delegate to full mise tasks, and task vars gain monorepo inheritance and per-task overrides. Several lockfile and idiomatic version file parsing bugs are also fixed.

Highlights

  • mise prepare overhaul -- Freshness detection switches from mtime to blake3 content hashing (reliable across CI and clock skew), providers can declare dependencies on each other, a new --explain flag shows detailed diagnostics, and per-provider timeouts are now supported.
  • Task-backed hooks -- Hooks and watch_files can now reference mise tasks instead of inline scripts, gaining access to the full task system (deps, env, templating).
  • Per-task vars and monorepo vars inheritance -- Tasks can define their own vars that override config-level vars, and monorepo subdirectory vars are now properly inherited when running tasks from the root.

Added

  • Task references in hooks and watch_files -- Hooks can now use { task = "name" } syntax to run a mise task instead of an inline script. Mixed arrays of scripts and task references are supported. Task refs respect MISE_NO_HOOKS=1 and the full task system (deps, env, etc.). #8400 by @jdx

    [hooks]
    enter = { task = "setup" }
    
    [[watch_files]]
    patterns = ["uv.lock"]
    task = "uv-deps"
  • Per-task vars and monorepo vars inheritance -- Tasks can now define task-local vars that override config-level vars for that task. Monorepo subdirectory vars are also properly inherited when running tasks from the project root, matching how env already works. #8248 by @halms

    [vars]
    greeting = "hello"
    
    [tasks.test]
    run = 'echo {{vars.greeting}}'
    vars = { greeting = "hi" }   # overrides config-level var
  • Built-in git-submodule prepare provider -- A new built-in provider detects .gitmodules and runs git submodule update --init --recursive when submodule directories are stale. No configuration needed -- it activates automatically when .gitmodules exists. #8407 by @jdx

  • Blake3 content-hash freshness for prepare -- mise prepare now uses blake3 content hashing instead of mtime comparison to determine whether providers need to run. Hashes are persisted to .mise/prepare-state.toml. This is more reliable across CI, VCS operations, and clock skew scenarios. #8404 by @jdx

  • Human-readable stale reasons in prepare output -- Dry-run and status bar messages now explain why a provider would run, e.g. [dry-run] Would prepare: npm (node_modules does not exist) or prepare: codegen (schema.graphql changed) -- run 'mise prep'. #8408 by @jdx

  • mise prepare --explain <provider> diagnostics -- A new --explain flag shows detailed information about a specific provider: sources, outputs, auto status, command, and a fresh/stale verdict with reasons. Exits 0 if fresh, 1 if stale, useful for scripting. #8409 by @jdx

  • Per-provider timeout support for prepare -- Providers can now set a timeout in seconds. If the command exceeds the timeout it is killed. #8405 by @jdx

    [prepare.npm]
    timeout = 120  # kill after 2 minutes
  • Dependency ordering for prepare providers -- Providers can declare depends = ["other-provider"] to enforce execution ordering. Independent providers still run in parallel. Cycle detection, failure propagation, and unknown-dep warnings are all handled. #8401 by @jdx

    [prepare.ansible-galaxy]
    depends = ["uv"]
    run = "ansible-galaxy install -f requirements.yml"
    sources = ["requirements.yml"]
    outputs = [".galaxy-installed"]

Fixed

  • Idiomatic version files now ignore comments -- Files like .python-version, .node-version, .ruby-version, and .java-version now correctly strip # comments (both full-line and inline) and blank lines, preventing mise from treating comment text as version specifiers. #7682 by @iloveitaly

  • Generic parser used for idiomatic files -- Built-in idiomatic file parsers (e.g. for package.json and raw text files) are now used consistently, preventing unexpected behavior when plugins like vfox don't support certain file formats. #8171 by @risu729

  • Aqua bin_paths disk cache restored with proper invalidation -- The aqua bin_paths.msgpack.z cache removed in v2026.2.24 has been restored with fresh_file invalidation keyed on the install directory. This recovers the 7-11% performance regression on mise env and mise hook-env while keeping cache correctness. #8398 by @jdx

  • Lockfile no longer splits entries for precompiled settings -- mise lock with precompiled_flavor or similar settings configured no longer produces duplicate tool entries by splitting the host platform into a separate entry. #8396 by @jdx

  • Python lockfile respects precompiled settings -- mise lock now correctly uses precompiled_arch, precompiled_os, and precompiled_flavor settings when generating Python lock file entries, and precompiled_flavor is properly honored during installs. #8399 by @jdx

  • "v" prefix normalized in lockfile version matching -- --locked mode no longer fails when mise.toml specifies v1.2.3 but the lockfile stores 1.2.3 (or vice versa). #8413 by @jdx

  • Vfox no longer eagerly loads metadata -- Removed vfox's idiomatic_filenames() override that triggered plugin metadata loading for every config file check, and reordered detection logic so known patterns are checked first. Eliminates spurious [vfox] Getting metadata for yarn debug messages. #8397 by @jdx

  • Fixed infinite recursion with uv_venv_auto and uv shims -- When uv_venv_auto = "create|source" is set and a mise shim for uv exists on PATH, venv creation no longer enters infinite subprocess recursion. The fix excludes the mise shims directory from the uv binary search. #8402 by @halms

  • Improved git submodule parser for prepare -- The .gitmodules parser is now INI-section aware, only extracting path values from [submodule "..."] sections and ignoring comments. Freshness check errors now default to fresh rather than stale, preventing spurious warnings. #8412 by @jdx

Breaking Changes

  • The deprecated # mise ... file task header syntax has been removed as scheduled. Only #MISE / # [MISE] / //MISE / ::MISE headers are now recognized. If you have task files still using the old # mise headers, update them to use the new syntax. #8403 by @jdx

New Contributors

Full Changelog: v2026.2.24...v2026.3.0

Don't miss a new mise release

NewReleases is sending notifications on new releases.