v2026.5.9

jdx/misev2026.5.9May 15, 2026by mise-en-dev

AI Summary

A modest release: SwiftPM gains artifact bundle support, `[[watch_files]]` hooks can pick their own inline shell, and aqua registry lookup performance improves.

Key Highlights

  • SwiftPM installs now prefer prebuilt artifact bundles.
  • `[[watch_files]]` hooks can now accept an optional `shell` field.
  • Aqua registry lookup tables are baked as static maps for performance.

New Features

  • SwiftPM artifact bundle support
  • Per-hook watch shell configuration
  • Performance improvements for aqua registry

Full Release Notes

A modest release: SwiftPM gains artifact bundle support, `[[watch_files]]` hooks can pick their own inline shell, and a handful of fixes land for aqua latest-tag resolution, vfox `cmd.exec`, and GitHub OAuth device-flow URLs. Plain-string Tera rendering also gets a fast path.

## Added

- **(spm)** SwiftPM installs now prefer prebuilt artifact bundles (`*.artifactbundle.zip`) when a release publishes one for the current Swift target triple, falling back to a source build otherwise ([#9825](https://github.com/jdx/mise/pull/9825)) by @ikesyo. New controls:

  ```toml
  [tools]
  # require an artifact bundle; fail instead of source-building
  "spm:giginet/swift-testing-revolutionary" = { version = "0.4.0", artifactbundle = true }

  # always source-build, ignore any bundles
  "spm:tuist/tuist" = { version = "latest", artifactbundle = false }

  # disambiguate when multiple bundle assets are published
  "spm:org/tool" = { version = "1.0.0", artifactbundle_asset = "tool.artifactbundle.zip" }

  [settings]
  # apply "bundles only" globally (mirrors cargo.binstall_only)
  spm.artifactbundle_only = true
  ```

- **(config)** `[[watch_files]]` entries with `run` accept an optional `shell` field, rendered through templates and falling back to the configured default inline shell when unset ([#9810](https://github.com/jdx/mise/pull/9810)) by @risu729:

  ```toml
  [[watch_files]]
  patterns = ["*.js"]
  run = "eslint --fix ."
  shell = "bash -c"
  ```

  `shell` only applies to `run` hooks; combining it with `task` produces a warning and the value is ignored.

## Fixed

- **(aqua)** When GitHub's `latest` release pointed at a tag that aqua's registry rejected via `version_filter` or `version_constraint`, mise would return it anyway. The latest fast path now applies both checks before accepting a tag ([#9834](https://github.com/jdx/mise/pull/9834)) by @risu729.
- **(vfox)** Lua `cmd.exec` calls inside vfox plugins now build commands from mise's configured `unix_default_inline_shell_args` / `windows_default_inline_shell_args` instead of hardcoding `sh -c` or `cmd /C`, aligning plugin behavior with tasks, Tera command rendering, and other inline shell users ([#9837](https://github.com/jdx/mise/pull/9837)) by @risu729.
- GitHub OAuth device-flow paths were slightly off compared to the documented endpoints. The default `oauth_auth_url` is now the GitHub login base, with mise appending `/device/code` and `/oauth/access_token` per [GitHub's device-flow docs](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#device-flow) ([#9791](https://github.com/jdx/mise/pull/9791)) by @jasisk.
- **(patrons)** `mise patrons` now points the "become a patron" link to the en.dev homepage instead of `/sponsor` ([#9868](https://github.com/jdx/mise/pull/9868)) by @jdx.

## Changed

- **(registry)** `npm` is now resolved through `aqua:npm/cli` (with `npm:npm` retained as a fallback), and `buck2` switches to `aqua:facebook/buck2` with `prerelease = true` so its always-prerelease releases are visible ([#9762](https://github.com/jdx/mise/pull/9762), [#9805](https://github.com/jdx/mise/pull/9805)) by @risu729.
- **(registry)** Added SonarQube CLI as `aqua:SonarSource/sonarqube-cli` ([#9824](https://github.com/jdx/mise/pull/9824)) by @3PeatVR.

## Performance

- **(config)** Strings with no Tera block markers (`{{`, `{%`, `{#`, including whitespace-trimmed forms) now bypass the Tera renderer at config evaluation sites, skipping context construction, async context fetches, and `get_tera` setup. Tera 1.20.1's grammar guarantees these are the only block openers, so output is unchanged for both well-formed and malformed templates ([#9833](https://github.com/jdx/mise/pull/9833)) by @risu729.

## Documentation

- Updated the Walkthrough guide ([#9853](https://github.com/jdx/mise/pull/9853)) by @thernstig.

## New Contributors

- @3PeatVR made their first contribution in [#9824](https://github.com/jdx/mise/pull/9824)
- @ikesyo made their first contribution in [#9825](https://github.com/jdx/mise/pull/9825)
- @thernstig made their first contribution in [#9853](https://github.com/jdx/mise/pull/9853)

**Full Changelog**: https://github.com/jdx/mise/compare/v2026.5.8...v2026.5.9

## 💚 Sponsor mise

mise is built by [@jdx](https://github.com/jdx) under [**en.dev**](https://en.dev) — an independent studio making developer tooling (mise, [aube](https://aube.en.dev/), and more). Development is funded by sponsors.

If mise saves you or your team time, please consider sponsoring at [en.dev](https://en.dev). Individual and company sponsorships keep mise fast, free, and independent.