v2026.10.12

jdx/misev2026.10.12Oct 16, 2026by mise-en-dev

Upgrading?

AI Summary

This release introduces per-tool Python runtimes for PyPI tools, adds support for Gradle workspace discovery in monorepo tasks, and enhances `env._.file` with recursive search capabilities. It also improves the resilience of GitHub lookups and fixes environment leakage issues.

Key Highlights

  • Per-tool Python runtimes for PyPI tools
  • Gradle workspace discovery for multi-module builds
  • Recursive search support for `env._.file`
  • Retry logic for GitHub lookups during outages
  • Fix for `_.source` loading `~/.bashrc`

New Features

  • Per-tool Python for `pypi:` tools
  • Gradle workspace discovery
  • find_up support for `env._.file`
  • Git-rewritten file detection in watch_files hooks
  • Inferred .tera sources for dotfile templates
  • mise lock warnings for unsupported platforms
  • Added martin registry

Full Release Notes

PyPI and pipx tools can now choose their own Python runtime, the workspace graph can read Gradle multi-module builds, and `env._.file` can search parent directories. When mise-versions is having an outage, GitHub lookups now retry on `api.github.com`, and `_.source` scripts no longer pick up `~/.bashrc` when mise is launched from an editor.

## Added

- **Per-tool Python for `pypi:` tools.** Set `python` to a minor series or an exact version, and mise installs that runtime and passes it to uv or pipx for that tool only. The runtime stays private to the tool and does not become your shell's default Python. `mise lock` records the selected Python with the tool, and `mise prune` keeps any runtime that a retained tool environment still uses. You can't combine `python` with `--python`/`-p` in `uvx_args` or `pipx_args`. Tools that don't set `python` behave as before. [#14479](https://github.com/jdx/mise/pull/14479) (@jdx)

  ```toml
  [tools]
  "pypi:black" = { version = "latest", python = "3.12" }
  "pypi:ruff" = { version = "latest", python = "3.12.12" }
  ```

  If you change a tool's `python`, mise installs a new environment instead of reusing the old one. If that install fails, the previous working environment is left untouched. [#14504](https://github.com/jdx/mise/pull/14504) (@jdx)

- **Gradle workspace discovery.** `mise tasks graph` and `mise run --affected` now find projects listed by `include` in `settings.gradle` or `settings.gradle.kts`, using Groovy or Kotlin syntax. Project IDs follow Gradle paths: `:app` becomes `gradle::app`, and the root project is `gradle::`. Literal `project(":lib")` references in a project's top-level `dependencies {}` block become graph edges. mise reads the scripts as text and never runs Gradle. If an `include` is computed or conditional, a `projectDir` isn't a plain `file("...")` literal, or both settings files exist, mise reports an error that points to `[monorepo.projects."gradle:..."]` overrides. Editing the settings script marks every Gradle project as affected. Based on a prototype by @Jarvvski. [#14512](https://github.com/jdx/mise/pull/14512) (@jdx)

- **`find_up` for `env._.file`.** With `find_up = true`, mise looks for a relative path in the current directory and in every parent, so a global config can load each project's `.env` files. Files load from the root down, so values in closer files win. The default is `false`, and the option has no effect on absolute paths. [#14497](https://github.com/jdx/mise/pull/14497) (@jdx)

  ```toml
  # ~/.config/mise/config.toml
  [env]
  _.file = [
    { path = ".env", find_up = true },
    { path = ".env.local", find_up = true },
  ]
  ```

- **Detect git-rewritten files in `watch_files` hooks.** mise sets `MISE_WATCH_FILES_GIT_REWRITTEN=1` when every changed file was last written before git's most recent HEAD move (checkout, pull, rebase). Commits don't count as HEAD moves. Hooks such as format-on-edit can use this to skip files the user didn't edit. `git stash pop`/`apply` don't move HEAD, so mise doesn't detect them. [#14511](https://github.com/jdx/mise/pull/14511) (@jdx)

  ```toml
  [[watch_files]]
  patterns = ["**/*.go"]
  run = '[ -n "$MISE_WATCH_FILES_GIT_REWRITTEN" ] || { IFS=:; hk fix $MISE_WATCH_FILES_MODIFIED; }'
  ```

- **`.tera` sources inferred for dotfile group templates.** A `mode = "template"` entry in `[dotfile_groups]` no longer needs a `source` just to point at a `.tera` file. If the exact path doesn't exist, mise falls back to the same path with `.tera` added. An explicit `source` still takes precedence, and the `.tera` file is not also deployed under its suffixed name. [#14502](https://github.com/jdx/mise/pull/14502) (@jdx)

- **`mise lock` warns about unsupported platforms.** If you name platforms with `lockfile_platforms` or `mise lock --platform`, mise prints a warning for each tool version that has no build for one of them, for example `apko@0.30.0 is not available for windows-x64; it will not install there`. The default platform set still only logs this at debug level, and the exit status is unchanged. [#14500](https://github.com/jdx/mise/pull/14500) (@jdx)

- Registry: added `martin` (`github:maplibre/martin`). [#14488](https://github.com/jdx/mise/pull/14488) (@ivan-ivkovic, @jdx)

## Fixed

- **GitHub lookups survive mise-versions outages.** If mise-versions times out, drops the connection, or returns `429` or `5xx`, mise now retries the lookup on `api.github.com`, using your GitHub token if one is set. This covers releases, tags, repository contents, attestations and `self-update`. A `404`, `403` or empty answer from mise-versions is still trusted and not retried, so normal use doesn't spend GitHub's anonymous rate limit. If both sources fail, the error shows both failures, and a previously cached version list is still used. [#14501](https://github.com/jdx/mise/pull/14501) (@jdx)
- **`_.source` no longer loads `~/.bashrc`.** When mise's stdin was a socket and `SHLVL` was unset, which happens when an editor extension such as the VS Code mise extension starts it, bash sourced `~/.bashrc` before the script. That leaked variables into the environment and could drop the script's `PATH` entries. The script now runs with `--norc`. [#14487](https://github.com/jdx/mise/pull/14487) (@pikeas)
- **Each version entry uses its own options.** When a tool listed several versions, options set only on the first entry leaked into the later ones. For example, `prerelease = true` on a `latest` entry made a separate `"1"` entry resolve to a prerelease. [#14476](https://github.com/jdx/mise/pull/14476) (@JamBalaya56562, @risu729)
- **Project overrides now work when a workspace provider fails.** Previously, if a provider couldn't read its manifest (for example, a malformed `go.work`), `mise tasks graph` and `mise run --affected` failed for the whole repo. Declaring a project in that provider's namespace under `[monorepo.projects]` now replaces the provider's output and clears its error. Providers with no declared projects still fail loudly. [#14508](https://github.com/jdx/mise/pull/14508) (@jdx)

## Documentation

- Explained why `mise activate` keeps shims on `PATH` [#14493](https://github.com/jdx/mise/pull/14493) (@jdx), and clarified the platform-specific mise cache paths for CI [#14506](https://github.com/jdx/mise/pull/14506) (@zeitlinger).

**Full Changelog**: https://github.com/jdx/mise/compare/v2026.10.11...v2026.10.12

## 💚 Sponsor mise

mise is built and maintained by [@jdx](https://github.com/jdx), an open source developer at [**entire.io**](https://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](https://jdx.dev/sponsors.html). Your support funds ongoing development and helps keep mise fast, free, and independent.

Related Repositories