mise 2026.9.4 turns machine setup into a portable project declaration
The latest mise release adds a built-in Nix package manager, environment-aware host packages, man pages for managed tools, and safer cross-platform locking. It is useful, but it also makes mise configuration powerful enough to deserve a careful review.
A version manager normally answers a narrow question: which Node, Python, Ruby, Go, or Rust version should this project use? mise has been answering a wider one for some time. It can manage tool versions, environment variables, tasks, repositories, dotfiles, services, and parts of a workstation setup from configuration checked into Git. The latest release pushes that boundary further.

Version 2026.9.4 adds Nix as a built-in bootstrap package manager, lets package declarations depend on an active mise environment, allows Packslip-managed tools to install man pages, and improves locking and platform selection. The release landed on September 9 and is the most interesting recent mise update because it changes the relationship between a project configuration and the host machine around it.
That distinction matters. A project can now describe more of the software it expects to find outside its language runtimes, while still handing package installation to the native manager already used by the machine. The result is potentially cleaner onboarding for teams with mixed macOS and Linux systems. It is not, however, a universal replacement for Nix, a container, or a fully reproducible operating-system definition.
What changed in mise 2026.9.4
The release has four changes worth separating. The headline feature is the new nix: backend under [bootstrap.packages]. A configuration can declare entries such as:
[bootstrap.packages]
"nix:ripgrep" = "latest"
"nix:jq" = "latest"
"nix:python3Packages.pip" = "latest"
Running mise bootstrap packages apply installs those packages into the user’s ordinary Nix profile. mise does not create shims for them, does not take ownership of the Nix store, and does not invoke sudo for this backend. Nix remains responsible for its profiles, registries, substituters, trusted keys, caches, and rollback model.
The second change is an env selector for bootstrap package entries. A package can be active only in one or more named mise environments:
[bootstrap.packages]
"brew:postgresql" = { version = "latest", env = ["dev", "test"] }
"apt:clang" = { version = "latest", env = "native" }
The selector is evaluated against the environment activated with -E or MISE_ENV. If an entry also has an os selector, both conditions must match. A developer working in the dev environment can receive PostgreSQL, while a lighter documentation or production-like environment does not activate it. The declaration stays in configuration even when the environment is inactive, and mise protects it from pruning.
The third change concerns Packslip, mise’s signed release-artifact path for tools. Packslip-installed versions can now include static man-page resources, alongside shell completions and agent skills. When such a tool is active, mise adds its man-page root to MANPATH while preserving system and caller-defined paths. Existing installations need to be reinstalled before their newly declared man pages appear.
The fourth is a smaller but practical task-runner change. task.quiet, or the MISE_TASK_QUIET environment variable, suppresses mise’s own task prefixes, status messages, and command-echo headers without hiding output produced by the task itself. The older output = "quiet" mode is deprecated and scheduled for removal in 2027.9.3.
There is also a substantial group of correctness fixes. They cover lazy tools with lazy dependencies, ARM architecture resolution, selection of release artifacts when no native binary exists, Homebrew hard-linked Mach-O signing, Windows shim names, glibc compatibility, and platform-aware lock files. The release also improves dotfiles history indexing by reconstructing metadata in-process rather than spawning Git for every checkpoint. The maintainer reports that an 80-checkpoint, 44-file test case fell from roughly 26–28 seconds to under one second.
The useful idea is not “Nix through mise”
It would be easy to describe the release as a Nix integration and stop there. That misses the more useful design decision. mise is trying to provide one declarative surface for several kinds of dependency without pretending that all of them have identical semantics.
A language runtime belongs naturally in a project tool definition. A compiler library, system header, command-line utility, or database server often belongs to the host package manager. A Nix package belongs to a Nix profile or NixOS configuration. Before 2026.9.4, a team that wanted to describe these layers in one bootstrap flow had to write separate instructions or use a collection of package-specific scripts. The new backend gives the project a common declaration while leaving the actual ownership with Nix.
That separation is visible in the commands. mise bootstrap packages use records a declaration. mise bootstrap packages apply installs missing items. mise bootstrap packages status reports what is present, missing, unavailable, or skipped. mise bootstrap packages upgrade is the explicit update operation. Applying a declaration whose value is latest does not necessarily update an already installed package from a moving source. This is a sensible distinction: onboarding should converge missing state, not silently upgrade a workstation every time a developer enters a repository.
The Nix backend also has an export path for NixOS. A team can record declarations without installing them:
mise bootstrap packages use --no-install nix:ripgrep nix:jq
mise bootstrap packages export --format nix > packages.nix
The generated module can then be imported by a NixOS configuration. In that workflow, NixOS owns evaluation, package selection, overlays, system activation, and rollback. mise is acting as a convenient authoring and translation layer, not as a second system manager.
That is an important boundary. If a project uses mise bootstrap packages apply for a nix: declaration, the package goes into the user profile. If the same intent is meant to become part of a NixOS system configuration, the safer workflow is to use --no-install, export the module, review it, and rebuild through the existing NixOS process. Those two paths are related but not interchangeable.
Environment selectors solve a real team problem
The env selector is likely to matter more to ordinary teams than the Nix backend. Many repositories have multiple operating modes but only one setup document. A frontend project may need Node and a browser toolchain in every environment, PostgreSQL for integration tests, and an image-processing library only for a native build. A monorepo may have a small default environment for editing, a test environment with databases and browsers, and a release environment with signing utilities.
Without selectors, the setup file tends to choose between two bad options. It can install every possible dependency on every machine, making the default environment slow and noisy, or it can split setup into scripts that drift as platforms and teams change. Conditional declarations make the intent visible in one place.
The feature is deliberately narrower than arbitrary configuration logic. A package can be selected by operating system or mise environment; it is not a general-purpose programming language for package installation. The os and env conditions are combined rather than treated as alternatives. A macOS-only package in the native environment will remain inactive on Linux even if the environment name matches.
That predictability helps with review. A reviewer can see that a package is restricted to macos, linux/x64, dev, or test without evaluating an opaque shell script. It also makes status output more meaningful. An unavailable package manager on the current host should not automatically be interpreted as proof that the project is correctly provisioned; the documentation warns that skipped declarations need separate inspection.
There is a subtle lifecycle issue. Inactive environment packages remain declared and are protected from pruning. That is the safer default, because switching temporarily to a smaller environment should not make a later environment lose its tools. It also means a user who expects environment switching to reclaim disk space will need an explicit, manager-scoped cleanup strategy. Declarative presence and local disk minimization are different goals.
Man pages make managed tools feel less like downloaded binaries
Tool managers often focus on putting executables on PATH. That is enough for a quick command, but it is a poor fit for mature utilities whose documentation, examples, and operational details live in man pages. The new Packslip resource support lets a packaged tool ship those pages as part of its managed version.
The implementation is intentionally scoped. mise adds man roots for Packslip-backed tool versions and keeps the caller’s original MANPATH in the environment-cache identity. That avoids reusing a cached process built for a different caller’s documentation path. A user upgrading to 2026.9.4 should not assume every existing installation gains pages automatically; reinstalling the relevant tool is required.
This is a small change with a useful effect on onboarding. A repository can pin a tool and make tool --help and man tool refer to the same managed version. It is especially helpful for command-line infrastructure tools whose behavior differs significantly between releases. The feature does not turn every arbitrary binary into a fully packaged operating-system component, and system man-page conventions still vary across platforms.
The lock and artifact fixes deserve attention
The release’s packaging fixes are less visible than Nix support but more relevant to CI. mise lock --platform now verifies signed release manifests and records the URL, checksum, size, and signer for each requested target. That matters when a lock file is created on one machine and consumed on another. A lock file that identifies only a version but not the exact artifact leaves too much room for platform-specific resolution to change underneath it.
Artifact selection also avoids falling back to a generic source.tar.gz when the registry has no published binary for the host. That is a better failure mode than downloading source as though it were a runnable release. On glibc Linux, the selector now considers an artifact’s minimum glibc requirement and can choose a matching static musl build when one exists. This does not guarantee compatibility: native libraries, kernel features, CPU instructions, and runtime assumptions can still matter. It simply makes one common incompatibility visible to the resolver.
The Windows fix is similarly concrete. Packslip links now use the correct .exe filename for Windows while Unix systems retain extensionless shim names. The Homebrew fix addresses a more surprising failure: hard-linked Mach-O executables could be installed successfully but later killed by macOS after signing did not cover every alias. These are the kinds of defects that rarely appear in a feature announcement yet determine whether a version manager can be trusted in a mixed fleet.
A careful first test
The right way to evaluate this release is to start with a disposable repository and a dry run. The official bootstrap documentation recommends reviewing configuration and running mise bootstrap --dry-run before applying it. The same habit is appropriate for package-specific operations. A minimal experiment might declare one tool, one Nix package, and one environment-restricted host package.
[tools]
node = "22"
[env]
_.python.venv = { path = ".venv", create = true }
[bootstrap.packages]
"nix:jq" = "latest"
"brew:postgresql" = { version = "latest", os = "macos", env = ["test"] }
"apt:postgresql" = { version = "latest", os = "linux", env = ["test"] }
Review the output for the default environment, then for the test environment. Confirm that the package manager commands are the ones you expect, that the host package is not active under the wrong operating system, and that the Nix declaration resolves through the registry you intend to use. For a project committed to Git, the configuration itself should be reviewed like code. It can install packages, change shell activation, create services, write files, and run hooks.
A reasonable sequence is:
mise trust
mise bootstrap packages status
mise bootstrap --dry-run
mise -E test bootstrap --dry-run
mise bootstrap packages apply --dry-run
Only after the output is understandable should a developer apply it. In CI, mise bootstrap --yes is available for unattended operation, but the non-interactive flag removes a confirmation step; it does not make an untrusted configuration safe. Pin versions or source revisions where repeatability matters, and keep CI lock files under review.
For Nix specifically, the official documentation requires Nix 2.24 or newer with nix-command and flakes enabled, and modern nix profile support. The shorthand nix:ripgrep resolves through the machine’s nixpkgs registry. The latest value means whatever that source currently supplies; it is not a lock. If the build must be recoverable later, use a revision-pinned source or a pinned registry entry. A package-version pin such as nix:ripgrep@14 is not supported by this backend.
The documentation also emphasizes that mise does not initialize or migrate a legacy Nix profile. If the machine reports an old nix-env profile format, that is a Nix administration problem to solve separately. The tool does not delete or silently convert it, which is a good safety property but can surprise users expecting a one-command migration.
What it does not replace
mise 2026.9.4 is a strong fit when the problem is coordination across existing tools. It is less compelling when the central requirement is a hermetic build or an immutable system. A Nix flake can pin inputs and describe a development shell with deeper control over dependency graphs and evaluation. devenv builds a developer-focused layer on top of Nix, including services, tasks, language support, and lock files. A container or devcontainer may provide a stronger boundary for CI and onboarding.
The comparison with asdf is also useful. asdf is primarily a multi-runtime version manager with a plugin system and a per-project .tool-versions file. It is a simpler choice for teams that need consistent language runtimes and automatic switching but do not want a broader machine bootstrap model. direnv addresses yet another part of the problem: loading environment changes when entering a directory. It can be paired with mise, Nix, or other environment producers.
The choice should follow the problem rather than the number of supported integrations. Use mise when a repository benefits from a single configuration for runtimes, tasks, environment variables, and carefully scoped host setup. Use native Nix when reproducibility and package-graph control are the primary requirements. Use devenv when a team wants a Nix-based development environment with higher-level service and workflow configuration. Use asdf when runtime version management is enough. Use direnv when automatic environment activation is the main missing piece. These tools can coexist, but overlapping ownership of PATH, language versions, and shell hooks creates confusing failures.
Security and trust boundaries
The release is open source and the repository is MIT-licensed, with a published security policy. The signed release tag and Packslip manifest verification are useful supply-chain signals, but neither eliminates the risks of the configuration being executed. A signed mise binary can faithfully apply a malicious mise.toml; signature verification proves where an artifact came from, not that a repository’s requested package, hook, service, or file change is appropriate for your machine.
Bootstrap is explicitly capable of destructive actions. The command can install packages, alter activation files, manage services, update repositories, write dotfiles, and run tasks. That is why the dry-run and trust steps matter. Do not automatically trust a repository merely because it is public or because its configuration is short. Read hooks, inspect remote URLs, check package names, and pay attention to commands that use elevated privileges or modify shell startup.
Nix introduces its own trust decisions. Registries, binary caches, substituters, trusted public keys, and flake inputs affect what is downloaded and built. The mise integration uses the existing Nix configuration rather than creating a separate trust model. That is convenient, but it means the security review cannot stop at the mise file. Teams should document which Nix registries and caches are accepted and how source revisions are pinned.
The project’s active development is another reason to stage adoption. A release with many cross-platform changes can improve real failures while also exposing edge cases in shells, package managers, or architectures the maintainer could not test locally. Start with a development machine, then a clean CI runner, then a broader rollout. Preserve the previous setup path until the new bootstrap flow has demonstrated that it can be removed and recreated predictably.
Who should try it now
The best candidates are teams already using mise that have accumulated separate onboarding scripts for Homebrew, apt, Nix, dotfiles, or test services. They can gain the most from environment selectors and from the distinction between “declared” and “installed.” Mixed macOS/Linux repositories are another good fit, particularly when developers need the same project task names but different native package managers.
It is also worth testing for maintainers of CLI-heavy projects. Packslip man pages, signed manifests, platform-aware lock files, and improved artifact selection address the details that affect daily use rather than demo appeal. A project that distributes its own tools can inspect whether managed versions now behave consistently across shells and platforms.
The less suitable audience is a team looking for automatic, invisible machine mutation. mise makes setup more legible, but it does not make it risk-free. Nor should a latest declaration be mistaken for reproducibility. The new Nix backend is a bridge between a project-level declaration and the native package manager, not a magic abstraction that erases package-manager semantics.
Verdict
The most important part of mise 2026.9.4 is the way it makes host dependencies conditional and reviewable. Nix support is valuable because it respects Nix’s ownership model, while env selectors solve a practical problem for repositories with more than one working mode. The man-page and locking changes strengthen the less glamorous parts of tool management, and the cross-platform fixes make the release relevant to CI rather than only to local shells.
Try it if your current workflow already resembles a collection of runtime files, package scripts, task definitions, and environment-specific instructions. Begin with a small configuration, use dry runs, pin what must be repeatable, and keep system-level Nix or container definitions authoritative where they need to be. For a simple runtime manager, mise may be more machinery than necessary. For a team trying to make the entire developer setup understandable without pretending every operating system is the same, this release is a credible upgrade to test.
Comments
Sign in to comment.
No comments yet.