New settings let mise manage a tool without claiming its command names (shims.exclude) and approve non-registry npm dependencies (allow_exotic_deps), mise dot pull can decide every sharing conflict at once, and vfox plugin hooks gain cmd.stream plus a working cmd.exec timeout. On the fix side, mise run now survives Ctrl-C on Windows instead of orphaning cmd.exe, fish shells launched through shims start much faster with correct PATH order, and several task-resolution, lockfile, and Homebrew cask bugs are corrected.
Highlights
- Control over what mise puts on PATH and what it installs:
settings.shims.excludekeeps names likepythonresolving to the OS while mise still manages the tool;allow_exotic_depsapproves specific npm packages fetched from git or tarball URLs; exactpackslip:pins install during aminimum_release_agecooling window; andmise upgrade --bumpkeeps SemVer build metadata such as+k3s1. - Dotfiles sharing on a second machine:
mise dot pull --take-remote-all/--keep-local-allresolve all conflicts in one command, paths that cannot be decided are held rather than aborting the pass, and a directory sitting where a tracked file belongs is now reported as exactly that. - Task and shell reliability: Windows Ctrl-C shuts tasks down cleanly, a task's own name always beats another task's alias, glob expansions no longer drop file tasks, Bash completion of
ns:tasknames no longer duplicates the prefix, and fish startup throughmise exec/shims is no longer quadratic in the number of tools.
Added
-
shims:
settings.shims.exclude(envMISE_SHIMS_EXCLUDE) lists command names mise never creates shims for. The tool stays installed and version-qualified names likepython3.12still resolve through mise, but the excluded name resolves to whatever else is onPATH; existing shims for those names are removed on the nextmise reshim. Note that undermise activatewithout--shimsthe tool'sbindirectory still joinsPATH, and excludingpython3meanspython3 -m venvsilently uses the system interpreter. (#13266)[settings.shims] exclude = ["python", "python3", "pip", "pip3"]
-
npm:
allow_exotic_depsapproves dependencies that aube'sblockExoticSubdepsgate would otherwise block because they come from a git,file:, or direct tarball URL. List package names to exempt only those (the gate stays on for the rest of the graph), or settrueto exempt the whole graph. Applies to theaubeandaube_cliinstallers. Embedded-aube installs now also warn wheninstall_envis set, since it never reached the in-process installer. (#13231)[tools] "npm:@gmickel/gno" = { version = "2.3.0", allow_exotic_deps = ["xlsx"] }
-
dotfiles:
mise dot pull --take-remote-alland--keep-local-alldecide every pending conflict at once, with per-path--take-remote/--keep-localnaming exceptions. The two blanket flags are mutually exclusive, and paused-sync and adoption messages now point at them. (#13233)mise dot pull --take-remote-all --keep-local ~/.bashrc -
bootstrap: Every string value in
[bootstrap.linux.systemd.units]and[bootstrap.macos.launchd.agents]is rendered as a template before the unit file or plist is written, so{{ config_root }}/.envinenvironment_fileresolves to the declaring config's directory. Values without template syntax (including%hand$HOME) pass through untouched,exec()is rejected, and a unit whose template fails is skipped by name without blocking the others.[bootstrap.services]is not yet templated. (#13227) -
hooks: Each
MISE_INSTALLED_TOOLSentry passed topostinstallhooks now carriesrequested_version(for examplelatest,22, or an alias) alongside the resolvedversion, so a hook can tell a floating request from a pin. The field is always present; existing hooks readingname/versionare unaffected. (#13274) -
vfox plugins:
cmd.streamruns a command with stdin connected and stdout/stderr streamed to the terminal, for hooks that genuinely need input such as a login or license prompt; it pauses the progress renderer and holds the terminal exclusively while it runs.cmd.execandos.executenow detach stdin unless--rawis set, matching every other subprocess mise spawns, so a plugin that read stdin throughos.executeshould switch tocmd.stream. (#13261) -
vfox plugins: The
timeoutoption oncmd.exec(andcmd.stream) now works instead of being silently ignored. It takes seconds (fractions allowed); on expiry the spawned shell is killed and the call raises a catchable error. Only the shell mise spawned is killed, so background processes it started may keep running. (#13263)local ok, err = pcall(cmd.exec, "some-tool sync", { timeout = 30 })
Fixed
- task: On Windows, pressing Ctrl-C during
mise runno longer kills mise immediately and leaves acmd.exebehind stuck onTerminate batch job (Y/N)?. The first Ctrl-C lets running commands exit and stops scheduling new tasks; a second one takes the remaining process tree down. Tasks ended by the console are reported as interrupted instead of failing with exit code -1073741510. (#13226) - task: A task's own name now always wins over another task's alias. Previously a parent config's
teststask withalias = "test"could shadow atesttask in the current directory, depending on alphabetical order. Aliases still resolve wherever no task claims that name. (#13230) - task: Glob expansions such as
mise run '//...:lint'or'*:lint'no longer silently drop file tasks (mise-tasks/lint.sh) when a sibling package has an exact match. The same-package dedup that stopshelloandhello.shrunning twice is preserved. (#13277) - completions: Bash completion of namespaced tasks like
update:deps:no<TAB>no longer producesupdate:deps:update:deps:no-cooldown. Reinstall the script withmise completion bash --installif yours predates the prefix-aware wrapper. (#13276) - exec: Launching fish through
mise execor a shim emitted onefish_add_pathper directory, which made startup quadratic (over 1s with ~80 tools) and reversed mise's PATH order relative to bash. A single batched call restores both. (#13235) - dotfiles: A blanket
--take-remote-all/--keep-local-allno longer aborts the whole pass when one path cannot be decided (a directory on the live side, or unsaved local changes under--keep-local-all). Decisions for the other conflicts are recorded, and the error names the held paths so fixing just those finishes the setup. (#13239, #13242) - dotfiles: A directory or unreadable path where the repository has a file is now reported by
mise dot conflicts,mise dot status, andmise doctoras exactly that, with advice to move it aside, instead of as a "changed type" conflict that--take-remote/--keep-localcannot resolve. Git or process failures while reading a live file now stop the sync with their own error instead of posing as a conflict. (#13249) - upgrade:
mise upgrade --bumppreserves SemVer build metadata when rewriting a pin, so k3s bumps to1.37.0+k3s1rather than a nonexistent1.37.0, and Temurin keeps its+7build number. Coarser pins like1.36still bump to1.37. (#13258) - packslip: An exactly pinned version (for example
"packslip:github.com/jdx/hk" = "2.0.1") now installs and locks while still inside itsminimum_release_agewindow, as the setting documents. Fuzzy requests such as"2"orlateststill wait out the cutoff. (#13251) - install:
MISE_LOCKED=1 mise install <tool>no longer warns about unrelated (often global) tools missing from the lockfile; installing the requested tool or a baremise installstill fails if that tool is not locked. (#13259 by @jamescassell) - pypi:
mise lockno longer fails when awith/exposerequirement is pinned to a release needing a newer Python than the tool itself (e.g.mkdocs1.6.1 withmkdocstrings==1.0.6). The sidecar'srequires-pythonis now intersected across every pinned requirement; unpinned requirements and pins behind an interpreter marker leave the range alone. Existing lockfiles remain valid. (#13252) - aqua: With
minimum_release_ageset, the latest release no longer falls back to an older version when the hosted version list lags GitHub. The release date from the/releases/latestresponse mise already fetched is used directly, with no extra requests. (#13228) - backend: Tools whose registry entry splits across backends at a version boundary (like
hk) now list versions from the backend that actually resolves, somise ls-remote hk@1.57andmise latest hk@1.57return1.57.0instead of nothing. Also covers backends promoted byMISE_DISABLE_BACKENDS, platform-scoped entries, and lockfile pins. (#13238) - http: GitHub answers an exhausted rate limit with 403 rather than 429, so mise never retried it. A 403 carrying
x-ratelimit-remaining: 0orretry-afteris now retried like a 429 underhttp_retries; a 403 with quota remaining is still treated as a refusal. Default backoff (~5s total) will not outlast a long reset, but brief contention no longer fails an install outright. (#13256) - skills:
mise skills lsandmise skills syncnow warn when a packslip declares a skill the install does not hold, with the reason (skills.fetchoff,packslip.execoff, or a failed download), instead of looking identical to "no skills declared". After an install withskills.auto_syncoff, a one-time hint points atmise skills sync.--jsonoutput is unchanged. (#13275) - brew:
adoptis now honored for casks named on the command line (mise bootstrap packages apply brew-cask:menuwhere) and for tap-qualified names and aliases likebrew-cask:homebrew/cask/firefox, so existing app bundles are adopted rather than replaced and macOS keeps their Privacy & Security grants. (#13262) - brew: Tap formulae declaring requirement symbols such as
depends_on :macosno longer makebootstrap packagestry to fetch a formula namedmacosand abort the whole run with a 404. (#13240 by @waynehoover) - brew: Tap cask metadata evaluation now understands
appdirandHOMEBREW_PREFIXinterpolation, and casks whose app bundle sits in a nested archive directory (app "nested/Example.app") install asExample.appinstead of being rejected as a relative target; duplicate app targets are rejected before anything is downloaded. (#13138 by @Guria, #13199 and #13200 by @soodoh) - bootstrap: Selecting a Ruby to evaluate third-party Homebrew taps skips mise shims, which the metadata sandbox could not load, so package bootstrap no longer fails when Ruby is installed through mise. (#13198 by @jacobbednarz)
Documentation
- The dotfiles history guide now explains encryption recipients (SSH keys,
age-keygen, recovery keys) and warns that passphrase-protected SSH keys and plugin-only recipients cannot decrypt in the background; the setup guide covers adopting onto a machine that already has the files and using non-GitHub Git hosts. (#13232) - The PyPI backend's locking limitations now point at the lockable
with,expose, anddependency_prereleasesoptions. (#13222)
New Contributors
- @waynehoover made their first contribution in #13240
Full Changelog: v2026.9.9...v2026.9.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.