v2026.10.10

jdx/misev2026.10.10Oct 14, 2026by mise-en-dev

Upgrading?

AI Summary

This release introduces a `skip_if` configuration for tasks, adds support for Snap packages and COPR repositories in bootstrap, and enables branch selection for `--adopt`. It also resolves several performance and stability issues with `mise dot pull` and fixes Windows-specific problems with executable resolution and npm installs.

Key Highlights

  • New `skip_if` task directive allows tasks to conditionally skip execution based on shell command exit status.
  • Bootstrap configuration now supports Snap packages and Fedora COPR repositories via new TOML sections.
  • The `mise bootstrap --adopt` command now supports selecting specific branches using a `ref` query parameter.
  • Significant performance improvements and bug fixes for `mise dot pull`, resolving infinite loops and stalled operations.
  • Windows support improved: `mise x` and shims now correctly resolve to original executables, and npm tools are automatically reinstalled if dependency links are missing.

Breaking Changes

  • On Windows, `experimental = true` now automatically enables the identity install layout for new installations. Existing installs remain unchanged, but the default behavior is altered for new setups.

New Features

  • Task `skip_if` configuration for conditional execution.
  • Snap packages support in bootstrap configuration.
  • COPR repository support in bootstrap configuration.
  • Branch selection for `mise bootstrap --adopt` command.
  • GitHub OAuth refresh token caching in Mac Secure Enclave with Touch ID.

Full Release Notes

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](https://github.com/jdx/mise/pull/14399)

  ```toml
  [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](https://github.com/jdx/mise/pull/14402)

  ```toml
  [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](https://github.com/jdx/mise/pull/14401)

  ```toml
  [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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/14413)

## Changed

- On Windows, `experimental = true` now turns on the [identity install layout](https://mise.jdx.dev/dev-tools/install-layout.html) 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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/14407), [#14415](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/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](https://github.com/jdx/mise/pull/14387) (@JamBalaya56562, @risu729)

## Documentation

- The configuration docs now explain how mise searches for config before listing the per-directory file names. [#14390](https://github.com/jdx/mise/pull/14390)
- The bootstrap overview and run order now include `[bootstrap.apt.sources]`. [#14396](https://github.com/jdx/mise/pull/14396)

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

## 💚 Sponsor mise

mise is built and maintained by [@jdx](https://github.com/jdx), an open source developer at [**entire.io**](https://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](https://jdx.dev/sponsors.html). Your support funds ongoing development and helps keep mise fast, free, and independent.

Related Repositories