mise-en-place

jdx/mise last check 311 releases today
Notes

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

Release notes
v2026.9.11: macos-app bootstrap packages, task template inheritance for flags and file tasks, and Swift on Linux fixes · today
view on github

A new macos-app bootstrap manager installs .app bundles from a pinned URL and checksum when no Homebrew cask exists, task templates now compose usage flags and can be extended from file tasks, and Swift on Linux picks its distro build from swift.org's release index instead of a hard-coded map that 404'd on arm64 and on newer Fedora, Amazon Linux, and Arch hosts. Install failures also become far more actionable: errors name the minimum_release_age cutoff that hid every version, the child's last stderr line, or the shared libraries a Swift toolchain cannot load.

Highlights

  • Apps without a cask: "macos-app:<name>" entries in [bootstrap.packages] download, checksum-verify, and install a .app into /Applications using mise's existing cask pipeline, with stricter ownership rules for apps already at the target.
  • Task templates that actually share things: a task that extends a template now inherits the template's usage flags alongside its own, file tasks can write #MISE extends="...", and a template's vars can read the values the extending task supplies.
  • Swift on Linux: arm64 downloads resolve on every distro, the build is chosen from what a release actually publishes (with a warning when a fallback is used), and a fallback that cannot start names the missing libraries instead of exiting 127 after a 1 GB download.

