This release turns mise bootstrap into a full declarative host-provisioning system: alongside packages, mise can now converge privileged files, Linux users and groups, systemd services, Docker Compose projects, and firewall rules — all with plan/apply/status workflows, secret handling, and the ability to run over SSH against remote hosts. It also makes Ruby's ruby.compile=false a strict precompiled-only mode and lands a batch of install and lockfile fixes.
Highlights
mise bootstrapgains a Terraform-style declarative model. A newmise bootstrap planpreviews changes with table or JSON output and detailed exit codes, and each resource type has its ownapply/statuscommands that converge only when something actually differs.- Bootstrap can now provision far more than tools and packages: privileged files and directories, Linux accounts, systemd services, Compose projects, and host firewall rules, with dependency ordering, fail-closed safety checks, and secret inputs sourced from environment variables (never stored in config).
- The same bootstrap project can be applied to remote machines over SSH via
mise bootstrap remote, including automatic detection of the target's OS/arch/libc and signature-verified download of the matching mise binary.
Added
- bootstrap: declarative resource plans.
mise bootstrap planpreviews what bootstrap would change before applying, with table or--jsonoutput and optional--detailed-exitcode(0 = no changes, 2 = changes, 1 = error). Resources have stable identities, dependency graphs, and validation for duplicates, missing dependencies, and cycles. (#11669 by @jdx) - bootstrap: manage privileged files and directories via
[bootstrap.files]and[bootstrap.directories], with content (inline or from a source), ownership, mode, and explicitpresent/absentstate. Writes are atomic, removal is opt-in (and requiresrecursive = truefor non-empty directories), and privileged work runs through hidden helpers that never expose file content in argv or logs. (#11674 by @jdx) - bootstrap: secret inputs for managed files.
[bootstrap.secrets]references sensitive values through environment variables so nothing is stored in config, and managed files withtemplate = truecan render them via{{ secret(name="...") }}.mise bootstrap secrets statusreports availability without revealing values, and--prompt-secretsprompts securely for anything missing. (#11680 by @jdx) - bootstrap: manage Linux users and groups via
[bootstrap.users]and[bootstrap.groups], with create/update/remove, supplementary groups, home handling, and explicitstate = "absent". Accounts converge before the files that reference them, and UID/GID collisions fail closed. (#11681 by @jdx) - bootstrap: manage Linux systemd services via
[bootstrap.services]for running/stopped, enabled/disabled, and masked state. Managed files and directories can setnotifyto triggerreload,restart, orreload_or_restarthandlers, but only after a real file change. (#11688 by @jdx) - bootstrap: manage Docker Compose projects via
[bootstrap.compose]for running, stopped, and absent states, with pull/build/recreate/wait policies, one-shot services, orphan/volume/image removal, and explicit dependencies. Convergence compares live container runtime and health to the rendered Compose model (Compose v2 only). (#11689 by @jdx) - bootstrap: manage Linux host firewall rules via
[bootstrap.linux.firewall]with nftables, firewalld, and UFW backends (backend = "auto"). Includes SSH-lockout protection (default-deny requires a covering allow rule orallow_lockout = true), drift detection, and preservation of undeclared rules unlessexclusiveis set. (#11694 by @jdx) - bootstrap: run bootstrap over SSH with
mise bootstrap remote, targeting a named[bootstrap.remote.hosts]inventory or ad-hocuser@hosttargets. mise archives and stages your project, provisions a compatible mise binary on the host, runs bootstrap with forwarded flags, and cleans up staging afterward. (#11690 by @jdx) - bootstrap: remote provisioning now detects each target's OS, architecture, and Linux libc (glibc vs musl) and, when the local binary is not compatible, downloads the matching raw executable for the same release from GitHub with minisign-verified checksums. Custom or debug builds fail closed and require an explicit
mise_bin,remote_mise, orbootstrap_command. (#11693 by @jdx)
Changed
- ruby:
ruby.compile = falseis now a strict precompiled-only mode, matchingpython.compile. Installs error withno precompiled ruby foundinstead of silently falling back to ruby-build, and version listings (mise ls-remote ruby, fuzzy resolution) are filtered to versions that actually have a precompiled binary for your platform. Previouslyfalsewas a no-op after precompiled binaries became the default in 2026.8.0. Unset andcompile = trueare unchanged; Windows is unaffected. (#11710 by @jdx) - task: workspace task inference is now opt-in per provider via
task.auto_infer(e.g.task.auto_infer = ["node"]) instead of running whenever experimental features are enabled. Explicit mise tasks always take precedence over inferred package scripts on name and alias collisions. (#11706 by @jdx)
Fixed
- brew:
:any_skip_relocationbottles no longer leave unresolved@@HOMEBREW_*@@placeholders in scripts and config files. That tag now only skips binary linkage relocation while text placeholders are still replaced. (#11665 by @jdx) - brew-cask: detect extensionless DMG downloads (such as Raycast) by their UDIF trailer instead of treating them as raw executables and failing to find the app bundle. (#11692 by @jacobbednarz)
- lock:
mise lock --bumpnow errors instead of writing an incomplete lockfile when a version bump would drop platform coverage that the previous locked version had. Best-effort skips are retained for platforms a tool never supported. (#11664 by @jdx) - pipx: release-age gating now uses PyPI's precise RFC3339
upload_time_iso_8601timestamp instead of the timezone-naiveupload_time, which previously made freshly released packages appear up to ~24h younger and over-gated them underminimum_release_age. (#11662 by @Guria) - pacman:
pacman -Qis now parsed underLC_ALL=Cso missing-package detection works in non-English locales; previously[bootstrap.packages]could bail on a translated "was not found" message. (#11673 by @rarandeyo) - sync: clear stale
incompletemarkers when an external link (from uv, nvm, pyenv, nodenv, or Homebrew) is confirmed healthy, somise whereno longer treats a working external version as incomplete after an interrupted install. (#11172 by @risu729) - completions: an explicit
--no longer hijacks task argument completion after usage v5.mise run <task> -- <TAB>again offers the task's declared choices instead of falling back to filenames, while still forwarding extra arguments. (#11711 by @jdx) - registry: shim auto-install uses new declared
binsmetadata to pick the correct provider before falling back to incidental executables, fixing cases where invoking thenpmshim could run Node's bundled npm instead of the configured npm version. (#11666, #11671, #11676, #11677, #11678 by @jdx)
New Contributors
- @jacobbednarz made their first contribution in #11692
- @rarandeyo made their first contribution in #11673
Full Changelog: v2026.8.1...v2026.8.2
💚 Sponsor mise
mise is maintained by @jdx, an open source developer for entire.io, the title sponsor of the jdx.dev open source tools. Development is funded by sponsors.
If mise saves you or your team time, please consider sponsoring at jdx.dev. Individual and company sponsorships keep mise fast, free, and independent.