mise-en-place

jdx/mise last check 654 releases today
Notes

The front-end to your dev env Pronounced "MEEZ ahn plahs"

Release notes
view on github
2026.10.10 · v2026.10.10: Task skip_if, snap and COPR in bootstrap, and dotfiles pull fixes · today

Tasks can now skip themselves with a skip_if check, and bootstrap gains Snap packages, Fedora COPR repositories, and branch selection for --adopt. This release also fixes several mise dot pull problems that could loop, stall, or leave sharing paused on long histories. On the Windows side, it fixes .mise-bins executables and npm installs restored from a cache.

Added

  • skip_if for tasks. Before a task runs, mise runs its skip_if shell command. If the command exits 0, mise skips the task and counts it as successful. Any other exit status runs the task as usual. #14399

    [tasks.setup]
    skip_if = "test -f .initialized"
    run = "touch .initialized"
    

    The check runs after depends and before confirm. It uses the task's directory, shell, environment, sandbox and timeout, and it supports Tera templates and task arguments. Its output is discarded and it gets no stdin. It does not receive the task's secrets. File tasks can set it with #MISE skip_if="...". mise run --force skips the check, --dry-run prints it without running it, and mise tasks info shows it. If the check can't start, times out, or is killed, the task fails.

  • Snap packages in bootstrap. On Linux, you can declare snaps in [bootstrap.packages] alongside apt and flatpak, with optional channel and classic, and state = "absent" to remove a snap. If a snap tracks a different channel than you declared, status shows it and apply moves it with snap refresh --channel. snapd can't install or hold a specific version, so apply and upgrade skip entries with a version pin and print a warning. #14402

    [bootstrap.packages]
    "snap:jq" = "latest"
    "snap:node" = { channel = "22/stable", classic = true }
    
  • COPR repositories with [bootstrap.dnf.repos]. You can declare a COPR next to the dnf: packages that come from it, instead of using a pre-packages hook. mise writes the same /etc/yum.repos.d file that dnf copr enable does. It does not need the copr plugin, so this also works on Fedora Atomic hosts that layer packages. The chroot is chosen from /etc/os-release (Fedora, EL, Amazon Linux). Without --yes, mise asks before enabling any COPR. mise never disables or removes repositories, but mise bootstrap unapply names any leftover files. #14401

    [bootstrap.dnf.repos]
    ghostty = { copr = "scottames/ghostty" }
    
    [bootstrap.packages]
    "dnf:ghostty" = "latest"
    
  • mise bootstrap --adopt <url>?ref=<branch> adopts a branch other than the default, either for global config or for a setup history. This also works with mise bootstrap remote. The ref must be a branch: tags, commits and missing branches are refused before anything is cloned. mise never switches an existing ~/.config/mise checkout to another branch, even with --update, so use git switch first. The docs now also explain how mise dot origin set relates to an adopted global config. #14400

  • GitHub OAuth refresh token in the Secure Enclave. On a Mac with Touch ID, set github.oauth_cache_secure_enclave = true to keep the native GitHub OAuth refresh token behind Touch ID instead of in plaintext in github-oauth-tokens.toml. Touch ID asks for a fingerprint only when the token needs refreshing. If you cancel the prompt, mise skips the refresh and keeps the cached access token. This needs the Developer ID-signed release build. Homebrew and source builds print a warning and keep the token in the cache file. #14413

Changed

  • On Windows, experimental = true now turns on the identity install layout by itself, which keeps deep npm, pipx and Java trees under the 260-character path limit. Only new installs use it. Existing installs stay where they are, and mise installs migrate can move them. To keep the old layout, set install_layout = "legacy" (or MISE_INSTALL_LAYOUT=legacy). Linux and macOS still need install_layout = "identity" set explicitly. #14392

Fixed

Dotfiles

  • Machines that share an origin and track an encrypted file no longer swap ciphertext back and forth forever. age encryption gives different ciphertext for the same content, so mise dot watch could publish commits endlessly without any real edits. Now mise keeps the ciphertext that history already has whenever it decrypts to the same content, mode and recipients. Machines that are already looping settle after one more sync. #14405
  • mise dot pull on long histories is much faster. The number of git processes no longer grows with the length of the history: in one test with 2,000 commits, a pull went from 137 s to under 6 s. #14407, #14415
  • When a pull's plan went out of date because another operation saved first, it was treated as a failed apply and paused sharing until someone ran mise dot pull by hand. Now, if nothing has been written yet, mise retries on the next attempt and the watcher keeps applying changes. #14414
  • After an interrupted history operation, mise dot pull --yes no longer fails with "local saved history changed since planning". The pull now recovers the interrupted operation before it plans. #14410
  • A file that already has the incoming version (content and mode) is no longer held as an unsaved edit or conflict that pauses sharing. Running mise dot pull --take-remote <path> again for a path an earlier pull already resolved no longer fails with "is not a conflict". #14411

Windows

  • mise x and shims now run the original executable instead of its copy in .mise-bins, for tools installed with aqua symlink_bins, github filter_bins, or packslip. Programs that look for DLLs or data next to their own executable, such as exiftool, now start correctly. Tools installed by older versions need mise install --force to get this. A shell from mise activate that finds the copy on PATH still runs the copy. #14397
  • npm tools installed with the built-in aube installer are reinstalled if their dependency links are missing, for example after a CI cache restore drops NTFS junctions. Before, mise reported them as installed and they failed at run time with ERR_MODULE_NOT_FOUND. #14418

Tools and installs

  • rust@nightly, mise ls-remote rust, and mise outdated/upgrade now read the nightly manifest from RUSTUP_DIST_SERVER, so a mirror such as panamax no longer needs access to static.rust-lang.org. If [env] sets RUSTUP_DIST_SERVER or RUSTUP_UPDATE_ROOT, mise also passes them to rustup-init and rustup toolchain install. #14384
  • With a global minimum_release_age, mise use --tool-option minimum_release_age=0s <tool> now installs the actual latest version instead of the version the global cutoff allows. #14398 (@halms)
  • Upgrading a global npm tool that mise lock --global locked with a dependency graph now regenerates the graph for the new version, including with --bump. Before, the upgrade dropped the graph and the next mise install --locked failed. #14419 (@altendky)
  • Reinstalling a packslip tool signed by a shared reusable workflow works again with its saved pin. In v2026.10.9, mise rejected the unchanged signer as "not a workflow of" the tool's repository. Signer, workflow or repository changes are still refused. #14408
  • Building Erlang from source now shows compiling with kerl while the build runs, instead of staying on verifying checksum. kerl's output now prints above the progress row instead of writing over it. #14391
  • mise prune now shows a progress line while it scans for unused versions, instead of printing nothing for what could be a long time. #14420
  • The JSON schema now rejects unknown keys in env._.python and its venv options, matching what mise already refused at load time. Editors now flag these mistakes. #14387 (@JamBalaya56562, @risu729)

Documentation

  • The configuration docs now explain how mise searches for config before listing the per-directory file names. #14390
  • The bootstrap overview and run order now include [bootstrap.apt.sources]. #14396

Full Changelog: https://github.com/jdx/mise/compare/v2026.10.9...v2026.10.10

💚 Sponsor mise

mise is built and maintained by @jdx, an open source developer at entire.io, the title sponsor of his open source work.

If mise saves you or your team time, please consider becoming an individual or company sponsor. Your support funds ongoing development and helps keep mise fast, free, and independent.