Added

  • bootstrap: The macos-app package manager installs a macOS .app bundle from a vendor or internal download. version, url, sha256, and artifact are all required ("latest" is rejected because mise cannot discover releases behind a plain URL); {{version}} is interpolated into url, so a release bump is a two-field edit. Only .dmg and .zip archives containing an app bundle are supported, state is kept in mise's state directory rather than Homebrew's Caskroom, and an app already at the destination that this entry does not own is refused unless adopt = true and the contents match. mise bootstrap packages upgrade cannot discover new versions for these entries, and prune --manager macos-app is unsupported. Prefer brew-cask wherever a cask exists. (#13279)

    [bootstrap.packages."macos-app:example"]
    version = "1.2.3"
    url = "<HTTPS URL of the .dmg or .zip; {{version}} is interpolated>"
    sha256 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
    artifact = "Example.app"
    
  • tasks: A task that names a template with extends and declares its own usage now gets the template's flags too, listed first in --help. Previously the task's spec replaced the template's entirely, so shared flags had to be copied into every task. Workspace-root task defaults still only fill in usage when the task has none. A flag declared in both places is listed twice; declare each flag in one place, or use usage flagsets for replacements. (#13310)

    [task_templates.deploy]
    usage = 'flag "--env <env>" help="Target environment"'
    
    [tasks.deploy-api]
    extends = "deploy"
    usage = 'flag "--replicas <n>" help="How many to run"'
    run = 'echo "env=$usage_env replicas=$usage_replicas"'
    
  • tasks: File tasks (including remote HTTP and git:: scripts) can use #MISE extends="<template>" in their header to inherit tools, env, description, aliases, and other fields from a task template; previously the field was warned about and ignored. A task whose command is a script file no longer picks up a template's run. (#13307)

  • swift: When a Linux install fails its swift --version check, mise runs ldd over the toolchain and lists every unresolved shared library (for example libform.so.6, libncurses.so.6, libpanel.so.6 on an Arch-family host running a ubi9 build), with the tool's install_env applied so an LD_LIBRARY_PATH remedy is not misreported. docs/lang/swift.md documents the workaround. (#13319)

Fixed

  • swift: Installing Swift on arm64 failed with a 404 on every Linux distro except Ubuntu (and on Windows arm64 lock entries) because only Ubuntu used swift.org's <platform>-<arch> download directory. (#13293, fixes #13291)
  • swift: The Linux distro build is now chosen from swift.org's release index rather than a hard-coded map: the host's exact distro version wins, then the newest published build older than the host, then the family's oldest, with ID_LIKE consulted (Linux Mint gets an Ubuntu build) and unknown distros such as Arch falling back to ubi9. Every compromise is announced with a warning, musl hosts and unsupported architectures fail before downloading, and swift.platform still overrides selection without contacting swift.org. The swift_platform lockfile option now records the host as detected (e.g. fedora40 instead of fedora39); mismatched entries are re-resolved on the next lock. (#13297, fixes #13289)
  • config: install_env values are now rendered as templates like other tool options, so LD_LIBRARY_PATH = "{{env.HOME}}/.local/lib/compat" reaches the install subprocess expanded rather than literally. {{version}} is left unchanged. (#13314)
  • install: When minimum_release_age (default 24h) hides every candidate, the error names the setting and cutoff, how many releases it hid, the newest one with its release and eligibility dates, and a copy-pasteable exact pin to install it now, instead of no versions found ... matching date filter. A query that matched nothing is no longer blamed on the filter. (#13308)
  • cmd: A failing command run by mise (installs, tasks, plugin scripts) now appends the child's last non-empty stderr line to the error, e.g. exit code 127; last stderr: swift: error while loading shared libraries: libncurses.so.6 .... This also reaches the final error block under --quiet, where stderr was previously never shown. (#13315)
  • tasks: A broken usage spec now reports the task name and the parser's diagnostic (invalid usage spec for task 'deploy' followed by the reason) instead of a bare Invalid usage config; file tasks render the same diagnostic rather than a Debug dump, and a missing or unreadable script is reported as such rather than as a bad spec. (#13312)
  • tasks: A task template's vars can now read the vars the extending task supplies, so {{ vars.opt | default(value='none') }} in a template sees the task's opt instead of always taking the default. Literal vars within a single task are also bound first, so vars = { msg = "hi {{ vars.who }}", who = "world" } works regardless of declaration order. Config-level [vars] are unchanged. (#13322)
  • runtime symlinks: latest and version-prefix links under installs/<tool>/ that point at an install no longer eligible for a link (for example a directory left with an incomplete marker by an interrupted install) are now removed on rebuild instead of surviving indefinitely. Configured aliases, hand-made names, and absolute symlinks are left alone. (#13288)
  • npm: Semver pre-releases with numeric suffixes such as 1.3.1-3 no longer claim the latest, 1, and 1.3 runtime symlinks or satisfy "latest"/prefix requests over the newest stable install; links an older mise already wrote are cleaned up on the next install. An exact request or the prerelease option still selects them. (#13272 by @pataar)
  • lockfile: mise lock --global on a mise.lock symlinked into a dotfiles repository now keeps native dependency sidecars beside the target lockfile, so mise install --locked works from a fresh checkout. If you used this layout on 2026.9.7 through 2026.9.10 and see missing sidecars, run mise lock --global again to repair the pointers. (#13268 by @nettlesh)
  • lockfile: With lockfile_mode = "generate", mise unuse now removes the tool's entry from mise.lock and its .mise/locks/... sidecar immediately rather than leaving them until the next mise install or mise lock. Merge mode is unchanged. (#13304)
  • conda: Commands from conda: packages that have nothing to activate (no activate.d scripts, no dependency executables, no script entry points) are now plain symlinks instead of shell launchers, so tools like conda:ripgrep or conda:gh no longer prepend the conda prefix to the PATH of every child process and skip the extra shell. Packages that need activation keep their launcher; Windows is unchanged. A relative MISE_DATA_DIR is also handled. Existing installs keep their current entries until reinstalled with mise install --force conda:<pkg>. (#13305)
  • backends: A tool's postinstall hook now receives pre-tools [env] from the config on every backend (http, aqua, github, cargo, npm, core tools), not only for asdf plugins, and a hook that changes an env input is visible to hooks ordered after it. (#13316)
  • github: Tools whose release tags repeat the configured version_prefix (tag a-a-1.2.3 with version_prefix = "a-", listed as a-1.2.3) can now be installed; prefix + version is tried first so every listed version round-trips to its tag. If a repo publishes both a-1.2.3 and a-a-1.2.3, requesting a-1.2.3 now resolves to the doubled tag. (#13317)

Changed

  • brew-cask: Cask archives are downloaded concurrently at the configured jobs concurrency before the serial install pass, so --jobs/MISE_JOBS now speed up cask-heavy runs. Placement (mounting, swapping app bundles) remains serial. (#13282 by @waynehoover)

Security

  • http: Artifact downloads now refuse a redirect that steps down from HTTPS to HTTP, matching the policy the remote-version client already applied; the error names which kind of request was refused. URLs that are plain HTTP to begin with are unaffected. (#13292)
  • brew-cask: The fingerprint used to adopt or refuse an existing app bundle is now computed entirely through the verified directory descriptor (fstatat/openat/readlinkat), so a path component swapped mid-check cannot make mise compare against a different tree than the one it will replace. Digests are unchanged, so existing receipts remain valid; large files are now hashed in-process, which can make adoption checks slower. (#13294)

Documentation

  • The bootstrap packages guide is reorganized around choosing a manager, declaring packages, and the command reference, with a dedicated section for direct macos-app downloads and app ownership. (#13298)
  • The variables guide explains when [vars] resolve and why a task-local override does not recompute a top-level var that already referenced it, with task templates as the way to defer a fragment. (#13323)
  • Task Arguments documents sharing flags between tasks with usage flagset, use, and include, in both TOML and file tasks. (#13313)

New Contributors

  • @pataar made their first contribution in #13272

Full Changelog: https://github.com/jdx/mise/compare/v2026.9.10...v2026.9.11

💚 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.