# Why
We've encountered a need for showing a field from the not-authorized entity in the user facing error message. While we explicitly didn't pass this in the past since it's not authorized, upon second thought and the concrete use case it should be okay since this is only able to be used within the error message. While it is technically possible to leak unauthorized data this way, the variable name and docblock should at least hint that it's not authorized and caution should be used.
# How
Add entity and evaluation context params to the message fn.
# Test Plan
Run updated tests.
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [postgres](https://hub.docker.com/_/postgres) ([source](https://redirect.github.com/docker-library/postgres)) | digest | `74935e7` → `edb0c08` |
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xODAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjE4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| redis | digest | `2c2dff7` → `97ec881` |
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xODAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjE4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [jdx/mise](https://redirect.github.com/jdx/mise) | patch | `v2026.10.15` → `v2026.10.19` |
---
### Release Notes
<details>
<summary>jdx/mise</summary>
### [`v2026.10.19`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.19): : Security hardening across trust, installs and provenance; lockfiles now rebuilt completely by default
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.18...vfox-v2026.10.19)
Most of this release closes ways an untrusted repository, download host or mirror could run code, leak credentials or get around verification. Some of these fixes make mise stricter, so check **Breaking Changes** before you upgrade. Also in this release: `lockfile_mode = "generate"` is now the default, `mise lsp` sends semantic highlighting, and there is a new `{{ mise_config_dir }}` template variable.
#### Highlights
- **Trust is narrower and tied to the files you trusted.** Help output, shims, hooks, config writes and shell completion no longer trust a project or run its code without your consent. Trust also follows worktrees, symlinks and config directories correctly, and safe mode closes several more gaps.
- **Verification fails closed.** Pinned checksums, Node signatures, SLSA provenance (including the tag it was built from) and GitHub attestations are now enforced. Before, a 404 or a missing file could make mise skip them.
- **Hostile inputs are contained.** Archives, asset names, versions, lockfiles and HTTP responses can no longer write outside their directories, use unbounded memory or disk, or hang the prompt. Credentials no longer show up in install paths, lockfiles, logs or redirects.
#### Added
- **`{{ mise_config_dir }}` template variable.** It resolves to the config directory mise itself uses: `MISE_CONFIG_DIR`, or else `xdg_config_home` + `/mise`. It is available wherever `xdg_config_home` is: config templates, `.miserc.toml` and settings paths. This is useful for dotfiles variants that link into `conf.d`. [#​14886](https://redirect.github.com/jdx/mise/pull/14886) ([@​jdx](https://redirect.github.com/jdx), [@​ponko2](https://redirect.github.com/ponko2))
```toml
[dotfiles."git-tools"]
source = "git"
mode = "symlink"
variants = [{ default = true, target = "{{ mise_config_dir }}/conf.d/git-tools" }]
```
- **Semantic highlighting in `mise lsp`.** Editors can now color task names, tools, env vars, `[vars]` keys, `_.` directives, `{{ }}`/`{% %}`/`{# #}` template delimiters and deprecated keys in `mise.toml`. To turn it off, pass `{"semanticTokens": false}` in `initializationOptions`. [#​14918](https://redirect.github.com/jdx/mise/pull/14918) ([@​jdx](https://redirect.github.com/jdx))
- **`extract_max_ratio` setting (global only).** It caps how far an archive may expand during extraction. See Security below. [#​14915](https://redirect.github.com/jdx/mise/pull/14915) ([@​jdx](https://redirect.github.com/jdx))
- **`github.enterprise_hosts` setting (global only, `MISE_GITHUB_ENTERPRISE_HOSTS`).** It lists the GitHub Enterprise hosts that receive the GitHub token on `/api/v3` URLs over https. [#​14913](https://redirect.github.com/jdx/mise/pull/14913) ([@​jdx](https://redirect.github.com/jdx))
- **New vfox attestation fields `slsa_source_repository` and `slsa_source_tag`.** Plugins can use them to pin the repository and tag that SLSA provenance must come from. [#​14904](https://redirect.github.com/jdx/mise/pull/14904), [#​14924](https://redirect.github.com/jdx/mise/pull/14924) ([@​jdx](https://redirect.github.com/jdx))
#### Changed
- **`lockfile_mode = "generate"` is now the default.** Installs now rebuild `mise.lock` from the current requests, reuse unchanged entries and also lock the other platforms. A lockfile committed from one machine therefore no longer fails `mise install --locked` on another platform because of missing entries. Neither mode creates a lockfile (use `mise lock` or `lockfile = true`), and the lockfile format is unchanged. To keep the previous behavior, set `lockfile_mode = "merge"` or `MISE_LOCKFILE_MODE=merge`. [#​14893](https://redirect.github.com/jdx/mise/pull/14893) ([@​jdx](https://redirect.github.com/jdx))
#### Security
**Trust and safe mode**
- Several actions no longer count as consent to trust a project: printing `mise run --help`/`mise watch --help`, running a shim, a hook starting `mise run`, an MCP call, or `mise set`/`unset`/`tasks add` saving config. Config writes now ask before they trust an untrusted sibling config. A task counts as trusted only if every config that adds to it is trusted. The MCP server refuses untrusted file tasks, task names that look like file paths, and inline tool options. [#​14903](https://redirect.github.com/jdx/mise/pull/14903) ([@​jdx](https://redirect.github.com/jdx))
- Trust now stays with the files you trusted. A forged git worktree, a symlink to your global config, a clone named `.mise`, or a project `.miserc.toml` can no longer borrow trust or hide global config. In paranoid mode, idiomatic version files, each local task file and project-named aqua registries need trust of their own. Remote git includes pinned to a commit SHA must check out exactly that commit. [#​14902](https://redirect.github.com/jdx/mise/pull/14902) ([@​jdx](https://redirect.github.com/jdx))
- Safe mode (`MISE_SAFE=1`) now also blocks:
- a project's lazy tools, `[deps]`, `path:` versions and spm `install_command`;
- all S3 requests;
- forge tokens and netrc credentials sent to hosts that project config names;
- `env` and filesystem helpers in project templates.
In every mode, a project `.miserc.toml` gets a restricted, size-limited template language, and `bin_path` must stay inside the tool's install directory. [#​14900](https://redirect.github.com/jdx/mise/pull/14900) ([@​jdx](https://redirect.github.com/jdx))
- Pressing TAB no longer runs untrusted task code. The dynamic completers (`complete run=`, `complete delegate=`, `choices run=`, `mount`) only run for trusted config. mise's own completers quote typed words, and control characters are removed from candidates. Quoting for fish and PowerShell is also fixed. [#​14898](https://redirect.github.com/jdx/mise/pull/14898) ([@​jdx](https://redirect.github.com/jdx))
- Hook commands are now rendered once, when they load. Before, a directory name containing `{{ exec(...) }}` could run code from a `cd` hook. A project's `enter`, `leave` and `watch_files` hooks now start in the project root. `mise use`, `mise upgrade --bump` and every other writer refuse to write a version containing template syntax, and a rewritten option keeps its `{{ env.X }}` template instead of the rendered secret. [#​14897](https://redirect.github.com/jdx/mise/pull/14897) ([@​jdx](https://redirect.github.com/jdx))
- `cd`-ing into a hostile repository can no longer hang or crash `hook-env` or make mise print files from outside the repo. Causes this covers include configs linked to devices, symlink mazes in task directories, non-UTF-8 paths, oversized files, glob characters in paths, and version files that link to another file. [#​14916](https://redirect.github.com/jdx/mise/pull/14916) ([@​jdx](https://redirect.github.com/jdx))
**Install verification**
- A checksum pinned in `mise.lock` is now enforced for erlang, npm, spm and http instead of being replaced or skipped. If Node's `SHASUMS256.txt.sig` is missing, the install fails. bun and deno check the publisher's sha256 when there is no lock entry. A locked node or spm artifact that returns 404 no longer silently falls back to a source build. [#​14899](https://redirect.github.com/jdx/mise/pull/14899) ([@​jdx](https://redirect.github.com/jdx))
- SLSA, attestation and signed-checksum checks now fail closed:
- the provenance file can no longer stand in for the artifact;
- `slsa_signer_*` pins require provenance;
- `mise lock` runs the cosign, minisign and SLSA checks that aqua recipes declare;
- SHA-512 signed checksum files are compared with the artifact;
- aqua honors `attestations_since`.
[#​14908](https://redirect.github.com/jdx/mise/pull/14908) ([@​jdx](https://redirect.github.com/jdx))
- The SLSA signing run must come from the workflow's repository or the tool's own repository. Attestations must name the requested repository. Public-good bundles without a Rekor entry are rejected. [#​14904](https://redirect.github.com/jdx/mise/pull/14904) ([@​jdx](https://redirect.github.com/jdx))
- SLSA provenance built from a different tag is now rejected, so a mirror can't serve an older release's genuine artifact and provenance as a newer version. [#​14924](https://redirect.github.com/jdx/mise/pull/14924) ([@​jdx](https://redirect.github.com/jdx))
- packslip signer pins are checked by repository ID, including `workflow` pins. Backdated GitLab `released_at` dates and bundles with no transparency-log time can no longer get around `minimum_release_age`. [#​14912](https://redirect.github.com/jdx/mise/pull/14912) ([@​jdx](https://redirect.github.com/jdx))
**Paths, subprocesses and resource limits**
- Release asset names must be plain file names. Archives from the github, http, aqua, cargo-binstall, packslip and vfox backends may not contain symlinks that point outside the install directory. [#​14895](https://redirect.github.com/jdx/mise/pull/14895) ([@​jdx](https://redirect.github.com/jdx))
- Resolved versions, plugin names and task stub names are checked before they become paths or URL segments. A remote version containing `..`, quotes, `$` or a leading `-` now fails as an invalid tool version. [#​14901](https://redirect.github.com/jdx/mise/pull/14901) ([@​jdx](https://redirect.github.com/jdx))
- Git lookups, build tools (ruby-build, python-build, `cargo install`, `gem install`) and npm now run outside the project directory, so the repo's `.git/config` and other project files can't change what they do. Untrusted values are kept out of their command-line arguments. In safe mode, asdf `exec-env` is refused. [#​14896](https://redirect.github.com/jdx/mise/pull/14896) ([@​jdx](https://redirect.github.com/jdx))
- Committed symlinks around lockfiles, tool stubs and the remote task cache can no longer make mise read, write or delete files outside the repo. An untrusted lockfile still pins versions and checksums, but it can no longer switch a tool's backend, add inline options or supply download URLs. [#​14906](https://redirect.github.com/jdx/mise/pull/14906) ([@​jdx](https://redirect.github.com/jdx))
- The task sandbox has fewer escapes:
- `--allow-write` refuses project symlinks that lead outside the project;
- `--deny-net` also blocks other socket families, io_uring and x32 syscalls;
- an empty `allow_write` blocks all writes instead of turning the sandbox off;
- macOS always uses `/usr/bin/sandbox-exec`;
- OCI whiteouts can't delete through planted symlinks.
[#​14911](https://redirect.github.com/jdx/mise/pull/14911) ([@​jdx](https://redirect.github.com/jdx))
- HTTP response bodies are capped at 128 MiB, and slow bodies are bounded by `http_download_timeout`. Downloads are saved exactly as sent. Archive extraction stops once the output exceeds both 256 MiB and 100 times the download size (`extract_max_ratio`). [#​14915](https://redirect.github.com/jdx/mise/pull/14915) ([@​jdx](https://redirect.github.com/jdx))
**Credentials**
- The GitHub token is sent only to GitHub API hosts or the configured `api_url`, not to any host that serves `/api/v3`. Release caches are keyed by the exact repository. A download that fails its pinned checksum is not kept. A project can no longer mark a task `global`. In safe mode, remote task files from project config are not fetched. [#​14913](https://redirect.github.com/jdx/mise/pull/14913) ([@​jdx](https://redirect.github.com/jdx))
- Credentials are now kept out of install directory names, install manifests, `mise.lock`, `Referer` headers, logs and error messages. Age keys and Forgejo tokens are redacted in `mise doctor`, `mise settings` and `mise tool`. Shebang task scripts are readable only by their owner, and multi-line secrets are redacted in task output. [#​14917](https://redirect.github.com/jdx/mise/pull/14917) ([@​jdx](https://redirect.github.com/jdx))
#### Fixed
- `uv_venv_auto` could fork-bomb the machine when uv probed mise's python shims while creating a venv. mise now skips venv creation when it is started from inside that venv creation. [#​14927](https://redirect.github.com/jdx/mise/pull/14927) ([@​jdx](https://redirect.github.com/jdx))
- With `minimum_release_age` set, `mise upgrade` no longer downgrades tools that use date versions with leading zeros (for example `2026.10.21` to `2026.08.19`). [#​14923](https://redirect.github.com/jdx/mise/pull/14923) ([@​jdx](https://redirect.github.com/jdx))
- File tasks that `extends` a task template now use the template's `usage` spec, so its flags show in `-h` and are accepted. [#​14888](https://redirect.github.com/jdx/mise/pull/14888) ([@​jdx](https://redirect.github.com/jdx))
- `mise tasks add --file` now quotes and escapes `#MISE` header values. Before, `--dir` and values containing quotes produced invalid TOML that broke the next `mise run`. [#​14925](https://redirect.github.com/jdx/mise/pull/14925) ([@​xucian](https://redirect.github.com/xucian))
- `mise uninstall` can now remove installs whose directories deny their owner write access, such as read-only `0555` runtime trees. [#​14883](https://redirect.github.com/jdx/mise/pull/14883) ([@​HengYangDS](https://redirect.github.com/HengYangDS))
- A `pypi:` tool with a private `git+ssh://` github.com source now lists versions through `git ls-remote` over SSH when GitHub can't see the repository. [#​14905](https://redirect.github.com/jdx/mise/pull/14905) ([@​jdx](https://redirect.github.com/jdx), [@​owpac](https://redirect.github.com/owpac))
#### Breaking Changes
Most setups need no changes. Check these cases:
- **Lockfiles:** installs now rewrite `mise.lock` in `generate` mode. To keep the old behavior, set `lockfile_mode = "merge"`.
- **Trust prompts:** `mise set`/`unset`/`tasks add` in a directory with an untrusted sibling config now ask for trust, or fail without a terminal. A project that has only a `mise-tasks/` directory needs `mise trust .` before its dynamic task completions work. In paranoid mode, run `mise trust <file>` once for each existing task file.
- **Worktrees and includes:** a worktree you moved by hand needs `git worktree repair` before it shares trust again. A remote include pinned to an annotated tag's object ID must pin the commit SHA instead. Your own `~/.miserc.toml` can no longer ignore the global config.
- **Project `.miserc.toml`:** templates that read `env` or use loops or functions other than `arch()`, `os()`, `os_family()`, `libc()`, `avx2()` and `num_cpus()` are no longer rendered. Move them to the global `.miserc.toml`.
- **Safe mode:** project templates that read an env var without a `default` now fail to render. Projects that point at a private forge or a netrc-protected server can no longer list versions there.
- **Node:** mirrors that don't copy the `.sig` files, and early releases without one (for example 4.0.0 and 5.12.0), need `node.gpg_verify = false`.
- **SLSA:** a `github:` tool that sets `slsa_signer_identity` but builds from a branch instead of a tag no longer verifies. A lock entry that has a checksum but no provenance installs on the checksum alone; re-run `mise lock` or set `locked_verify_provenance`.
- **packslip:** after a repository rename, a pin without a repository ID needs `mise packslip forget <tool>`.
- **GitHub Enterprise:** `http:` tools, aqua packages and remote tasks on `/api/v3` URLs no longer get the GitHub token automatically. Add the host to `github.enterprise_hosts` in global config, or set `api_url`.
- **Credentials in URLs:** `mise lock` refuses URLs whose query has a credential-like parameter. Use `headers` or netrc instead. Tools installed under a directory name that contained credentials are reinstalled under a clean name.
- **Task sandbox:** `--deny-write`/`allow_write` sandboxes no longer start on Linux before 6.2. Programs that need io_uring no longer run under `--deny-net`. To allow writes through a project symlink that points outside the project, name its target instead.
- **Archives:** archives that contain symlinks pointing outside the install directory fail to install (brew casks and aqua dmg/pkg are exempt). Archives that legitimately expand more than 100 times and past 256 MiB need a higher `extract_max_ratio`, or `0` to turn the check off.
- **Hooks:** a project's `enter`, `leave` and `watch_files` hooks now start in the project root. Use `$MISE_PROJECT_ROOT` if a hook needs the root explicitly.
- **Other changes:**
- `MISE_OVERRIDE_*_FILENAMES` entries are matched as literal file names;
- config, lock and task files over 16 MiB are refused;
- a `.tool-versions` or idiomatic version file that links to a file with a different name is skipped;
- a relative `go.repo` resolves from `$HOME`;
- a bare `OWNER/REPO` passed to `bootstrap --adopt` that matches a local path is an error (write `./OWNER/REPO` for the local path).
#### New Contributors
- [@​xucian](https://redirect.github.com/xucian) made their first contribution in [#​14925](https://redirect.github.com/jdx/mise/pull/14925)
- [@​HengYangDS](https://redirect.github.com/HengYangDS) made their first contribution in [#​14883](https://redirect.github.com/jdx/mise/pull/14883)
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.10.18...v2026.10.19>
#### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.10.18`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.18): : mise lsp: a language server for mise.toml
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.17...vfox-v2026.10.18)
mise now includes a language server, `mise lsp`, which gives editors diagnostics, completion, hover, navigation and quick fixes for `mise.toml`. Doctor checks can depend on other checks, and `mise dot history purge` erases a tracked file from dotfiles history. This release also fixes many lockfile, prune, Windows and dotfiles issues.
#### Added
- **`mise lsp`, a language server for mise config files.** It runs over stdin/stdout, so any editor with an LSP client can use it (Neovim, Helix, Emacs, Zed, VS Code, ...). It uses the schema and formatter of the installed mise, so its answers match your version. [#​14744](https://redirect.github.com/jdx/mise/pull/14744), [#​14808](https://redirect.github.com/jdx/mise/pull/14808), [#​14811](https://redirect.github.com/jdx/mise/pull/14811), [#​14812](https://redirect.github.com/jdx/mise/pull/14812) ([@​jdx](https://redirect.github.com/jdx))
- **Diagnostics:** TOML syntax errors, unknown keys with a "did you mean" suggestion, values of the wrong type, and deprecated keys. It warns about task references that point to no task and reports `depends` cycles as errors.
- **Completion and hover:** config keys and enum or boolean values, task names in `depends`, `depends_post`, `wait_for`, `run = [{ task = ... }]` and `extends`, and tool names from the registry under `[tools]`. Hover shows the description and backends of a tool, or the description and command of a task.
- **Navigation and editing:** go to a task's definition (also in included files), find its references, and rename a task together with every reference in the file. Quick fixes replace an unknown key or task name, and rewrite a deprecated key such as `env_path` to the key that replaces it. Formatting gives the same output as `mise fmt`.
- It only handles files that mise loads as configs (`mise.toml`, `mise.<env>.toml`, `conf.d/*.toml`, ...) and ignores `Cargo.toml`, `pyproject.toml` and other TOML files, so you can attach it to the TOML filetype. Configs are parsed but never rendered, and it makes no network requests, so opening an untrusted file runs nothing. Clients can turn off `formatting`, `hover`, `completion`, `definition`, `references` or `rename` with `initializationOptions`.
```lua
vim.lsp.config("mise", { cmd = { "mise", "lsp" }, filetypes = { "toml" }, root_markers = { "mise.toml" } })
vim.lsp.enable("mise")
```
- **Doctor checks can depend on other checks.** Add `depends` (a single name or a list) to a check in `[doctor.checks.*]`. If a dependency fails, errors, is skipped or is blocked, the dependent check is reported as `blocked`, and its command and hint are skipped. A `blocked` result does not change the exit code on its own. An unknown dependency name or a cycle is reported as a config error, and then no checks run. [#​14773](https://redirect.github.com/jdx/mise/pull/14773) ([@​jdx](https://redirect.github.com/jdx))
```toml
[doctor.checks."examplectl:project"]
depends = ["examplectl:auth"]
run = 'test -n "$(examplectl config get project)"'
```
- **`mise dot history purge <path>` removes a tracked path from local dotfiles history.** Use it after tracking a secret by mistake. Checkpoints that changed only that path are removed. All other checkpoints keep their numeric IDs, messages and dates, so `history`, `rollback` and `undo` keep working. Use `--dry-run` to preview and `--yes` to skip the prompt. `--backup` keeps the old history under `refs/mise/purge-backup/`, and `--keep-objects` skips pruning. The command refuses if any version of the path is already reachable from the origin, because mise never force-pushes. [#​14831](https://redirect.github.com/jdx/mise/pull/14831) ([@​jdx](https://redirect.github.com/jdx))
- **A dotfiles variant's `target` can be a template**, so one shared config can link into locations that differ between machines. Only the variant `target` is rendered. Templates get the standard config context (`env`, `xdg_config_home`, `config_root`, ...), but `exec()` and `vars` are not available. The rendered path must be absolute or start with `~/`. [#​14856](https://redirect.github.com/jdx/mise/pull/14856) ([@​jdx](https://redirect.github.com/jdx), [@​ponko2](https://redirect.github.com/ponko2))
```toml
[dotfiles.examplectl]
source = "dotfiles/examplectl"
mode = "symlink"
variants = [{ default = true, target = "{{ xdg_config_home }}/examplectl" }]
```
- **`mise upgrade --bump --pin` writes resolved versions to config.** Requests such as `latest` or `20` become the exact version, for example `24.14.0`, even if the tool was already up to date. With the `pin` setting (`MISE_PIN=1`), a plain `mise upgrade --bump` now does the same. `--dry-run` shows what would change. [#​14791](https://redirect.github.com/jdx/mise/pull/14791) ([@​jdx](https://redirect.github.com/jdx))
- **`[bootstrap.hooks]` tables accept `run_windows`**, as tasks and `[hooks]` already do. On Windows it is used instead of `run`. A table with only `run_windows` does nothing on other platforms. [#​14851](https://redirect.github.com/jdx/mise/pull/14851) ([@​jdx](https://redirect.github.com/jdx))
- **Registry:** `goose-agent` (`aqua:aaif-goose/goose`), the Goose AI agent CLI. The installed binary is still named `goose`. [#​14822](https://redirect.github.com/jdx/mise/pull/14822) ([@​kwsantiago](https://redirect.github.com/kwsantiago))
#### Changed
- **`pin` now also affects a plain `mise upgrade --bump`.** If you have `pin` enabled, your next `mise upgrade --bump` rewrites non-exact requests such as `"22"` to exact versions such as `"22.1.0"`. Without `pin`, requests keep their precision as before. [#​14791](https://redirect.github.com/jdx/mise/pull/14791) ([@​jdx](https://redirect.github.com/jdx))
- **`mise unuse tool@version` only prunes the version you named.** It used to prune every unused version of the tool. If the named version is kept, mise now explains why, for example `[email protected].0 is kept: required by ~/proj/mise.toml`. `mise unuse node` without a version still prunes all unused versions of node. [#​14863](https://redirect.github.com/jdx/mise/pull/14863) ([@​jdx](https://redirect.github.com/jdx), [@​Strepto](https://redirect.github.com/Strepto))
#### Fixed
##### Lockfiles
- If a pipx tool selects its own Python (`python = "3.12"`), `mise use`, `mise up -l`, `mise lock pipx:...` and `mise lock python` now keep both that Python and the project's Python in `mise.lock`. Before, one entry was dropped and `mise install --locked` failed. [#​14794](https://redirect.github.com/jdx/mise/pull/14794) ([@​jdx](https://redirect.github.com/jdx), [@​AllDmeat](https://redirect.github.com/AllDmeat))
- `mise install tool@latest` no longer fails with "lockfile contains multiple resolutions" when nested configs pin different versions. The nearest lockfile now decides. [#​14818](https://redirect.github.com/jdx/mise/pull/14818) ([@​jdx](https://redirect.github.com/jdx))
- When a monorepo root config is in `.config/mise.toml`, the shared lockfile is now written to `.config/mise.lock` instead of `<root>/mise.lock`. [#​14860](https://redirect.github.com/jdx/mise/pull/14860) ([@​jdx](https://redirect.github.com/jdx), [@​fxsalazar](https://redirect.github.com/fxsalazar))
- `mise lock` for `pipx:` and `pypi:` tools now accepts PyPI simple indexes that respond with a PEP 691 `+html` content type, such as Azure Artifacts. [#​14852](https://redirect.github.com/jdx/mise/pull/14852) ([@​jdx](https://redirect.github.com/jdx), [@​alexanderlinne](https://redirect.github.com/alexanderlinne))
- Locked conda installs reuse cached downloads whose checksum is known, instead of downloading the package again. [#​14866](https://redirect.github.com/jdx/mise/pull/14866) ([@​zeitlinger](https://redirect.github.com/zeitlinger))
##### Install, upgrade and prune
- A project-level `[hooks].postinstall` now runs with the version that was just installed. Before, during `mise upgrade` of a fuzzy request such as `latest`, its `PATH` pointed at the old version. [#​14853](https://redirect.github.com/jdx/mise/pull/14853) ([@​jdx](https://redirect.github.com/jdx), [@​sam9191](https://redirect.github.com/sam9191))
- `mise prune` no longer aborts with "points to an unknown mise Python installation" when a pypi/pipx tool's receipt reaches mise's Python through a minor-version link such as `python/3.14`. [#​14857](https://redirect.github.com/jdx/mise/pull/14857), [#​14874](https://redirect.github.com/jdx/mise/pull/14874) ([@​jdx](https://redirect.github.com/jdx), [@​chancez](https://redirect.github.com/chancez))
- With `MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES` set, tracked `.tool-versions` files are still loaded. Before, `mise prune` could remove versions that those projects still used. [#​14779](https://redirect.github.com/jdx/mise/pull/14779) ([@​jdx](https://redirect.github.com/jdx))
- `java = "latest"` now selects the newest installed build when two installed versions differ only after `+` (for example `+7` and `+101`). [#​14876](https://redirect.github.com/jdx/mise/pull/14876) ([@​jdx](https://redirect.github.com/jdx), [@​javabrett](https://redirect.github.com/javabrett))
- `gem:` installs and `bundle install` no longer fail when `mise` is not on `PATH`. This applies to Rubies installed with this release or later. [#​14850](https://redirect.github.com/jdx/mise/pull/14850) ([@​jdx](https://redirect.github.com/jdx), [@​fxsalazar](https://redirect.github.com/fxsalazar))
- packslip tools no longer warn on every `mise outdated` or `mise up` about skipping a version that is past the `minimum_release_age` cutoff when that version is already installed. [#​14835](https://redirect.github.com/jdx/mise/pull/14835) ([@​jdx](https://redirect.github.com/jdx), [@​alx-xo](https://redirect.github.com/alx-xo))
- Homebrew tap formulae that define their own `Requirement` classes no longer break `mise bootstrap packages apply`. mise does not enforce these requirements and logs a warning about them. [#​14807](https://redirect.github.com/jdx/mise/pull/14807) ([@​jdx](https://redirect.github.com/jdx))
- `mise oci build` images that include `rust` now contain a working `cargo` and `rustc`, with `CARGO_HOME` and `RUSTUP_HOME` set, so containers no longer download the toolchain again on first use. The build now fails if rust comes from a rustup that mise does not manage. [#​14854](https://redirect.github.com/jdx/mise/pull/14854) ([@​jdx](https://redirect.github.com/jdx), [@​eiswind](https://redirect.github.com/eiswind))
##### Network and backends
- In official rustls Linux builds, mise falls back to its bundled Mozilla root certificates, with a warning, when no system CA certificates can be loaded (for example in minimal containers, or when `SSL_CERT_FILE` points to a missing file). Roots that do load are not changed. [#​14817](https://redirect.github.com/jdx/mise/pull/14817) ([@​jdx](https://redirect.github.com/jdx))
- GitHub assets now download correctly when `.netrc` has credentials for `github.com`. The reachability check no longer sends those credentials, which had caused a fallback to the rate-limited API. [#​14786](https://redirect.github.com/jdx/mise/pull/14786) ([@​jdx](https://redirect.github.com/jdx))
- `github:` tools for which mise-versions returned an empty release list (such as `github:caarlos0/svu`) now fall back to paged listing, so their versions are found. [#​14877](https://redirect.github.com/jdx/mise/pull/14877) ([@​jdx](https://redirect.github.com/jdx))
- Expired glab OAuth2 tokens are now ignored instead of sent. This fixes `401 Unauthorized` errors when installing `gitlab:` tools from public projects. [#​14873](https://redirect.github.com/jdx/mise/pull/14873) ([@​jdx](https://redirect.github.com/jdx), [@​chung1905](https://redirect.github.com/chung1905))
##### Windows
- Zip archives that contain read-only files, such as the Flutter SDK, now extract without "Access is denied". [#​14869](https://redirect.github.com/jdx/mise/pull/14869) ([@​jdx](https://redirect.github.com/jdx), [@​akiWagashi](https://redirect.github.com/akiWagashi))
- uv-locked `pipx:` tools whose console script names end in `.py` (for example `pipx:clang-format`) now install. [#​14825](https://redirect.github.com/jdx/mise/pull/14825) ([@​jdx](https://redirect.github.com/jdx))
- In tasks, `run_windows = []` now skips the task on Windows instead of running `run`. [#​14859](https://redirect.github.com/jdx/mise/pull/14859) ([@​jdx](https://redirect.github.com/jdx))
##### Tasks, bootstrap and generate
- `mise tasks list` now works as an alias for `mise tasks ls`. If you have a task named `list`, that task still runs. [#​14878](https://redirect.github.com/jdx/mise/pull/14878) ([@​jdx](https://redirect.github.com/jdx), [@​mcstafford-git](https://redirect.github.com/mcstafford-git))
- `mise bootstrap` no longer fails when a namespaced task such as `system:bootstrap` exists but no task is named exactly `bootstrap`. [#​14858](https://redirect.github.com/jdx/mise/pull/14858) ([@​jdx](https://redirect.github.com/jdx))
- `mise generate install-script --write` and `mise generate task-stubs` now write files that end with a newline. Existing stubs regenerate as before. [#​14819](https://redirect.github.com/jdx/mise/pull/14819) ([@​itochan](https://redirect.github.com/itochan))
- `curl https://mise.run | sh` no longer fails when `~/.config/curlrc` sets `write-out`. [#​14830](https://redirect.github.com/jdx/mise/pull/14830) ([@​jdx](https://redirect.github.com/jdx))
##### Dotfiles
- A `mode = "track"` entry declared in a `config.<env>.toml` stays tracked on machines that don't select that env. Before, those machines published a removal of the entry. [#​14815](https://redirect.github.com/jdx/mise/pull/14815) ([@​jdx](https://redirect.github.com/jdx))
- One saved enrollment under a parent directory that is now a symlink no longer stops automatic capture for all other tracked paths. It is reported as invalid instead. [#​14871](https://redirect.github.com/jdx/mise/pull/14871) ([@​jdx](https://redirect.github.com/jdx))
- The JSON schema now declares the keys of `[dotfile_groups.<name>.entries]`, so strict validators such as Tombi accept valid entries and report unknown keys. [#​14810](https://redirect.github.com/jdx/mise/pull/14810) ([@​jdx](https://redirect.github.com/jdx))
##### Other
- The aqua registry built into mise is now encoded the same way on every build, so builds of the same source are reproducible. [#​14809](https://redirect.github.com/jdx/mise/pull/14809) ([@​jdx](https://redirect.github.com/jdx))
#### Performance
- mise now checks `trusted_config_paths` after the cheaper trust rules and resolves each entry at most once per process. This speeds up `hook-env` when entries are on slow mounts such as autofs `/home` on macOS. [#​14875](https://redirect.github.com/jdx/mise/pull/14875) ([@​jdx](https://redirect.github.com/jdx))
#### Documentation
- The dotfiles docs now explain repo-only files, how existing repos fit in, undoing an accidental track, and what `add --no-apply`, `dot diff` and `exclude` do. [#​14829](https://redirect.github.com/jdx/mise/pull/14829), [#​14862](https://redirect.github.com/jdx/mise/pull/14862) ([@​jdx](https://redirect.github.com/jdx))
#### New Contributors
- [@​kwsantiago](https://redirect.github.com/kwsantiago) made their first contribution in [#​14822](https://redirect.github.com/jdx/mise/pull/14822)
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.10.17...v2026.10.18>
#### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.10.17`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.17): : Shell names in bootstrap login_shell, templated doctor checks, and a per-plugin vfox cache directory
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.15...vfox-v2026.10.17)
`bootstrap.user.login_shell` now accepts a shell name such as `fish` instead of a full path. `[doctor.checks]` can use templates, and vfox backend plugins get their own cache directory. This release also fixes PATH handling in zsh setups that deduplicate PATH, stale task cache hits, a pipx interpreter mix-up on macOS, and removes trust in the compromised eMudhra CA certificates.
It also includes the changes prepared for 2026.10.16, which was tagged but never published: relative and templated `write_targets` paths, version aliases from vfox backend plugins, keyring passwords for private PyPI indexes, `vfox-backend:` packslip plugin sources, and a change to where `find_up` starts (see Changed and Upgrading).
#### Added
- **`[bootstrap.user].login_shell` accepts a shell name.** A config shared across machines no longer needs to know where each system installs the shell. mise looks up the name when it checks or applies the setting, which happens after `bootstrap.packages` has installed the shell. It searches `PATH` first (never the mise shims directory), then common package-manager locations: `/opt/homebrew/bin`, `/usr/local/bin`, `/home/linuxbrew/.linuxbrew/bin`, `~/.linuxbrew/bin`, `/usr/bin` and `/bin`. If no executable is found, `mise bootstrap user apply` fails without changing `/etc/shells` or the account, and `status` reports `not installed`. `mise bootstrap user status` shows the path it found, and `--json` output has a new `resolved` field. Absolute paths work as before. [#​14770](https://redirect.github.com/jdx/mise/pull/14770) ([@​jdx](https://redirect.github.com/jdx))
```toml
[bootstrap.packages]
"brew:fish" = "latest"
[bootstrap.user]
login_shell = "fish"
```
- **Doctor checks support templates.** `run`, `description` and `hint` in `[doctor.checks.*]` are rendered with the template context of the config file that declares them, the same way hooks are. A check can now use a value from `[vars]` instead of hard-coding it. `dir` is not rendered. If a template fails, only that check reports `ERROR` and the other checks still run. Text that already contains `{{` or `{%` in these fields is now parsed as a template. [#​14771](https://redirect.github.com/jdx/mise/pull/14771) ([@​jdx](https://redirect.github.com/jdx))
```toml
[doctor.checks."project-a:env"]
description = "project-a has a .env file"
run = 'test -f {{ vars.repos_dir | quote }}/project-a/.env'
hint = "cp {{ vars.repos_dir }}/project-a/.env.example {{ vars.repos_dir }}/project-a/.env"
```
- **vfox plugins get `RUNTIME.cacheDirPath`.** This is a cache directory for each plugin at `$MISE_CACHE_DIR/plugins/<plugin-name>`. mise creates it before running any hook, and every hook of the plugin sees the same path. Unlike `pluginDirPath`, it is kept when the plugin is reinstalled. `mise cache clear` deletes it, so plugins must handle it being missing. It is `nil` when no cache directory is available. [#​14776](https://redirect.github.com/jdx/mise/pull/14776) ([@​jdx](https://redirect.github.com/jdx))
- **`settings.write_targets` accepts relative and templated paths.** Before, only absolute or `~/` paths worked, so dotfiles shared between machines with different `MISE_CONFIG_DIR` or `XDG_CONFIG_HOME` had to hardcode the config directory. Templates are now rendered, and a relative result is joined to the `config_root` of the settings file that declares it. For a global file that is `$HOME`, so the portable spelling uses the file's own directory. The resolved path must still be a global config file that mise loads. If a template fails to render, mise warns, and `mise use --global` fails with "must resolve to an absolute path" instead of writing to the default file. [#​14742](https://redirect.github.com/jdx/mise/pull/14742) ([@​jdx](https://redirect.github.com/jdx))
```toml
# ~/.config/mise/conf.d/settings.toml
[settings.write_targets]
tools = "{{ config_source | dirname }}/tools.toml"
```
- **vfox backend plugins can report version aliases.** `BackendListVersions` can return an `aliases` table, so a registry's moving names resolve to real versions. Before, `"mise-ghcup:ghc" = "recommended"` passed the literal string to the plugin, installed into `installs/.../recommended`, never followed the tag when it moved, and showed `recommended` in `mise ls` and the lockfile. Now `ghc@recommended` resolves to `9.10.3`, installs into `9.10.3/`, and the lockfile records `9.10.3`. Aliases you define in config still win. They are cached like the version list, and an expired cache still answers offline. Older mise versions ignore the `aliases` field, so plugins can adopt it right away. [#​14732](https://redirect.github.com/jdx/mise/pull/14732) ([@​jdx](https://redirect.github.com/jdx), [@​cprecioso](https://redirect.github.com/cprecioso))
```lua
return {
versions = { "9.8.4", "9.10.3", "9.14.1" },
aliases = { recommended = "9.10.3" },
}
```
- **`mise lock` and version listing work with a PyPI index that uses a keyring.** With an index such as Azure Artifacts and `artifacts-keyring`, `mise install` worked because uv read the password from its keyring provider, but mise's own requests sent no credentials and failed with `401 Unauthorized`. Set the new `pypi.keyring_provider` (`disabled` by default, or `subprocess`; env var `MISE_PYPI_KEYRING_PROVIDER`) and give the registry URL a username without a password. mise then runs `keyring get <url> <username>`, as uv does, and sends the result as HTTP Basic credentials when it lists versions and when `mise lock` reads a release's `requires-python`. The password is never written to the lockfile or the version cache. The `keyring` executable must be on `PATH`. If it is missing or has no entry, mise sends the request without credentials. [#​14733](https://redirect.github.com/jdx/mise/pull/14733) ([@​jdx](https://redirect.github.com/jdx))
```toml
[settings.pypi]
keyring_provider = "subprocess"
registry_url = "https://[email protected]/org/project/_packaging/feed/pypi/simple/{}/"
```
- **`vfox-backend:` works as a prefix for packslip plugin sources.** A vfox backend plugin can be installed from a signed packslip archive, both from the CLI and in `[plugins]`. Before, `mise plugins install vfox-backend:foo 'packslip:owner/repo#1.0.0'` failed with `packslip plugin sources require the vfox plugin type`. An explicit `asdf:` or `package:` prefix is still rejected, and the error now says "vfox or vfox-backend". The archive still declares `extensions.mise.plugin = "vfox"`. [#​14727](https://redirect.github.com/jdx/mise/pull/14727) ([@​jdx](https://redirect.github.com/jdx))
```sh
mise plugins install vfox-backend:my-backend 'packslip:your-org/my-backend#1.0.0'
```
- `mise bootstrap packages list` is now an alias for `status`, alongside `ls`. [#​14709](https://redirect.github.com/jdx/mise/pull/14709) ([@​himkt](https://redirect.github.com/himkt))
#### Changed
- **`find_up` in `env._.file` starts at the config root.** Every other relative path in a config resolves against the config root, but `find_up` started at the current directory. A relative `find_up` path now starts at the config root and walks up through its parents, which suits a monorepo whose root `.env` applies to every package. An absolute path starts at its own directory. A global config that wants to search from wherever mise runs can use `cwd`. The `env_file` setting still discovers dotenv files up from the current directory and is unchanged. See Upgrading. [#​14734](https://redirect.github.com/jdx/mise/pull/14734) ([@​jdx](https://redirect.github.com/jdx), [@​thernstig](https://redirect.github.com/thernstig))
```toml
# ~/.config/mise/config.toml
[env]
_.file = { path = "{{cwd}}/.env", find_up = true }
```
- **`allow_builds` approves only the packages it lists.** With the embedded aube installer, `allow_builds = ["re2"]` also ran the install scripts of every package on aube's bundled trusted-dependencies list, such as `dtrace-provider`. For a package list, mise now turns that default list off, so only the packages you name build. `allow_builds = true` and the default with no option are unchanged. This updates the embedded aube to 2.8.0. [#​14731](https://redirect.github.com/jdx/mise/pull/14731) ([@​jdx](https://redirect.github.com/jdx))
#### Fixed
- `exec()` in `[env]` values, and other commands mise runs with the pre-activation environment, can now find commands in a `_.path` directory that was already on `PATH` before activation, even if the shell deduplicates `PATH` (for example zsh with `typeset -U path PATH`). [#​14772](https://redirect.github.com/jdx/mise/pull/14772) ([@​jdx](https://redirect.github.com/jdx))
- With `task.source_freshness_hash_contents = true`, a task now re-runs when a source file is changed to content of the same size and its old mtime is restored (for example by `rsync -a`, `cp -p` or `touch -r`). On Unix, mise now also compares the file's ctime. Cache entries written by older versions are rehashed once. [#​14778](https://redirect.github.com/jdx/mise/pull/14778) ([@​jdx](https://redirect.github.com/jdx))
- On macOS, `pipx:` installs no longer fail when `aqua:aws/aws-cli` is in the toolset. Because macOS filesystems ignore case by default, mise's lookup for `python` matched aws-cli's executable `Python` shared library and passed it to uv as the interpreter. This lookup now requires the exact case. [#​14769](https://redirect.github.com/jdx/mise/pull/14769) ([@​jdx](https://redirect.github.com/jdx))
- An aqua registry template with an unterminated string literal now fails with an "unterminated string literal" error instead of hanging. Escaped quotes after backslashes are also detected correctly. [#​14752](https://redirect.github.com/jdx/mise/pull/14752) ([@​Huge](https://redirect.github.com/Huge), [@​jdx](https://redirect.github.com/jdx))
- The built-in npm backend no longer trusts the eight eMudhra intermediate CA certificates whose private keys were compromised. The fix comes from updating its bundled root certificates (`webpki-root-certs` 1.0.10, `rustls-webpki` 0.103.16). Builds that use the OS trust store are fixed by OS updates instead. [#​14781](https://redirect.github.com/jdx/mise/pull/14781) ([@​jdx](https://redirect.github.com/jdx))
- A `[bootstrap.compose]` project no longer reports drift on every run when a service uses a `service:` reference such as `network_mode: service:vpn`. Compose hashes the reference as written but stamps the container with the hash of the resolved `container:<id>`, so the two never matched. mise now pins these references (`network_mode`, `ipc`, `pid`, `volumes_from`) to the running container before it asks compose for the hash. This needs an explicit `files` list in the project's config. Projects without one hash as before. [#​14729](https://redirect.github.com/jdx/mise/pull/14729) ([@​jdx](https://redirect.github.com/jdx))
- vfox plugins now keep symlinks when they extract `.zip` archives returned by `PreInstall`. Before, entries such as `bin/npm -> ../lib/node_modules/npm/bin/npm-cli.js` became regular files holding the link target, and the tool failed with `No such file or directory`. Links that resolve outside the install directory are still rejected. The `http:` backend and tarballs were not affected. [#​14730](https://redirect.github.com/jdx/mise/pull/14730) ([@​jdx](https://redirect.github.com/jdx))
- `[daemons.<name>] task = "worker"` now finds a file task such as `.mise/tasks/worker.sh`, as `mise run worker` does. Before, it failed with `daemon srv runs unknown task "worker"` unless you wrote `worker.sh`. [#​14741](https://redirect.github.com/jdx/mise/pull/14741) ([@​jdx](https://redirect.github.com/jdx))
- On Windows, `mise self-update` no longer replaces the winget `mise-shim.exe` link with a copy. It updates the real `mise-shim.exe` next to the real `mise.exe`. Before, `mise reshim` kept warning that the shim was older than mise. [#​14737](https://redirect.github.com/jdx/mise/pull/14737) ([@​jdx](https://redirect.github.com/jdx))
- An inherited `[dotfiles]` entry turned off with only `enabled = false` no longer prints `no recognized operation (block, source, or line), ignoring entry` on every command. Other tables with no recognized operation, such as a misspelled `line`, still warn. [#​14726](https://redirect.github.com/jdx/mise/pull/14726) ([@​jdx](https://redirect.github.com/jdx), [@​ponko2](https://redirect.github.com/ponko2))
#### Upgrading
- **`find_up` in a global config:** a relative `find_up` entry in `env._.file` used to search from the current directory. It now searches from the config root, which is `~` for a global config, so it no longer finds project files. To keep the old behavior, put `{{cwd}}/` in front of the path. `find_up` was added in 2026.10.12.
#### Documentation
- The dotfiles docs now explain that a group entry with only `permissions` does not inherit the group's `mode`, so it deploys nothing. Removing `mode` from an entry that used to deploy a file leaves that file orphaned, and `--prune` deletes it. To deploy a file and set its permissions, use `{ mode = "copy", permissions = "0600" }`. [#​14768](https://redirect.github.com/jdx/mise/pull/14768) ([@​jdx](https://redirect.github.com/jdx))
#### New Contributors
- [@​Huge](https://redirect.github.com/Huge) made their first contribution in [#​14752](https://redirect.github.com/jdx/mise/pull/14752)
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.10.15...v2026.10.17>
#### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xODAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjE4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
> [!NOTE]
> This PR body was truncated due to platform limits.
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [jdx/mise](https://redirect.github.com/jdx/mise) | patch | `v2026.10.8` → `v2026.10.15` |
---
### Release Notes
<details>
<summary>jdx/mise</summary>
### [`v2026.10.15`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.15): : Default minimum_release_age covers every backend, plus a PowerShell installer
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.14...vfox-v2026.10.15)
The default 24-hour `minimum_release_age` now applies to every backend. Many more backends report release dates, so the cooldown can actually hold new versions back, and mise warns when it installs a version it couldn't date. This release also adds a PowerShell installer for Windows, `read_json`/`read_yaml`/`read_toml` template functions, `dotnet@lts`/`dotnet@sts`, and new dotfiles options.
#### Changed
- **The default `minimum_release_age` applies to every backend.** The built-in 24h cooldown used to cover only backends that reported release dates (aqua, cargo, core, github, npm, pypi and others). asdf, vfox, conda, dotnet, `http:` and `s3:` tools had no cutoff at all. Now every backend gets the cooldown. A tool whose only version is less than 24h old now resolves to "no versions found", as aqua and github tools already did. To opt a tool out, add it to `minimum_release_age_excludes`. To turn the cooldown off, set `minimum_release_age = "0s"`. [#​14701](https://redirect.github.com/jdx/mise/pull/14701) ([@​jdx](https://redirect.github.com/jdx))
- **mise warns when it can't check a version's release date.** A version with no known date still passes the cutoff, but `mise install`, `mise upgrade` and `mise use` now print a one-time warning naming the version. Exact pins you wrote yourself don't trigger it. `mise env`, `mise ls`, `mise outdated` and `mise ls-remote` never print it. [#​14694](https://redirect.github.com/jdx/mise/pull/14694) ([@​jdx](https://redirect.github.com/jdx))
```
WARN asdf:[email protected] has no release date, so the ... cutoff cannot be checked and it is allowed (exclude it with minimum_release_age_excludes to silence this)
```
- **More backends report release dates, so the cooldown applies to them:**
- conda versions use the channel's earliest index timestamp. [#​14693](https://redirect.github.com/jdx/mise/pull/14693)
- aqua packages that take versions from git tags (`version_source: github_tag`, such as `aws/aws-cli`, `docker/cli` and `cockroachdb/cockroach`) are now dated. [#​14691](https://redirect.github.com/jdx/mise/pull/14691)
- dotnet dates come from Microsoft's releases index. deno and erlang dates come from their GitHub releases. [#​14692](https://redirect.github.com/jdx/mise/pull/14692)
- Every python version now has a date, and so do many more ruby versions (from ruby-lang.org, Maven Central for JRuby, and GitHub for TruffleRuby). Rust's `stable`, `beta` and `nightly` channels are dated too. With an explicit past cutoff, `rust@stable` resolves to the newest stable release that is old enough, and `beta`/`nightly` resolve to a dated build from before the cutoff. [#​14697](https://redirect.github.com/jdx/mise/pull/14697)
- The dart, flutter, nim, julia, nomad-pack, sentinel, tfc-agent, android-cli, cursor-agent and twg registry tools now report dates. [#​14698](https://redirect.github.com/jdx/mise/pull/14698)
All by [@​jdx](https://redirect.github.com/jdx).
- **Version lists for more backends come from the mise-versions host.** `npm:`, `pipx:`, `cargo:`, `gem:`, `go:`, `dotnet:` and `spm:` tools now list versions from mise-versions, like other registry tools, instead of going to their own source. So do http/s3 tools with a `version_list_url`. If you redirect a source, mise still lists from that source directly. That covers a custom npm registry or `npm.shell_out`, `pypi.registry_url`, a non-default `GOPROXY`, `cargo.registry_name`, a custom gem source, `dotnet.registry_url`, S3 endpoint overrides, and local listing options. conda always lists from its channel. The host cache TTL now follows the tool's `minimum_release_age`. To list everything from the source, set `MISE_USE_VERSIONS_HOST=0`. [#​14700](https://redirect.github.com/jdx/mise/pull/14700) ([@​jdx](https://redirect.github.com/jdx))
#### Added
- **PowerShell installer for Windows.** It's published with each release as `install.ps1` and served from mise.run at `/powershell` and `/pwsh`, so you pipe it into `iex` with `irm`. It works on PowerShell 5.1+ and doesn't need admin rights. It installs the newest release that is at least 24h old, or `MISE_VERSION` if set. The download is verified against `SHASUMS256.txt` from GitHub Releases. `mise.exe` and `mise-shim.exe` go into `~\.local\bin`, and that directory is added to your user `Path`. Re-running it upgrades an existing install. Options include `MISE_INSTALL_PATH`, `MISE_INSTALL_MODIFY_PATH=0`, `MISE_INSTALL_SHIMS_PATH=1` and `MISE_INSTALL_FROM_GITHUB=1`. See the "Installing mise" docs for the full command. [#​14660](https://redirect.github.com/jdx/mise/pull/14660) ([@​jdx](https://redirect.github.com/jdx), [@​lhs-12](https://redirect.github.com/lhs-12))
- **`read_json()`, `read_yaml()` and `read_toml()` template functions** parse a file so a template can use a value from it. This saves copying a version from `package.json` or `Pulumi.yaml` into `mise.toml` by hand. Relative paths resolve from the config file's directory. A missing key is an error unless you add `| default(value="...")`. Like `read_file()`, these functions need a trusted config, and they don't work in safe mode, `.miserc.toml` or OCI dotfile templates. [#​14705](https://redirect.github.com/jdx/mise/pull/14705) ([@​jdx](https://redirect.github.com/jdx), [@​edahlseng](https://redirect.github.com/edahlseng))
```toml
[tools]
node = "{{ read_json(path='package.json')['volta']['node'] }}"
pulumi = "{{ read_yaml(path='Pulumi.yaml')['requiredPulumiVersion'] }}"
```
- **`dotnet@lts` and `dotnet@sts`** resolve to the newest SDK in the current LTS or STS channel, using Microsoft's release index. Preview, go-live and end-of-life channels are skipped. A `lts` alias you define in `[tool_alias.dotnet.versions]` still takes precedence. Runtime-only installs still need an exact version. [#​14683](https://redirect.github.com/jdx/mise/pull/14683) ([@​jdx](https://redirect.github.com/jdx))
- **`mise bootstrap --prune-dotfiles`** removes dotfiles that are no longer deployed, the same way `mise dot apply --prune` does, so `mise bootstrap --upgrade --prune-dotfiles` handles everything in one run. The prune runs at the end of the dotfiles phase. It respects `--dry-run`, `--yes` and `--skip dotfiles`. Copies you edited are left in place. [#​14681](https://redirect.github.com/jdx/mise/pull/14681) ([@​jdx](https://redirect.github.com/jdx), [@​thernstig](https://redirect.github.com/thernstig))
- **`dotfiles.windows_symlinks`** (default `false`) makes `symlink` and `symlink-each` create real file symlinks on Windows. With it on, apply fails if Windows refuses to create a link, instead of silently copying. To create symlinks, Windows needs Developer Mode or an elevated shell. If you turn the setting back off, `mise dot unapply` needs `--force` on entries that still hold links. [#​14682](https://redirect.github.com/jdx/mise/pull/14682) ([@​jdx](https://redirect.github.com/jdx))
```toml
[settings.dotfiles]
windows_symlinks = true
```
- **`http:` tools can report release dates** with the new `version_date_expr` option. It maps versions to dates from the `version_list_url` response. Use `version_date_url` to read the dates from a different URL, and `version_date_next_expr` to follow paged listings (same host only). Dates can be RFC 3339, `YYYY-MM-DD` or HTTP dates. [#​14696](https://redirect.github.com/jdx/mise/pull/14696) ([@​jdx](https://redirect.github.com/jdx))
- **vfox plugins can report release dates.** An `Available` or `BackendListVersions` hook can return `created_at` (RFC 3339) for each version. Plain version strings still work. [#​14695](https://redirect.github.com/jdx/mise/pull/14695) ([@​jdx](https://redirect.github.com/jdx))
- `mise tasks -a` is a short alias for `mise tasks --all`. [#​14674](https://redirect.github.com/jdx/mise/pull/14674) ([@​williamsjokvist](https://redirect.github.com/williamsjokvist))
#### Fixed
- `mise fmt` no longer breaks multiline inline tables (TOML 1.1). It used to pull comments out of the table and drop indentation. Now it leaves these tables exactly as written. [#​14670](https://redirect.github.com/jdx/mise/pull/14670) ([@​jdx](https://redirect.github.com/jdx), [@​ponko2](https://redirect.github.com/ponko2))
- If one task's `dir` template fails to render, other task commands keep working. Before, every command failed, including `mise tasks validate`. Now `mise tasks validate` reports the broken task as `invalid-directory-template`, and only running that task fails. [#​14680](https://redirect.github.com/jdx/mise/pull/14680) ([@​jdx](https://redirect.github.com/jdx))
- aqua tools now find their binaries in macOS universal archives, such as fastfetch 2.70.0. [#​14665](https://redirect.github.com/jdx/mise/pull/14665) ([@​jdx](https://redirect.github.com/jdx))
- npm: lifecycle scripts approved by `allow_builds` now run even when `~/.npmrc` sets `ignore-scripts=true`. [#​14661](https://redirect.github.com/jdx/mise/pull/14661) ([@​jdx](https://redirect.github.com/jdx))
- npm: `mise lock` no longer fails when your aube config sets a different default lockfile, such as `pnpm-lock.yaml`. [#​14659](https://redirect.github.com/jdx/mise/pull/14659) ([@​jdx](https://redirect.github.com/jdx))
- `.7z` tool archives now extract when mise's data directory path contains `..`, for example in a localized mise setup. [#​14657](https://redirect.github.com/jdx/mise/pull/14657) ([@​jdx](https://redirect.github.com/jdx), [@​sevenc-nanashi](https://redirect.github.com/sevenc-nanashi))
- The `mise-shim.exe` in the Windows release now keeps its version tag, so `mise doctor` and `mise reshim --force` stop reporting it as outdated. The warning goes away after you update and run `mise reshim --force`. [#​14656](https://redirect.github.com/jdx/mise/pull/14656) ([@​jdx](https://redirect.github.com/jdx))
- On Windows, `symlink-each` dotfiles messages and dry-run previews now say the files were copied rather than symlinked. [#​14654](https://redirect.github.com/jdx/mise/pull/14654) ([@​jdx](https://redirect.github.com/jdx), [@​lhs-12](https://redirect.github.com/lhs-12))
- Rust: with a `RUSTUP_DIST_SERVER` mirror configured and GitHub unreachable, mise now lists the `stable`, `beta` and `nightly` channels instead of failing, so `rust@stable` installs through the mirror. [#​14662](https://redirect.github.com/jdx/mise/pull/14662) ([@​jdx](https://redirect.github.com/jdx))
- On Windows, `http:` installs of large archives no longer fail with "Access is denied" while antivirus is scanning the extracted files. mise now retries the final move for up to about a minute. [#​14703](https://redirect.github.com/jdx/mise/pull/14703) ([@​jdx](https://redirect.github.com/jdx))
#### Documentation
- New [mise.toml playground](https://mise.jdx.dev/configuration/playground.html): a schema-aware editor with hover help, completion and error checking. You can share a config as a link. Every `mise.toml` example in the docs now shows hover help on its keys. [#​14673](https://redirect.github.com/jdx/mise/pull/14673), [#​14686](https://redirect.github.com/jdx/mise/pull/14686) ([@​jdx](https://redirect.github.com/jdx))
- The [mise.toml reference](https://mise.jdx.dev/configuration/reference.html) is now a searchable key explorer grouped by topic. Each key shows its type, default and a real example. Nearly every key now has a description, and these also appear in `mise config explain`. [#​14687](https://redirect.github.com/jdx/mise/pull/14687), [#​14690](https://redirect.github.com/jdx/mise/pull/14690), [#​14688](https://redirect.github.com/jdx/mise/pull/14688) ([@​jdx](https://redirect.github.com/jdx))
- The fnox secrets page now covers setup, CI and migration. The dotnet page explains how private feeds authenticate. [#​14675](https://redirect.github.com/jdx/mise/pull/14675), [#​14679](https://redirect.github.com/jdx/mise/pull/14679) ([@​jdx](https://redirect.github.com/jdx))
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.10.14...v2026.10.15>
#### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.10.14`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.14): : Global override config, mise config explain, and stricter tool option checks
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.13...vfox-v2026.10.14)
A global `config.override.toml` can now take precedence over project config, and `mise config explain` describes each key in a config file. Paranoid mode can be turned on per category, and in that mode dotenv files need their own content-bound trust. Installs now fail when a tool has an option its backend doesn't read, which affects existing configs (see Changed).
#### Added
- **Global override files.** `~/.config/mise/config.override.toml`, and `config.<env>.override.toml` for each `MISE_ENV`, rank above every project file, including `mise.local.toml` and `mise.<env>.toml`. This covers `[env]`, `[tools]`, `[settings]`, `[tasks]`, hooks and the other sections. Anything the override file doesn't set still comes from the project. mise never writes to these files by default. To write to one, pass `--override` to `use`, `unuse`, `set`, `unset`, `settings set|add|unset` or `config get|set`. A tool declared in an override file resolves from the global `mise.lock` and is exempt from the project's `--locked` check. If `MISE_GLOBAL_CONFIG_FILE` is set, override files are not loaded. `mise config ls` shows a `Tier` column and `mise doctor` labels the files. [#​14610](https://redirect.github.com/jdx/mise/pull/14610) ([@​jdx](https://redirect.github.com/jdx))
```toml
# ~/.config/mise/config.override.toml
[env]
AWS_PROFILE = "personal"
[tools]
node = "24"
```
- **`mise config explain [KEY]`** lists each key a config file sets, with its line number and its description from the schema. It flags unknown keys with a "did you mean" suggestion and marks deprecated keys. It reads the file as plain TOML, so it also works on a config mise refuses to load. Pass a key such as `tasks` to show only that section, `--json` for machine-readable output, and `--file`, `--global`, `--system` or `--override` to pick a file. [#​14642](https://redirect.github.com/jdx/mise/pull/14642) ([@​jdx](https://redirect.github.com/jdx))
- **Paranoid mode can be turned on per category.** `paranoid` now accepts a list of `config`, `env_files`, `plugins` and `provenance` in addition to `true`/`false`. `MISE_PARANOID=config,env_files` also works. `true` still turns on all four categories. An unknown category name is an error. [#​14609](https://redirect.github.com/jdx/mise/pull/14609) ([@​jdx](https://redirect.github.com/jdx), [@​thernstig](https://redirect.github.com/thernstig))
```toml
[settings]
paranoid = ["env_files"]
```
- **`env_file` takes several filenames**, for example `env_file = [".env", ".env.local"]` or `MISE_ENV_FILE=.env:.env.local`. The file nearest the current directory wins. Within one directory, a name later in the list wins. A single string still works. [#​14606](https://redirect.github.com/jdx/mise/pull/14606) ([@​jdx](https://redirect.github.com/jdx), [@​thernstig](https://redirect.github.com/thernstig))
- **A `find_up` entry in `env._.file` can search several names together.** Give one entry a `path` list, and mise searches directory by directory. The closest directory wins, then the later name within a directory. With two separate entries, a `.env.local` in a parent directory still overrides the project's `.env`. The docs now explain this difference and how `env_file` differs from `_.file`. [#​14620](https://redirect.github.com/jdx/mise/pull/14620), [#​14602](https://redirect.github.com/jdx/mise/pull/14602) ([@​jdx](https://redirect.github.com/jdx))
```toml
[env]
_.file = { path = [".env", ".env.local"], find_up = true }
```
- **`#MISE` headers in file tasks accept the same keys as `[tasks.<name>]`**, including `timeout`, `vars` and the `deny_*`/`allow_*` sandbox keys. Before, these keys were ignored with a warning. If one header value is invalid, mise warns and skips that key, and every other task still loads. An invalid `confirm` or `deny_*` value is still an error, so a typo can't remove a confirmation prompt or a sandbox restriction. Before, a template named with `extends` overrode a header's `silent`. Now the header's value wins. [#​14637](https://redirect.github.com/jdx/mise/pull/14637) ([@​jdx](https://redirect.github.com/jdx))
- **Interactive `mise.toml` reference** in the docs at [configuration/reference](https://mise.jdx.dev/configuration/reference.html). It lists every key with its type, choices and default, and you can filter keys and link to them directly. Plain Markdown copies are also published for agents. [#​14641](https://redirect.github.com/jdx/mise/pull/14641) ([@​jdx](https://redirect.github.com/jdx))
#### Changed
- **Installs fail on tool options the backend doesn't read.** Before, such options were silently ignored. A typo or a key meant for another backend now stops the install, and the error names the option: `cargo:eza: option 'asset_pattern' is not used by the cargo backend`. Keys under `platforms` are checked too. So far this applies to the cargo, conda, gem, github, gitlab, forgejo, go, http, npm, packslip, pipx, s3, spinel, spm and ubi backends. aqua, plugin and core-language tools are not checked. The npm backend accepts the `checksum` option that comes from a `packageManager` field in `package.json`. [#​14629](https://redirect.github.com/jdx/mise/pull/14629), [#​14655](https://redirect.github.com/jdx/mise/pull/14655) ([@​jdx](https://redirect.github.com/jdx))
- **Paranoid mode needs content-bound trust for env files.** In paranoid mode, files loaded through `_.file`, found by the `env_file` setting, or run by `_.source` each need their own trust. Editing one of these files revokes its trust. Before, trusting `mise.toml` also approved these files, and later edits went unchecked. Running `mise trust` with no path trusts the project's config and every env file it loads. The error names the file but prints none of its values. To exempt a file by path, add it to `trusted_config_paths` in your global config. With a category list, this check belongs to `env_files`. [#​14604](https://redirect.github.com/jdx/mise/pull/14604) ([@​jdx](https://redirect.github.com/jdx), [@​thernstig](https://redirect.github.com/thernstig))
- **More specific config error messages.**
- A warning about an unknown `mise.toml` key now gives the line and column, and suggests a close match, for example `mise.toml:5:1: settings.experimantal (did you mean experimental?)`. [#​14639](https://redirect.github.com/jdx/mise/pull/14639) ([@​jdx](https://redirect.github.com/jdx))
- A wrong value for a hook, a task `run`/`depends` entry or an `[env]` variable now says which forms are accepted, or names the unknown key. Before, the error was `data did not match any variant of untagged enum`. An unknown key in a `run` or `depends` table now gets a warning. Before, it was silently ignored. [#​14640](https://redirect.github.com/jdx/mise/pull/14640) ([@​jdx](https://redirect.github.com/jdx))
- **`[bootstrap.linux.firewall]` is validated on every OS.** macOS and Windows still skip the section at bootstrap time, but an invalid value such as `backend = "iptables"` is now an error there too. [#​14615](https://redirect.github.com/jdx/mise/pull/14615) ([@​jdx](https://redirect.github.com/jdx))
- **Editor schema updates.** Editors now flag unknown keys in most `[bootstrap]` tables and in `[dotfiles]` entries. The schema now documents launchd `keep_alive_on_failure` and `nice`, and dotfile `autosave` and `enabled`. It also accepts valid configs it used to reject: templated `login_shell`, `queue_directories` and `umask`, nested macOS defaults values, and `tools` on `[vars]` entries. On Windows, `[bootstrap.brew].adopt` no longer causes an unknown-field warning. [#​14616](https://redirect.github.com/jdx/mise/pull/14616), [#​14644](https://redirect.github.com/jdx/mise/pull/14644), [#​14613](https://redirect.github.com/jdx/mise/pull/14613) ([@​jdx](https://redirect.github.com/jdx))
- `mise dot status` and `mise dot sync` are faster with many tracked files. They start one git process per tracked file instead of three, which took about 10s down to 4s for 860 files. [#​14607](https://redirect.github.com/jdx/mise/pull/14607) ([@​waynehoover](https://redirect.github.com/waynehoover))
#### Fixed
- With an external rustup that keeps its proxies in a shared directory, such as pacman's `/usr/bin`, mise no longer puts that directory ahead of its own tools. Before, `mise exec -- node` could run the system Node. Only the Rust proxies are now exposed, through a directory that mise owns. [#​14597](https://redirect.github.com/jdx/mise/pull/14597) ([@​jdx](https://redirect.github.com/jdx))
- The cargo backend now honors `rename_exe`. Before, it ignored the option and installed the executable under its original name. [#​14626](https://redirect.github.com/jdx/mise/pull/14626) ([@​jdx](https://redirect.github.com/jdx))
- Locked `pypi:` installs through uv now pass the configured mise Python to `uv sync`. Before, mise passed an empty path, so uv could pick another interpreter and fail on `--no-build` tools such as `yamllint`. [#​14593](https://redirect.github.com/jdx/mise/pull/14593) ([@​jdx](https://redirect.github.com/jdx), [@​hollow](https://redirect.github.com/hollow))
- When the TLS root store or a CA file can't be loaded, the npm backend now reports an error instead of crashing mise with a core dump. [#​14595](https://redirect.github.com/jdx/mise/pull/14595) ([@​jdx](https://redirect.github.com/jdx))
- On fish, mise no longer recurses until fish hits its call stack limit after `mise implode`. [#​14594](https://redirect.github.com/jdx/mise/pull/14594) ([@​jdx](https://redirect.github.com/jdx), [@​thernstig](https://redirect.github.com/thernstig))
- `mise bootstrap` now finds Nix in `/nix/var/nix/profiles/default/bin` when a `pre-packages` hook installed it earlier in the same run, so `nix:` packages install. [#​14596](https://redirect.github.com/jdx/mise/pull/14596) ([@​jdx](https://redirect.github.com/jdx))
- `MISE_WATCH_FILES_GIT_REWRITTEN` is no longer set when HEAD stayed on the same commit, for example after `git checkout -b`, `git reset` or `git branch -m`. Before, format-on-edit hooks skipped files you had just edited. [#​14585](https://redirect.github.com/jdx/mise/pull/14585) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- Command wrapper templates can now use `config_root` and `config_source`. Relative paths in template functions resolve from the wrapper's config file instead of the current directory. [#​14628](https://redirect.github.com/jdx/mise/pull/14628) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
#### Upgrading
- **Unsupported tool options:** if an install now fails with `option '...' is not used by the ... backend`, remove the option or fix its spelling. `mise config explain tools` shows which keys mise doesn't recognize.
- **Paranoid mode:** after upgrading, run `mise trust` in each project to approve its env files. Run it again after editing them. If you only want the env-file check, set `paranoid = ["env_files"]`.
- **Firewall config on macOS and Windows:** if a shared config has an invalid `[bootstrap.linux.firewall]` value, it now fails to load on macOS and Windows too. Correct the value.
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.10.13...v2026.10.14>
#### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.10.13`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.13): : Untrusted project configs can no longer change settings
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.12...vfox-v2026.10.13)
mise now ignores `[settings]` in a project config until you trust it. This release also adds per-version-range backend options to the registry and template support for command wrappers and `[bootstrap.repos]`. It fixes several bugs in lockfiles, tasks and multi-version tool options.
#### Security
- **`[settings]` from untrusted project configs is ignored.** Before, a cloned repo's `mise.toml` could change settings as soon as mise found it, with no trust prompt. That included settings that redirect downloads or feed build commands, such as `node.mirror_url`, `python.pyenv_repo` and `ruby.precompiled_url`. These settings now apply only after `mise trust`, like `[env]`, `[hooks]` and `[tools]` options already did. Trusted projects, global and system config, environment variables and CLI flags work as before. Commands that trust the active config implicitly (`mise run`, `mise exec`, `mise install`) reload settings after trusting it, so the project's settings still apply to that same command. Settings files are now parsed once per load. [#​14538](https://redirect.github.com/jdx/mise/pull/14538), [#​14553](https://redirect.github.com/jdx/mise/pull/14553) ([@​jdx](https://redirect.github.com/jdx))
For example, if an untrusted repo sets `[settings.python] pyenv_repo` to its own URL, `mise settings get python.pyenv_repo` returns the default pyenv repository until you run `mise trust`.
- mise's own `zip` dependency moved to 9.x, which fixes GHSA-4684-h2q9-2vcp. Older versions applied Unix permissions through extracted symlinks without checking that the target stayed inside the destination. mise uses this code to extract downloaded `.zip` tool archives. [#​14577](https://redirect.github.com/jdx/mise/pull/14577) ([@​jdx](https://redirect.github.com/jdx))
#### Added
- **One registry backend can carry different options for each version range.** A registry entry can list the same backend more than once, each time with its own `min_version`/`max_version` and `options`. Tools whose release assets changed at some version can then stay on one backend. Two entries can't give the same version different options unless their `platforms` don't overlap. Table syntax such as `tool = { version = "1.4.0" }` now takes its registry defaults from the entry that version selects. Older mise releases apply only the first entry's options to every version. [#​14543](https://redirect.github.com/jdx/mise/pull/14543) ([@​jdx](https://redirect.github.com/jdx))
```toml
backends = [
{ full = "github:example/tool", min_version = "2.0.0", options = { asset_pattern = "tool-v2-*" } },
{ full = "github:example/tool", max_version = "2.0.0", options = { asset_pattern = "tool-*" } },
]
```
- **`mise ls-remote` lists every version range of a registry tool.** When a tool's backends serve different version ranges, mise now lists each range from the backend that serves it. Before, it listed only the first backend's range. For example, `mise ls-remote hk` now starts at 0.1.4 instead of 1.58.1. Explicit backends, overrides, `--all` and `--strict-metadata` behave as before. [#​14544](https://redirect.github.com/jdx/mise/pull/14544) ([@​jdx](https://redirect.github.com/jdx))
- **Command wrapper values render as templates.** `command`, `args` and `env` in `[wrappers]` can use `vars`, `env` and the usual template functions. `tools` and `config_root` are not available. A command that renders blank is an error. Use `{% raw %}` to keep literal braces, such as Docker's `{{.Names}}`. [#​14565](https://redirect.github.com/jdx/mise/pull/14565) ([@​jdx](https://redirect.github.com/jdx))
```toml
[wrappers.foo]
command = "foo-real"
args = ["--mode={{ vars.mode }}"]
env = { FOO_HOME = "{{ [xdg_data_home, 'foo'] | join_path }}" }
```
- **`[bootstrap.repos]` supports templated `url`/`ref` and clone options.** `url` and `ref` render from `[vars]` or the process environment. Values from a config's `[env]` table are not available. `filter`, `depth` and `submodules = true` are passed to the first `git clone` as `--filter`, `--depth` and `--recurse-submodules`. Existing checkouts are left as they are. `depth` can't be combined with a commit SHA or a `refs/…` ref. [#​14548](https://redirect.github.com/jdx/mise/pull/14548) ([@​jdx](https://redirect.github.com/jdx), [@​ovidiubuligan](https://redirect.github.com/ovidiubuligan))
```toml
[bootstrap.repos]
"~/src/large" = { url = "[email protected]:example/large.git", ref = "{{ vars.branch }}", filter = "blob:none", depth = 1 }
```
- **`{{ system_brew_prefix }}` template variable.** It resolves to the Homebrew prefix that `mise bootstrap` installs into: `/opt/homebrew` on macOS and `/home/linuxbrew/.linuxbrew` on Linux, or the value of `MISE_SYSTEM_BREW_PREFIX`. It does not detect a Homebrew install somewhere else. `[bootstrap.user].login_shell` now renders templates too, so `login_shell = "{{ system_brew_prefix }}/bin/zsh"` works. [#​14572](https://redirect.github.com/jdx/mise/pull/14572), [#​14570](https://redirect.github.com/jdx/mise/pull/14570) ([@​jdx](https://redirect.github.com/jdx))
- **vfox `PreInstall` hooks can return a `headers` table** next to `url` and `sha256`. Plugins can now download private or token-gated artifacts through the normal install path, which handles checksums, retries and lockfile URLs. Headers are sent only to the origin of `url`, are dropped on cross-origin redirects, are redacted in debug output and are never written to `mise.lock`. An explicit `Authorization` header overrides netrc and the automatic GitHub token. [#​14531](https://redirect.github.com/jdx/mise/pull/14531) ([@​jdx](https://redirect.github.com/jdx))
- **`mise doctor` reports a stale `mise-shim.exe` on Windows.** In `windows_shim_mode = "exe"`, shims are copies of the `mise-shim.exe` that sits beside `mise.exe`. If that template is older than mise, or has no version tag (every template built before this release), `mise doctor` reports it and `mise reshim` warns. To fix it, update mise with the package manager that installed it, or run `mise self-update`, and then run `mise reshim --force`. [#​14586](https://redirect.github.com/jdx/mise/pull/14586) ([@​jdx](https://redirect.github.com/jdx))
#### Fixed
- **Lockfiles**
- Running `mise lock` on Windows now records `ruby` entries for Windows, Linux and macOS platforms. Before, it skipped them, and `mise install --locked` then failed. [#​14520](https://redirect.github.com/jdx/mise/pull/14520), [#​14529](https://redirect.github.com/jdx/mise/pull/14529) ([@​jdx](https://redirect.github.com/jdx))
- Commands that rewrite `mise.lock` without locking again, such as `mise link`, no longer delete other platforms' option variants (for example, per-platform `asset_pattern` entries). [#​14519](https://redirect.github.com/jdx/mise/pull/14519) ([@​jdx](https://redirect.github.com/jdx))
- A `mise link` for one version of a tool no longer makes `mise install --locked` fail for that tool's other versions. A link now bypasses the lockfile only when the requested version could select it. [#​14539](https://redirect.github.com/jdx/mise/pull/14539) ([@​jdx](https://redirect.github.com/jdx))
- `mise install --locked` for Java no longer fetches the mise-java catalog when `mise.lock` already has the download URL, so locked installs work in air-gapped or proxied environments. [#​14534](https://redirect.github.com/jdx/mise/pull/14534) ([@​jdx](https://redirect.github.com/jdx))
- **Tasks and shims**
- `mise run` no longer hangs when parallel tasks need to install the same tool. [#​14536](https://redirect.github.com/jdx/mise/pull/14536) ([@​jdx](https://redirect.github.com/jdx))
- Running `mise install` inside a task no longer removes the shims for that task's `lazy` tools. [#​14533](https://redirect.github.com/jdx/mise/pull/14533) ([@​jdx](https://redirect.github.com/jdx))
- Task hooks (such as `postinstall = { task = "setup" }`) and `watch_files` task hooks now run with mise even when a tool shim triggered them. Before, they could fail with errors like `jq: Unknown option --cd`. [#​14550](https://redirect.github.com/jdx/mise/pull/14550) ([@​jdx](https://redirect.github.com/jdx), [@​alitas](https://redirect.github.com/alitas))
- `mise watch` exits quietly with status 130 when you interrupt watchexec with Ctrl+C, instead of printing an error. [#​14541](https://redirect.github.com/jdx/mise/pull/14541) ([@​jdx](https://redirect.github.com/jdx))
- **Per-version tool options**
- When a `github:`, `gitlab:` or `forgejo:` tool lists several versions in config, each version now installs with its own options. Before, an option such as `rename_exe` set only on the first entry applied to every version. [#​14537](https://redirect.github.com/jdx/mise/pull/14537) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- `vfox:` plugin hooks now receive only the options configured for the version they handle. [#​14562](https://redirect.github.com/jdx/mise/pull/14562) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- `mise install` now restores `cargo`, `rustc` and the host's `rust-std` when they are missing from a Rust toolchain with the `minimal` or `default` profile. Before, mise reported such a toolchain as installed. [#​14525](https://redirect.github.com/jdx/mise/pull/14525) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562), [@​risu729](https://redirect.github.com/risu729))
- The uv, pip and poetry deps providers now run again after mise recreates a deleted venv in a later process. Before, the new venv stayed empty. [#​14532](https://redirect.github.com/jdx/mise/pull/14532) ([@​halms](https://redirect.github.com/halms))
- vfox plugins now report an error, instead of crashing mise, when the HTTP client can't be built (for example, when no CA certificates are installed). [#​14576](https://redirect.github.com/jdx/mise/pull/14576) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- MCP resource read errors now include the underlying cause, such as the untrusted-config message and its `mise trust` hint. [#​14566](https://redirect.github.com/jdx/mise/pull/14566) ([@​diogochaves](https://redirect.github.com/diogochaves))
#### Registry
- `xcsift` 1.7.0 and later installs from signed Packslip releases and now supports Linux x64 as well as macOS ARM64. [#​14540](https://redirect.github.com/jdx/mise/pull/14540) ([@​jdx](https://redirect.github.com/jdx))
- `protoc-gen-connect-go` 2.x now installs from the `/v2` Go module path, and 1.x versions keep working. [#​14545](https://redirect.github.com/jdx/mise/pull/14545) ([@​jdx](https://redirect.github.com/jdx))
- Added `rea` (`npm:rea-agents`). [#​14421](https://redirect.github.com/jdx/mise/pull/14421) ([@​phucisstupid](https://redirect.github.com/phucisstupid))
#### Documentation
- The docs now state that OpenTelemetry export and spinel installs require `experimental = true`. [#​14552](https://redirect.github.com/jdx/mise/pull/14552) ([@​ZainnQureshii](https://redirect.github.com/ZainnQureshii))
#### New Contributors
- [@​phucisstupid](https://redirect.github.com/phucisstupid) made their first contribution in [#​14421](https://redirect.github.com/jdx/mise/pull/14421)
- [@​diogochaves](https://redirect.github.com/diogochaves) made their first contribution in [#​14566](https://redirect.github.com/jdx/mise/pull/14566)
- [@​ZainnQureshii](https://redirect.github.com/ZainnQureshii) made their first contribution in [#​14552](https://redirect.github.com/jdx/mise/pull/14552)
- [@​fang2hou](https://redirect.github.com/fang2hou) made their first contribution in [#​14551](https://redirect.github.com/jdx/mise/pull/14551)
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.10.12...v2026.10.13>
#### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.10.12`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.12): : Per-tool Python runtimes for PyPI tools, Gradle workspace discovery, and env file find_up
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.11...vfox-v2026.10.12)
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://redirect.github.com/jdx/mise/pull/14479) ([@​jdx](https://redirect.github.com/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://redirect.github.com/jdx/mise/pull/14504) ([@​jdx](https://redirect.github.com/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](https://redirect.github.com/Jarvvski). [#​14512](https://redirect.github.com/jdx/mise/pull/14512) ([@​jdx](https://redirect.github.com/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://redirect.github.com/jdx/mise/pull/14497) ([@​jdx](https://redirect.github.com/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://redirect.github.com/jdx/mise/pull/14511) ([@​jdx](https://redirect.github.com/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://redirect.github.com/jdx/mise/pull/14502) ([@​jdx](https://redirect.github.com/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 `[email protected].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://redirect.github.com/jdx/mise/pull/14500) ([@​jdx](https://redirect.github.com/jdx))
- Registry: added `martin` (`github:maplibre/martin`). [#​14488](https://redirect.github.com/jdx/mise/pull/14488) ([@​ivan-ivkovic](https://redirect.github.com/ivan-ivkovic), [@​jdx](https://redirect.github.com/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://redirect.github.com/jdx/mise/pull/14501) ([@​jdx](https://redirect.github.com/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://redirect.github.com/jdx/mise/pull/14487) ([@​pikeas](https://redirect.github.com/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://redirect.github.com/jdx/mise/pull/14476) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562), [@​risu729](https://redirect.github.com/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://redirect.github.com/jdx/mise/pull/14508) ([@​jdx](https://redirect.github.com/jdx))
#### Documentation
- Explained why `mise activate` keeps shims on `PATH` [#​14493](https://redirect.github.com/jdx/mise/pull/14493) ([@​jdx](https://redirect.github.com/jdx)), and clarified the platform-specific mise cache paths for CI [#​14506](https://redirect.github.com/jdx/mise/pull/14506) ([@​zeitlinger](https://redirect.github.com/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://redirect.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.
### [`v2026.10.11`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.11): : Much faster installs and far fewer GitHub API calls
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.10...vfox-v2026.10.11)
mise is much faster in this release and calls the GitHub API far less. Version lists, release tags, attestations and other public GitHub metadata now come from mise-versions, so everyday commands like `mise install`, `exec`, shims, `outdated`, `lock` and `self-update` are quicker and users without a GitHub token no longer run into the 60-requests-an-hour limit. Cached version lists are reused for longer, so repeat installs skip most lookups. It also adds `mise bootstrap --upgrade` and `mise env --paths`, and closes a trust gap in remote task files.
#### Speed and GitHub API usage
Cold-cache timings for v2026.10.10 versus v2026.10.11, measured with hyperfine on one Linux x64 machine with no GitHub token set:
| Command | v2026.10.10 | v2026.10.11 |
| ----------------------------------------------------- | ----------- | ----------- |
| `mise ls-remote python` | 961 ms | 93 ms |
| `mise install` (jq, ripgrep, fd, bat, gh, shellcheck) | 1.49 s | 1.08 s |
| `mise outdated` (same six tools installed) | 433 ms | 272 ms |
The install and `outdated` runs are noisy (±0.1–0.4s over 4 runs) and the install time includes downloads, so treat them as rough. Requests to `api.github.com` in a cold `mise install` of `github:` tools dropped from 2 to 0. Cold `mise outdated` made 8 network requests before and none now.
- **Public GitHub metadata comes from mise-versions.** With `use_versions_host` on (the default), release lists, `latest`, git tags (aqua `github_tag` packages, ubi and go), artifact attestations (including aqua's `predicate_type` filters) and the digest in the checksum-mismatch hint are read from mise-versions instead of `api.github.com`. GitHub is still asked directly for repositories mise-versions doesn't list when you have a token (the private-repository case), and in paranoid mode for attestations. The direct API is also used with `use_versions_host = false`, GitHub `url_replacements` and custom `api_url`s. [#​14460](https://redirect.github.com/jdx/mise/pull/14460), [#​14461](https://redirect.github.com/jdx/mise/pull/14461), [#​14469](https://redirect.github.com/jdx/mise/pull/14469), [#​14481](https://redirect.github.com/jdx/mise/pull/14481), [#​14477](https://redirect.github.com/jdx/mise/pull/14477), [#​14443](https://redirect.github.com/jdx/mise/pull/14443)
- Other requests also moved off the GitHub API:
- `mise x`, `mise exec`, shims and `hook-env` use mise-versions when they auto-install a tool. [#​14458](https://redirect.github.com/jdx/mise/pull/14458)
- `mise self-update` reads mise's releases from mise-versions and downloads the archive from github.com release downloads. Packslip and zipsign verification are unchanged. [#​14464](https://redirect.github.com/jdx/mise/pull/14464)
- `mise lock` downloads artifacts for provenance checks from github.com instead of the API asset endpoint. [#​14465](https://redirect.github.com/jdx/mise/pull/14465)
- Aqua registries hosted on GitHub are fetched from raw\.githubusercontent.com. [#​14470](https://redirect.github.com/jdx/mise/pull/14470)
- Ruby looks up the latest ruby-build release through mise-versions. [#​14471](https://redirect.github.com/jdx/mise/pull/14471)
- **Fewer version-list fetches.** `mise install`, `use` and `run` now reuse a cached version list for the tool's `minimum_release_age` window minus one hour, clamped to 1–24h. With the default 24h cutoff, that is 23h. `outdated`, `upgrade`, `ls-remote`, `lock` and `latest` still refresh after 1h. If you set `fetch_remote_versions_cache` yourself, your value applies to every command. [#​14484](https://redirect.github.com/jdx/mise/pull/14484), [#​14485](https://redirect.github.com/jdx/mise/pull/14485), [#​14457](https://redirect.github.com/jdx/mise/pull/14457)
- **Faster version resolution:**
- Multi-tool commands such as `mise outdated` can resolve many registry tools with one request to the mise-versions index. [#​14473](https://redirect.github.com/jdx/mise/pull/14473)
- `latest` is resolved without refetching the list. [#​14456](https://redirect.github.com/jdx/mise/pull/14456)
- Explicit backend args such as `aqua:jqlang/jq` reuse the registry tool's version list. [#​14459](https://redirect.github.com/jdx/mise/pull/14459)
- Release tags come from the versions host instead of being listed or guessed. [#​14442](https://redirect.github.com/jdx/mise/pull/14442)
- Packslip installs no longer re-download what resolution already verified. [#​14466](https://redirect.github.com/jdx/mise/pull/14466)
- Install tracking and the Python version list are served from static assets. [#​14441](https://redirect.github.com/jdx/mise/pull/14441)
- **Python version listing no longer clones pyenv.** `mise ls-remote python`, `outdated`, `upgrade` and fuzzy `mise use [email protected]` read the python-build definitions from mise-versions. A cold listing took about 960ms before and about 90ms now. pyenv is still cloned when mise compiles Python, when `python.pyenv_repo` points at a fork, when you're offline, or when `use_versions_host = false`. Some definitions that had no date before now have one, so they are held back by `minimum_release_age` until they are old enough. [#​14455](https://redirect.github.com/jdx/mise/pull/14455)
- `mise oci build` now requires root for `apt:` packages, as it already did for apk, and fails up front with a clear message. If apt-get still fails, the error now includes the last lines of dpkg's output. [#​14447](https://redirect.github.com/jdx/mise/pull/14447)
- Registry: `native-sdk` now installs from npm (`@native-sdk/cli`), so the `native` command works. It requires Node 24+. [#​14431](https://redirect.github.com/jdx/mise/pull/14431)
#### Security
- **Remote task files now need trust before their headers render.** A `mise.toml` with only `[tasks]` loads without trust. Before this fix, if one of those tasks set `file` to a remote URL, `mise tasks ls`, `mise tasks info` and `mise tasks validate` rendered the file's `#MISE` headers, so a template like `{{ exec(...) }}` ran without a trust prompt. Remote files now follow the same rule as local task includes: if the headers contain template syntax, the config that references them must be trusted first. Remote files with plain headers still list without trust, and braces in the script body need no trust. [#​14416](https://redirect.github.com/jdx/mise/pull/14416) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562), [@​risu729](https://redirect.github.com/risu729))
- Updated rustls to 0.23.46 to address a RustSec advisory. [#​14434](https://redirect.github.com/jdx/mise/pull/14434)
#### Added
- **`mise bootstrap --upgrade`** installs what is missing and then upgrades what is already installed, in a single run. In the packages phase it runs the same upgrade as `mise bootstrap packages upgrade`, and pins are respected. In the tools phase it runs `mise upgrade` without `--bump`, so configured version ranges hold. Both run before the matching post hooks and dependent services. `--dry-run` previews both steps and `--skip` works as before. It does not update mise itself, repositories or images, and it does not restart services. [#​14433](https://redirect.github.com/jdx/mise/pull/14433)
```sh
mise self-update --yes && mise bootstrap --upgrade
```
- **`mise env --paths`** prints the PATH entries mise manages, one per line and in PATH order: tool bin directories, `_.path` entries, and inherited directories that mise moves forward, such as `~/.cargo/bin`. This lets CI integrations export only mise's additions without diffing `PATH`. [#​14429](https://redirect.github.com/jdx/mise/pull/14429)
```console
$ mise env --paths
/home/me/.local/share/mise/installs/node/24.11.0/bin
/home/me/.cargo/bin
```
- **The install script downloads pinned versions from mise.jdx.dev.** `curl https://mise.run | MISE_VERSION=<version> sh` now tries mise.jdx.dev first and falls back to GitHub Releases if that download fails. Checksums for pinned versions still come only from GitHub's `SHASUMS256.txt`. If no checksum is found, the script refuses to install. `MISE_INSTALL_FROM_GITHUB=1` still uses GitHub only. [#​14446](https://redirect.github.com/jdx/mise/pull/14446)
- Registry: `gdal` installs the GDAL/OGR command-line tools from conda-forge (`conda:libgdal-core`). [#​14440](https://redirect.github.com/jdx/mise/pull/14440) ([@​ivan-ivkovic](https://redirect.github.com/ivan-ivkovic))
#### Fixed
- **A bare `mise upgrade` no longer installs lazy tools that have never been installed.** Naming the tool still installs it. A lazy tool that already has a version installed upgrades as before. A missing lazy tool is still installed if an upgraded tool depends on it. `mise outdated` now marks these tools as `[MISSING] (lazy)`, and the bare upgrade no longer looks up their versions. [#​14422](https://redirect.github.com/jdx/mise/pull/14422) ([@​ryanrhughes](https://redirect.github.com/ryanrhughes)), [#​14444](https://redirect.github.com/jdx/mise/pull/14444)
- Fixed false `stack limit reached` errors on the static musl builds, for example on Ubuntu 26.04. These errors broke aqua `version_filter` parsing and made shims such as kubectl's report "not a valid shim". [#​14450](https://redirect.github.com/jdx/mise/pull/14450)
- `mise lock --platform ...` run on Alpine or NixOS no longer records Node source builds for other platforms. Only an explicit `node.compile` or `all_compile = true` forces source builds for those targets. [#​14432](https://redirect.github.com/jdx/mise/pull/14432)
- `mise upgrade --bump` and hand-edited version pins no longer drop a pipx tool's locked uv dependency graph. Before, `mise install --locked` then failed on a fresh checkout. [#​14426](https://redirect.github.com/jdx/mise/pull/14426) ([@​wislertt](https://redirect.github.com/wislertt))
- Packslip prefixes such as `fnox@1` now skip releases this host can't install, the same way `latest` does. Each skipped release gets a warning, and if no match can
> [!IMPORTANT]
> ✂ PR body was truncated to here.
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNjQuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjE2NC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
> [!NOTE]
> This PR body was truncated due to platform limits.
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [jdx/mise](https://redirect.github.com/jdx/mise) | minor | `v2026.9.7` → `v2026.10.8` |
---
### Release Notes
<details>
<summary>jdx/mise</summary>
### [`v2026.10.8`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.8): : Stable `global` install link for IDEs
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.7...vfox-v2026.10.8)
Each tool's install directory now has a `global` link that follows your global config, which gives IDEs a path that doesn't change when you switch versions. This release also retries downloads whose response body drops partway through, fixes lockfile checks for release tags that contain `@`, and stops dotfiles history from rewriting files that haven't changed.
##### Added
- **`global` runtime symlink.** Each tool's install directory now has a `global` link to the version your global and system config select. Programs that can't run mise, such as IDEs, can point at this path and follow `mise use -g` changes. [#​14271](https://redirect.github.com/jdx/mise/pull/14271)
```text
~/.local/share/mise/installs/maven/
├── 3.9.13/
├── 3.9.16/
└── global -> ./3.9.16
```
The link is updated along with the other runtime symlinks (`latest`, `3`, ...), for example after `mise use -g`, `mise install` and `mise upgrade`. Project config and `MISE_*_VERSION` don't change it. If no global config selects the tool, mise removes the link. A real directory named `global` is left alone. The link is always on, and no setting turns it off.
##### Fixed
- HTTP requests now retry, up to `http_retries`, when the response body drops partway through. Before, only the request and headers were retried, so a version list or release page cut off mid-transfer failed with `error decoding response body`. This applies to text, JSON and byte requests, and to version lists read with `version_regex`. [#​14253](https://redirect.github.com/jdx/mise/pull/14253) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- `mise install` no longer rejects lockfile entries whose release tag contains `@`, such as `[email protected].0`. `mise lock` writes these tags percent-encoded (`cli%400.46.0`), and the locked-URL check read that as version `400.46.0`. Re-running `mise lock` couldn't fix it. [#​14252](https://redirect.github.com/jdx/mise/pull/14252)
- Dotfiles history index rebuilds now skip checkpoint metadata files whose contents haven't changed. On large histories, rebuilds used to rewrite every file, which caused minutes of disk writes and made `mise dot save` fail with `another history operation is running`. [#​14249](https://redirect.github.com/jdx/mise/pull/14249)
- The JSON schema now accepts `outputs = { auto = false }` on tasks, so editors and linters such as tombi and Taplo no longer flag it. mise's behavior is unchanged: `auto = false` means the same as leaving `outputs` unset. [#​14265](https://redirect.github.com/jdx/mise/pull/14265) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
##### Documentation
- The dotfiles docs now open with a recommended setup, and the modes-and-keys reference table has been reorganized into three readable columns. [#​14267](https://redirect.github.com/jdx/mise/pull/14267)
##### Registry
- New aqua packages: [`runxhq/runx`](https://redirect.github.com/runxhq/runx) and [`takumin/passt-bin`](https://redirect.github.com/takumin/passt-bin).
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.10.7...v2026.10.8>
##### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.10.7`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.7): : Background tool updates at the shell prompt, a verified download cache, and `mise upgrade --global`
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.6...vfox-v2026.10.7)
Tools with `auto_update` now update in the background from an activated shell, and a new `tool_update.global_auto` setting turns this on for every global tool. mise also keeps finished downloads in a content-addressed cache and checks them again before reusing them. This release also fixes `.env` parsing regressions from 2026.10.3 and a crash in `mise run`.
##### Added
- **Automatic updates at the shell prompt.** Before, `auto_update` only ran when a shim or `mise exec` launched a tool. With `mise activate`, tools run straight from `PATH`, so they were never updated. Now, when a check is due, `mise hook-env` starts the update in a detached background process. The prompt doesn't wait and nothing is printed. The next command after the update finishes uses the new version. The existing rules still apply: only global config counts, exact versions don't move, nothing updates offline, in CI or with `locked`, and `minimum_release_age` is honored. While the `tool-update` service is running, prompts leave updates to it. Failed background updates show up in `mise doctor`. [#​14239](https://redirect.github.com/jdx/mise/pull/14239)
- **`tool_update.global_auto`** turns on automatic updates for every tool in global config at once. It takes the same values as `auto_update`: `true` checks every `tool_update.check_duration` (24h by default), and a duration sets the interval. A tool's own `auto_update` takes precedence, so `auto_update = false` opts a tool out. Projects can't enable this setting. You can also set it with `MISE_TOOL_UPDATE_GLOBAL_AUTO`. `self_update.auto` now accepts an interval too, for example `self_update.auto = "1d"`. [#​14237](https://redirect.github.com/jdx/mise/pull/14237)
```toml
# ~/.config/mise/config.toml
[settings]
tool_update.global_auto = "12h"
[tools]
claude = "latest" # checked every 12h
node = { version = "24", auto_update = "6h" } # its own interval wins
python = { version = "3.13", auto_update = false } # opted out
```
- **`mise upgrade --global` and `mise outdated --global`** act only on the tool requests in global and system config, even inside a project that pins its own version or when `MISE_<TOOL>_VERSION` is set. The project's `mise.toml`, lockfile and `[env]` are not read or changed. `--bump` writes to the global config. `--global` can't be combined with `--local` or `--inactive`. A new "Self-updating tools" docs page explains how tools that update themselves, such as coding agents, can detect a mise install and update through mise instead of overwriting their own install. [#​14243](https://redirect.github.com/jdx/mise/pull/14243)
```sh
mise outdated --global claude --json
mise upgrade --global claude
```
- **Verified download cache.** Finished downloads are stored once in `$MISE_CACHE_DIR/downloads-cas` and hashed again before every reuse. A cached file that no longer matches is dropped and downloaded again. [#​14222](https://redirect.github.com/jdx/mise/pull/14222), [#​14242](https://redirect.github.com/jdx/mise/pull/14242)
- When the server sent an `ETag` or `Last-Modified` header, the next request for the same URL is conditional. On `304 Not Modified`, mise reuses the cached file without downloading it again. This applies to every download through mise's HTTP client.
- For tools with a pinned checksum (from tool options, `mise.lock` or a packslip digest), `http`, `github`, `aqua`, `packslip` and the precompiled core tools (Node, Go, Bun, Deno, Zig, Java, Python, Ruby, Erlang, Elixir, Swift) reuse the cached file without any network request. The file is hard-linked into place, so it doesn't use extra disk space.
- With `--locked` or `paranoid`, mise only uses the cache for downloads with a pinned checksum. This means a CI cache you restore can save downloads but can't change what gets installed. The CI guide now shows how to cache `~/.cache/mise/downloads-cas` instead of installed tools.
- `download_cache_max_size` sets the size limit (default `2GiB`, `0` for no limit). When the cache is full, the least recently used files are removed. `download_cache = false` (`MISE_DOWNLOAD_CACHE=0`) turns the cache off.
- **`npm:` packages that install no executables now trigger a warning.** For example, `mise use npm:lodash` used to succeed silently even though it created no shims. The install still succeeds. [#​14246](https://redirect.github.com/jdx/mise/pull/14246)
##### Fixed
- **`.env` parsing regressions from 2026.10.3**, affecting `[env] _.file` and the `env_file` setting:
- Backslashes in single-quoted values are literal again, so Windows paths like `'\\fileserver\share'` and `'C:\temp\'` load correctly. To embed a single quote, use double quotes. [#​14228](https://redirect.github.com/jdx/mise/pull/14228)
- Quoted and unquoted parts placed next to each other are joined again, as in shell. For example, `A='it'\''s'` gives `it's` and `B=a'b c'd` gives `ab cd`. These lines used to cause syntax errors that dropped the rest of the file. Quotes inside an unquoted value are now removed, so JSON that needs to keep its quotes must be single-quoted (`CONFIG='{"debug": true}'`). A quote with no matching closing quote on the same line stays literal, so `NAME=O'Brien` reads as written. [#​14231](https://redirect.github.com/jdx/mise/pull/14231)
- `mise run` no longer crashes now and then with `called Option::unwrap() on a None value` when it reads the tool list while it's being reloaded after an install. [#​14240](https://redirect.github.com/jdx/mise/pull/14240)
- On Windows with `core.autocrlf=true`, `mise bootstrap repos status` no longer reports freshly cloned repos as dirty. [#​14225](https://redirect.github.com/jdx/mise/pull/14225)
- On Windows, `mise dot apply` can now repoint a `mode = "symlink"` dotfile whose target is a directory junction after its `source` changes. It used to fail with `os error 5`. [#​14226](https://redirect.github.com/jdx/mise/pull/14226)
- `history.describe_command` now works for files tracked through a variant (such as `home@work/...`), including files added or removed inside variant directories. Encrypted files are still left out of the diff. [#​14194](https://redirect.github.com/jdx/mise/pull/14194) ([@​oppegard](https://redirect.github.com/oppegard))
- `mise doctor` now shows the `dotfiles:` section, including the history `repo:` and `origin:`, when `history.enabled = false`. `mise doctor --json` adds `dotfiles.history_enabled` and `dotfiles.tracking_error`. [#​14244](https://redirect.github.com/jdx/mise/pull/14244)
- `mise lock` now applies aqua registry version prefixes (such as Codex's `rust-` prefix) before it chooses version overrides. Before, platform entries like `windows-x64` were skipped. When several prefix families match, mise now warns and skips the entry instead of picking one arbitrarily. [#​14218](https://redirect.github.com/jdx/mise/pull/14218) ([@​nettlesh](https://redirect.github.com/nettlesh))
- The rustup profile aliases `m`, `d`, `c` and the empty value are now treated like `minimal`, `default` and `complete`. With `profile = "d"`, `mise install` now restores missing components like clippy and rustfmt. Unknown profile names now fail with rustup's list of valid names. [#​14220](https://redirect.github.com/jdx/mise/pull/14220) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- The cargo backend now takes the same rust-state lock as the rust plugin when `CARGO_HOME`/`RUSTUP_HOME` are set through the `rust.cargo_home`/`rust.rustup_home` settings or `MISE_CARGO_HOME`/`MISE_RUSTUP_HOME` in `[env]`. Before, parallel source-build installs could race and fail. [#​14219](https://redirect.github.com/jdx/mise/pull/14219) ([@​wislertt](https://redirect.github.com/wislertt))
- The hint to enable `self_update.auto` now appears on every `mise version` and `mise self-update` run, not just the first time. It stops once you enable auto-update or run `mise settings add disable_hints auto_update`. [#​14233](https://redirect.github.com/jdx/mise/pull/14233)
- The JSON schema now matches what mise accepts, so editors and linters like tombi and Taplo report the right errors ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562)):
- Task arrays can contain `{ task = ... }` and `{ tasks = [...] }` entries. [#​14229](https://redirect.github.com/jdx/mise/pull/14229)
- `depends`, `depends_post` and `wait_for` accept a single table, and empty nested lists like `depends = [[]]` are rejected. [#​14236](https://redirect.github.com/jdx/mise/pull/14236)
- `[env]` entries that combine `value` with `required = true` or a help string, and `{ required = false }` with no value, are rejected. [#​14247](https://redirect.github.com/jdx/mise/pull/14247)
##### Deprecated
- `always_keep_download` is deprecated because downloads are now kept in the download cache. It will warn starting in 2026.11.0 and will be removed in 2027.11.0. [#​14222](https://redirect.github.com/jdx/mise/pull/14222)
##### Documentation
- The automatic tool updates docs now explain that `minimum_release_age` (24h by default) plus the check interval can delay an update by 24 to 48 hours after a release. You can set `minimum_release_age` per tool. Docs and hints now use the shorter `mise settings KEY=VALUE` form. [#​14235](https://redirect.github.com/jdx/mise/pull/14235)
##### New Contributors
- [@​wislertt](https://redirect.github.com/wislertt) made their first contribution in [#​14219](https://redirect.github.com/jdx/mise/pull/14219)
- [@​oppegard](https://redirect.github.com/oppegard) made their first contribution in [#​14194](https://redirect.github.com/jdx/mise/pull/14194)
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.10.6...v2026.10.7>
##### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.10.6`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.6): : Per-machine [vars] prompts, local config includes, and working-tree changes in --affected
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.5...vfox-v2026.10.6)
`[vars]` entries can now ask once per machine and remember the answer, `include` accepts local files, and `mise run --affected` now counts uncommitted work and no longer needs `experimental = true`. On a fresh machine, `mise bootstrap` can install git and ssh before it clones. The release also fixes several dotfiles history issues and stops lazy tools from triggering remote version lookups when something else launches.
##### Added
- **Per-machine `[vars]` prompts.** Give a var a `prompt`, plus either a `default` or `required`. mise asks for it once and saves the answer in `$MISE_STATE_DIR/vars.toml`, outside your config and dotfiles history. Templates, tasks and tools then read it as usual. One shared dotfiles setup can use this to set a different Git identity on each machine. [#​14190](https://redirect.github.com/jdx/mise/pull/14190)
```toml
[vars.git_name]
default = "Ada Lovelace"
prompt = "Git author name"
[vars.git_email]
required = "Run mise vars prompt to set git_email"
prompt = "Git email"
```
```sh
mise vars # list every var and where its value comes from
mise vars prompt # ask for every unanswered prompt var (or name some)
mise vars git_name=Ada # save a value without a prompt
mise vars unset git_name # forget a saved value
mise bootstrap --prompt-vars # prompt during a bootstrap run, e.g. with --adopt
```
Only `mise vars prompt` and `mise bootstrap --prompt-vars` ever ask. Everything else uses the saved answer, then the `default`. Precedence, highest first: the process environment, a value from a higher-precedence config file, the saved answer, the `default`. Answers are keyed by var name, so projects that use the same name share one answer on a machine. `prompt` is not allowed in `[env]`.
- **Local paths in `include`.** `include` in `mise.toml` now accepts local TOML files, not just `git::` and `oci::` references. A path can be relative to the including file or absolute. Local files merge the same way as remote ones, ranking just below the including file. They are read on every load, so edits apply immediately and invalidate the cached env. Paranoid mode rejects local includes, and safe mode still skips all includes in project config. [#​14178](https://redirect.github.com/jdx/mise/pull/14178)
```toml
include = ["./config/tools.toml", "/etc/mise/team.toml"]
```
- **`mise bootstrap` installs git and ssh before cloning.** `mise bootstrap --from` and `--adopt` used to fail with a spawn error when git was missing. Now mise checks for git, and for ssh when the URL is `ssh://` or `user@host:path`, and offers to install whatever is missing with the host package manager. Supported managers are apt, dnf, pacman, apk, zypper, Homebrew, scoop and winget. `--yes` accepts the offer without asking, and `--dry-run` only reports what is missing. [#​14188](https://redirect.github.com/jdx/mise/pull/14188)
- **`mise dot save --re-encrypt`.** After you change `[history.encryption] recipients`, a normal save leaves some encrypted files under their old keys: manual-save entries the save doesn't name, and other-platform variants. Add `--re-encrypt` to re-encrypt every saved file in the new checkpoint to the current recipients. It never captures unsaved edits. If this machine can't unlock some of the files, nothing is saved and the error lists all of them. [#​14210](https://redirect.github.com/jdx/mise/pull/14210)
- **`mise dot status` shows unsaved changes.** It now lists tracked paths that changed since the latest checkpoint. Unsaved edits were previously invisible there when the watcher was stopped or an entry used `--no-autosave`. `--json` reports these paths as `history.unsaved`. The value is `null` when they can't be determined, for example with no checkpoint yet or with encrypted files this machine can't compare without prompting. [#​14209](https://redirect.github.com/jdx/mise/pull/14209)
##### Changed
- **`mise run --affected` now counts working-tree changes, and the workspace graph is no longer experimental.** Besides the committed `base...head` range, `--affected` now also counts staged and unstaged edits and untracked files that aren't ignored. You can narrow it with `--affected-committed`, `--affected-uncommitted` and `--affected-untracked`, which can be combined (environment variables: `MISE_AFFECTED_*`). Working-tree changes only count when the head is your current checkout. To get the old committed-only selection, for example in a CI job that writes untracked files before it runs, use `--affected-committed`. `--affected`, `mise tasks graph`, `[monorepo.task_defaults]`, `[monorepo.projects]` and `task.auto_infer` no longer require `experimental = true`. [#​14214](https://redirect.github.com/jdx/mise/pull/14214)
```sh
mise run --affected build # committed + uncommitted + untracked
mise run --affected --affected-uncommitted --affected-untracked build # only what you haven't committed yet
mise run --affected --affected-committed build # committed range only, as before
```
- **Credential checks for dotfiles.** Files with names ending in `.example`, `.sample` or `.template` no longer match the credential name rules. The content scan before publishing still checks them. Once you approve a file for plaintext tracking, mise no longer warns about it on every save. [#​14204](https://redirect.github.com/jdx/mise/pull/14204)
- **`mise dot track` only asks about plaintext at a terminal.** Before saving a credential-named file in plaintext, it now asks only when both stdin and stderr are terminals. Previously, a piped line, such as the next entry in a `while read` loop, could be taken as the answer. Scripts need `--allow-plaintext` or `--encrypt`. [#​14205](https://redirect.github.com/jdx/mise/pull/14205)
##### Fixed
- **Lazy tools no longer trigger remote lookups for other lazy tools.** Previously, mise looked up versions for configured lazy tools that weren't installed, even though they weren't being launched. With a cold cache and no network, launching one tool waited on each lookup and could print "Failed to resolve tool version list" warnings. In one offline test a launch took 41 seconds. This no longer happens in these cases:
- the update that runs before an `auto_update` tool launches ([#​14195](https://redirect.github.com/jdx/mise/pull/14195))
- after `mise x` or a shim installs a new version ([#​14197](https://redirect.github.com/jdx/mise/pull/14197))
- the first launch of a lazy tool through its shim ([#​14201](https://redirect.github.com/jdx/mise/pull/14201))
`mise install`, `mise upgrade` and `mise use` still resolve everything.
- **`Too many open files` with parallel `npm:` installs.** Parallel installs could fail under macOS's default launchd soft limit of 256, for example when mise was started from a LaunchAgent. On Unix, mise now raises its soft open-file limit at startup toward the hard limit, up to 10240, and never lowers it. [#​14174](https://redirect.github.com/jdx/mise/pull/14174), [#​14216](https://redirect.github.com/jdx/mise/pull/14216)
- **`go:` tools with an untidy `go.mod`.** Tools whose published `go.mod` is missing a requirement now install, for example `go:tailscale.com/cmd/tailscale`. mise now passes `-mod=mod` to `go install` instead of `-mod=readonly`. A project's `GOFLAGS=-mod=vendor` still doesn't affect these installs. [#​14180](https://redirect.github.com/jdx/mise/pull/14180) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- **Config at the filesystem root.** A config file at `/`, such as `/mise.toml` in a Docker image, made `mise install` and `mise exec` panic. It now works. [#​14182](https://redirect.github.com/jdx/mise/pull/14182)
- **.NET installs.** Installing a .NET SDK no longer fails with "was not found in `dotnet --list-sdks` output" when another mise-managed SDK comes before the shims on `PATH`. The post-install check now runs the new SDK's `dotnet` directly. [#​14189](https://redirect.github.com/jdx/mise/pull/14189)
- **Shims and directories.** Shims and `mise which` no longer resolve a bin name to a directory in another tool's bin path. Previously, `hunk`'s `skills/` directory blocked `npm:skills` with "Permission denied". [#​14193](https://redirect.github.com/jdx/mise/pull/14193)
- **`mise oci build` and multiple versions.** A tool pinned to several versions is now written to the embedded `/etc/mise/config.toml` as a single array, in resolution order. Previously each version got its own duplicate key, which made the config unreadable inside the container. [#​14200](https://redirect.github.com/jdx/mise/pull/14200) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- **Encrypted files a sync can't unlock.** `mise bootstrap --adopt`, `mise dot pull` and `mise dot sync` now list every encrypted file they can't unlock in one error, instead of stopping at the first one. Damaged files still stop the sync immediately. [#​14208](https://redirect.github.com/jdx/mise/pull/14208)
- **Rollback and undo messages.** `mise dot rollback <path>` now names the checkpoint that saved the restored version, which matches `mise dot history --path`. Rollback and undo also name both checkpoints they record: the result, and the one holding the state before the operation. Previously, rollback could name a checkpoint that `history --path` didn't list. What gets restored is unchanged. [#​14207](https://redirect.github.com/jdx/mise/pull/14207), [#​14211](https://redirect.github.com/jdx/mise/pull/14211)
- **`mise dot status` on adopted machines.** On a machine that adopted a shared setup, it no longer prints "nothing configured in \[dotfiles]" while history tracks entries. [#​14206](https://redirect.github.com/jdx/mise/pull/14206)
##### New Contributors
- [@​jovial-liu](https://redirect.github.com/jovial-liu) made their first contribution in [#​14184](https://redirect.github.com/jdx/mise/pull/14184)
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.10.5...v2026.10.6>
##### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.10.5`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.5): : Java defaults to Temurin, per-machine and local-only dotfile history, packslip workflow pinning
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.4...vfox-v2026.10.5)
Java versions without a vendor prefix now install Eclipse Temurin builds. Dotfiles gain per-machine and local-only history, a `merge = "missing"` mode, and a secret check before `mise dot sync` publishes anything. Packslip tools can be pinned to the workflow that signs their releases. Several features documented as experimental now actually require `experimental = true`. The rest of the release is fixes across tasks, shims, config loading, bootstrap and backends.
##### Breaking Changes
- **`java@21`, `java@lts` and `java@latest` now install Temurin.** The default of `java.shorthand_vendor` changes from `openjdk` to `temurin`. The jdk.java.net OpenJDK builds stop at the next feature release, so `java@21` was stuck on 21.0.2 from January 2024. Vendor-prefixed requests (`openjdk-21`, `corretto-21`, ...) are not affected. Installed OpenJDK versions keep working, and `mise upgrade` offers the Temurin build. Shorthand versions now include Temurin's build suffix (for example `21.0.12+101.0.LTS`). Temurin has no builds of Java 9, 10 or 12–15, so use `openjdk-12` and similar for those. [#​14146](https://redirect.github.com/jdx/mise/pull/14146)
- **Lockfiles:** existing shorthand lock entries record `shorthand_vendor = "openjdk"`. Without that setting, `mise install --locked` fails with `java@21 is not in the lockfile`. Either keep OpenJDK:
```toml
[settings]
java.shorthand_vendor = "openjdk"
# or per project: java = "openjdk-21"
```
or switch to Temurin with `mise lock --bump java` and commit the result.
- **Some experimental features now require `experimental = true`** (or `MISE_EXPERIMENTAL=1`) when you use them. Config that only mentions them still loads. [#​14114](https://redirect.github.com/jdx/mise/pull/14114)
- Running a task with a `git::` remote `file`, including through `mise run --dry-run`, `mise watch`, or as a dependency. Commands that only inspect tasks (`tasks ls`, `tasks info`, `tasks deps`, `generate task-docs`) show the task from its TOML and warn once that the file wasn't fetched. These were documented as experimental but were missing the check in the codebase.
- `git::` and `oci::` entries in `task_config.includes`. These are skipped with a warning.
- OpenTelemetry export of `mise run` when an OTLP endpoint is set.
- Installing `spinel:` tools.
- **`mise.local.toml` now overrides `mise.<env>.toml` in the same directory**, as the docs already said. Before, the committed environment file won in project directories, and also in `~/.config/mise` when the walk up from the cwd reached it. Within each directory the order is now, highest first: `mise.<env>.local.toml`, `mise.local.toml`, `mise.<env>.toml`, `mise.toml`. If you relied on the environment file winning, move those keys into `mise.<env>.local.toml`. [#​14148](https://redirect.github.com/jdx/mise/pull/14148)
- **MCP:** in the `mise://tasks` resource, `env` is now an array of env directive strings, the same format as `mise tasks ls --json`. It was always an empty object before. [#​14111](https://redirect.github.com/jdx/mise/pull/14111)
- **`mise settings set` and `add` refuse writes that would have no effect.** This covers early-init settings (`env`, `ceiling_paths`, `env_conf_d`, ...) written to a config file, and global-only settings (`yes`, `paranoid`, `trusted_config_paths`, ...) written with `--local`. The error says where the setting has to go: `miserc.toml`, the global config, or the `MISE_*` variable. [#​14126](https://redirect.github.com/jdx/mise/pull/14126)
##### Added
##### Dotfiles
- **Per-machine tracked files.** Some files describe the machine, such as a monitor layout. Use `variants = [{ machine = true }]` or `mise dot track --machine` to keep a separate history for each machine. Sync pushes every machine's version to the origin but never applies one machine's version on another. Each machine gets a generated name, which you can set with `[history] machine = "desk"`. A machine variant must be the entry's only variant and can't be combined with `encrypt`. Upgrade every machine that shares a setup before using it. [#​14062](https://redirect.github.com/jdx/mise/pull/14062)
```toml
[dotfiles]
"~/.config/hypr/monitors.lua" = { mode = "track", variants = [{ machine = true }] }
```
- **`mode = "track-local"`** (or `mise dot track --local`) keeps a file's history in a separate store on this machine, with no origin. The file never reaches the shared manifest, a commit or a push. Commands that name a path use the history that holds it. Use `mise dot --local history` or `mise dot --local undo` to work with the local history directly. `save`, `capture` and `watch` cover both histories. [#​14082](https://redirect.github.com/jdx/mise/pull/14082)
- **`merge = "missing"`** sets only the keys the target file doesn't have yet. Values an app writes itself, such as the model picked with `/model` in Codex or Claude Code, are left alone. Works with TOML, YAML and JSON. [#​14081](https://redirect.github.com/jdx/mise/pull/14081)
```toml
[dotfiles]
"~/.codex/config.toml/shared" = { merge = true }
"~/.codex/config.toml/defaults" = { source = "codex/defaults.toml", merge = "missing" }
```
- Merge entries can leave out `source`. mise then reads the target's path under `dotfiles.root`. Switching an entry from `symlink` to `merge` now replaces a link that points at the merge source with a writable copy, so the app's own keys survive. [#​14076](https://redirect.github.com/jdx/mise/pull/14076)
- **`mise dot sync` refuses to publish saved versions that look like secrets.** It checks for provider tokens, private key blocks, and `*_KEY`/`*_TOKEN`/`*_SECRET`/`*_PASSWORD` assignments. Only versions the origin doesn't have yet are checked. The error names the file, line and version, never the value. `--allow-plaintext-history` skips the check. [#​14171](https://redirect.github.com/jdx/mise/pull/14171)
- `mise bootstrap --adopt <url> --take-remote-all` takes the repository's version of every file that differs, in one step. Combined with `--replace-history`, it also adopts the repository on a machine that already has history of its own. [#​14065](https://redirect.github.com/jdx/mise/pull/14065)
- `mise doctor` shows the dotfiles history repo path and the connected origin (URL, branch, sync mode), in both text and `--json` output. [#​14173](https://redirect.github.com/jdx/mise/pull/14173)
##### Bootstrap
- `[bootstrap.files]` and `[bootstrap.directories]` accept the same `os` selector as packages. Entries that don't match the host are skipped completely. [#​14058](https://redirect.github.com/jdx/mise/pull/14058)
```toml
[bootstrap.files."/etc/docker/daemon.json"]
os = "linux"
source = "./files/docker-daemon.json"
```
- `fish = "auto"` in `[bootstrap.mise_shell_activate]` writes a block that runs `mise activate fish` in interactive shells and `--shims` everywhere else. [#​14172](https://redirect.github.com/jdx/mise/pull/14172)
- `[bootstrap]` is now allowed in config includes. It merges below the including file, so a shared baseline can declare packages, hooks and services, and the project still wins on any key it sets itself. [#​14176](https://redirect.github.com/jdx/mise/pull/14176)
- Systemd units accept `state = "absent"`, which stops, disables and deletes the matching mise-managed service and timer. `mise bootstrap unapply` now also removes the units an environment added. [#​14139](https://redirect.github.com/jdx/mise/pull/14139)
##### Tools and backends
- **Packslip `workflow` option.** It accepts only releases signed by the named GitHub Actions workflow on tags. It takes one workflow or a list, and an entry can name a ref (`release.yml@refs/heads/main`). It can't be combined with `pubkey`, `identity`, `identity_prefix` or `issuer`. [#​14075](https://redirect.github.com/jdx/mise/pull/14075), [#​14093](https://redirect.github.com/jdx/mise/pull/14093)
```toml
[tools]
"packslip:github.com/aubepkg/aube" = { version = "latest", workflow = ["release-plz.yml", "release.yml"] }
```
- Registry entries for dagu, timoni, helmfile, fnox, hk, usage, communique, mr-boxington, pitchfork, aube and worktrunk are now pinned to the workflow that signs their releases. A `workflow` or `pubkey` you set yourself replaces the registry pin. [#​14092](https://redirect.github.com/jdx/mise/pull/14092), [#​14091](https://redirect.github.com/jdx/mise/pull/14091), [#​14073](https://redirect.github.com/jdx/mise/pull/14073) ([@​max-sixty](https://redirect.github.com/max-sixty))
- **MCP `install_tool` is implemented.** It installs the requested version, or the configured version, or latest, and returns the resolved version and install path. `install_tool` and `run_task` now refuse to act on untrusted config instead of trusting it on the client's behalf. [#​14111](https://redirect.github.com/jdx/mise/pull/14111)
- `mise installs migrate` no longer fails on installs it can't reinstall, such as withdrawn releases, signer changes or no network. It moves them into the identity layout as they are and leaves a link at the old path. It also handles lockfile-suffixed `~aube~`/`~uv~` directories correctly. [#​14079](https://redirect.github.com/jdx/mise/pull/14079)
- Registry: `mprocs` is renamed to `dekit` to match upstream, and `mprocs` stays as an alias. From v0.10.0 the binary is `dekit`. [#​14169](https://redirect.github.com/jdx/mise/pull/14169)
##### Changed
- Dotfile operations you can undo no longer ask for confirmation after showing their plan. This covers `dot pull`, `dot track`, `undo`, `rollback`, `connect` and `bootstrap --adopt`. Destructive ones still ask, such as `--replace-history`, `dot recover --keep-current` and `implode`. `--yes` and `MISE_YES` are still accepted. [#​14077](https://redirect.github.com/jdx/mise/pull/14077), [#​14071](https://redirect.github.com/jdx/mise/pull/14071), [#​14067](https://redirect.github.com/jdx/mise/pull/14067)
- Safe mode (`MISE_SAFE=1`) now ignores a project's `[bootstrap]`, `[dotfiles]` and `[dotfile_groups]`. Before, an untrusted repo could link files into `$HOME` or clone repositories. Global and system config still apply. [#​14110](https://redirect.github.com/jdx/mise/pull/14110)
- Node downloads are checked against the GPG signature for every version that publishes one. Before, only versions starting with `2` were checked. Set `node.gpg_verify = false` for mirrors without signatures. [#​14132](https://redirect.github.com/jdx/mise/pull/14132)
- `mise generate github-action` now uses `actions/checkout@v7` and `jdx/mise-action@v5` and no longer sets `MISE_EXPERIMENTAL`. `mise generate devcontainer` now adds `"postCreateCommand": "mise install"`. [#​14145](https://redirect.github.com/jdx/mise/pull/14145)
##### Deprecated
- `task.cache.stats_report`, `sops.age_recipients` and `plugin_autoupdate_last_check_duration` never had any effect. Setting one now prints a warning, and they will be removed in 2027.10.5. [#​14112](https://redirect.github.com/jdx/mise/pull/14112)
- `mise bootstrap launchd|systemd|macos-defaults`, the old `--only`/`--skip` part names (`launchd`, `systemd`, `defaults`, `shell`) and `mise direnv` now print a warning that names the replacement. They will be removed in 2027.10.4. [#​14113](https://redirect.github.com/jdx/mise/pull/14113)
##### Fixed
##### Tasks
- A raw or interactive task with `cache` enabled is now skipped when its sources are fresh and its cache key hasn't changed. Before, it ran every time. [#​14121](https://redirect.github.com/jdx/mise/pull/14121)
- A typo in `sources` that matches no files now prints a warning. `mise tasks deps <task>` now shows `depends_post` tasks. Scripts in `$MISE_CONFIG_DIR/tasks` load even without a global config file. [#​14122](https://redirect.github.com/jdx/mise/pull/14122)
- `mise run ./script` resolves relative to the current directory. [#​14120](https://redirect.github.com/jdx/mise/pull/14120)
- Script extensions are stripped only from file task names. [#​14159](https://redirect.github.com/jdx/mise/pull/14159)
- Requests to the remote task cache include the mbx-cache headers. [#​14147](https://redirect.github.com/jdx/mise/pull/14147)
- `mise generate task-stubs` skips hidden and global tasks. [#​14127](https://redirect.github.com/jdx/mise/pull/14127)
##### Shims and exec
- Shims, `mise x` and `mise env` no longer look up remote versions for lazy tools that aren't installed. With 20 lazy tools and no network, running an installed tool went from about 42s to 0.09s. [#​14063](https://redirect.github.com/jdx/mise/pull/14063)
- On Unix, a system wrapper that execs the same command name can no longer send an unconfigured shim into an endless loop. [#​14088](https://redirect.github.com/jdx/mise/pull/14088)
- Windows lazy shim names now match regardless of letter case. [#​14090](https://redirect.github.com/jdx/mise/pull/14090)
- `mise x [email protected]` installs the exact version when the version list times out, instead of failing with "couldn't exec process". [#​14164](https://redirect.github.com/jdx/mise/pull/14164)
- `mise doctor` recognizes a `mise` entry in the dedicated shims dir. [#​14069](https://redirect.github.com/jdx/mise/pull/14069)
##### Config, settings and CLI
- With an environment active and no `config.toml` yet, `mise use -g` creates `config.toml` instead of writing into `config.<env>.toml`. [#​14179](https://redirect.github.com/jdx/mise/pull/14179)
- Booleans set through `mise config set --type bool` and boolean settings accept `yes`/`no`/`1`/`0`. For `env.*` and other keys that aren't settings, only `true` and `false` become booleans, and anything else is stored as written. `mise latest tool@prefix:X` works, and `--log-level warn` is accepted. `mise doctor` prints the full chain when config fails to load. [#​14125](https://redirect.github.com/jdx/mise/pull/14125)
- Help output uses the command name you typed. [#​14123](https://redirect.github.com/jdx/mise/pull/14123)
- `mise edit` no longer overwrites an existing config when there is no terminal. [#​14124](https://redirect.github.com/jdx/mise/pull/14124)
- `.monorepo` markers are verified in paranoid mode. [#​14105](https://redirect.github.com/jdx/mise/pull/14105)
- Bad input now gives an error instead of a panic, in places including `mise config ls` and `mise prune` with an invalid tool version, the `--monorepo` flags, and `mise plugins uninstall --purge`. [#​14118](https://redirect.github.com/jdx/mise/pull/14118), [#​14094](https://redirect.github.com/jdx/mise/pull/14094) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562)), [#​14103](https://redirect.github.com/jdx/mise/pull/14103) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562)), [#​14116](https://redirect.github.com/jdx/mise/pull/14116), [#​14117](https://redirect.github.com/jdx/mise/pull/14117)
- `mise env --redacted` honors `redact = false` exclusions. `watch_files` hooks don't run in safe mode or with `--no-hooks`. [#​14109](https://redirect.github.com/jdx/mise/pull/14109), [#​14108](https://redirect.github.com/jdx/mise/pull/14108)
- `mise watch` passes watchexec flags through to watchexec. [#​14115](https://redirect.github.com/jdx/mise/pull/14115)
- Error and warning hints point at current commands, for example the PATH advice from `bootstrap remote` and the watchexec install hint. [#​14142](https://redirect.github.com/jdx/mise/pull/14142)
- If stderr can't be written to during a migration, mise no longer aborts. [#​14158](https://redirect.github.com/jdx/mise/pull/14158) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- When the default cache and temp directories overlap (the Windows default), temp files now go to `<temp>/mise-tmp`, so `mise cache clear` no longer deletes files that are still in use. [#​14134](https://redirect.github.com/jdx/mise/pull/14134)
##### Bootstrap and dotfiles
- `mise bootstrap` keeps writing the shell activation block into a startup file that is only tracked. [#​14135](https://redirect.github.com/jdx/mise/pull/14135)
- If one package manager fails, the others still run. [#​14138](https://redirect.github.com/jdx/mise/pull/14138)
- The firewall section is skipped on systems that don't support it. [#​14137](https://redirect.github.com/jdx/mise/pull/14137)
- Dry runs show hooks that use `exec()`. [#​14136](https://redirect.github.com/jdx/mise/pull/14136)
- Pulling onto a machine with no history now saves the files it replaces first, so `mise dot undo` restores them. `--replace-history` no longer fails on its first attempt. [#​14065](https://redirect.github.com/jdx/mise/pull/14065)
- `mise dot pull` says so when incoming history changes no files on this machine. [#​14066](https://redirect.github.com/jdx/mise/pull/14066)
##### Backends and plugins
- `mise install cargo:...` no longer uses an inactive `cargo-binstall` shim. It falls back to native binstall or `cargo install`. [#​14070](https://redirect.github.com/jdx/mise/pull/14070)
- With `npm.shell_out`, a mise shim from another data dir can no longer be run as `npm` and fork until the machine runs out of memory. [#​14084](https://redirect.github.com/jdx/mise/pull/14084) (originally found and fixed by [@​tfournet](https://redirect.github.com/tfournet))
- Java: changing `java.shorthand_vendor` takes effect without waiting for the cache to expire. Inline `java[release_type=ea]` is respected when listing and resolving versions. [#​14131](https://redirect.github.com/jdx/mise/pull/14131)
- Ruby precompiled URLs expand `{os}` and `{arch}` correctly. [#​14133](https://redirect.github.com/jdx/mise/pull/14133)
- `ls-remote` respects `disable_backends`. [#​14130](https://redirect.github.com/jdx/mise/pull/14130)
- SPM uses a custom `api_url` for cloning and skips lockfile URLs. [#​14129](https://redirect.github.com/jdx/mise/pull/14129)
- GitHub assets are size-checked even when there is no checksum. GitLab release lookups percent-encode the tag. [#​14128](https://redirect.github.com/jdx/mise/pull/14128), [#​14102](https://redirect.github.com/jdx/mise/pull/14102) ([@​thespags](https://redirect.github.com/thespags))
- Brew infers the formula version from the GitHub release tag path, and detaches a DMG left attached by an interrupted install. [#​14165](https://redirect.github.com/jdx/mise/pull/14165) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562)), [#​14177](https://redirect.github.com/jdx/mise/pull/14177)
- `git::` plugins install from a subdirectory, and `[plugins]` entries compare those sources correctly. Packslip entries in `[plugins]` install as vfox plugins. [#​14140](https://redirect.github.com/jdx/mise/pull/14140), [#​14150](https://redirect.github.com/jdx/mise/pull/14150) ([@​onokonem](https://redirect.github.com/onokonem)), [#​14141](https://redirect.github.com/jdx/mise/pull/14141)
- vfox: an env plugin with no source no longer makes every command fail. Embedded plugin files are found relative to the manifest directory. [#​14119](https://redirect.github.com/jdx/mise/pull/14119), [#​14167](https://redirect.github.com/jdx/mise/pull/14167)
##### Daemons and sandbox
- On Windows, deferred daemon commands are quoted for cmd.exe. Argv and Windows readiness probes run in the tool environment. [#​14055](https://redirect.github.com/jdx/mise/pull/14055), [#​14080](https://redirect.github.com/jdx/mise/pull/14080) ([@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- `--deny-env` clears inherited variables on Windows. On macOS, `allow_net` is rejected instead of writing invalid sandbox rules. [#​14107](https://redirect.github.com/jdx/mise/pull/14107), [#​14106](https://redirect.github.com/jdx/mise/pull/14106)
##### Security
- Remote task cache keys store env, `[vars]` and task arg values as `blake3:` digests instead of plaintext, so secret values are no longer uploaded. Existing cache entries miss once after upgrading. [#​14104](https://redirect.github.com/jdx/mise/pull/14104)
- URL credentials are redacted from HTTP debug logs and from npm Git-source and SSH diagnostics. [#​14155](https://redirect.github.com/jdx/mise/pull/14155), [#​14057](https://redirect.github.com/jdx/mise/pull/14057), [#​14064](https://redirect.github.com/jdx/mise/pull/14064)
##### Documentation
- The documentation site, CLI help and settings descriptions have been restructured and rewritten, and moved pages still resolve. [#​14097](https://redirect.github.com/jdx/mise/pull/14097), [#​14098](https://redirect.github.com/jdx/mise/pull/14098), [#​14096](https://redirect.github.com/jdx/mise/pull/14096), [#​14163](https://redirect.github.com/jdx/mise/pull/14163)
##### New Contributors
- [@​onokonem](https://redirect.github.com/onokonem) made their first contribution in [#​14150](https://redirect.github.com/jdx/mise/pull/14150)
- [@​max-sixty](https://redirect.github.com/max-sixty) made their first contribution in [#​14073](https://redirect.github.com/jdx/mise/pull/14073)
**Full Changelog**: <https://github.com/jdx/mise/compare/vfox-v2026.10.4...v2026.10.5>
##### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.10.4`](https://redirect.github.com/jdx/mise/releases/tag/v2026.10.4): : Task-scoped fnox secrets, automatic global tool updates, and an opt-in identity install layout
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.10.3...vfox-v2026.10.4)
This release adds experimental task-scoped secrets backed by fnox, automatic updates for global tools, and an experimental opt-in install layout that names installations by what they contain. It also adds dotfile `merge` entries, `headers` auth for the `http:` backend, npm installs from git, and a set of prune, install and lockfile fixes.
##### Added
##### Secrets (experimental)
These need `mise settings experimental=true` and fnox 1.39.0 or newer. They are refused in safe mode.
- **`[secrets.fnox]` and `mise secrets ls`.** A project can name fnox as its secrets source in its own `mise.toml`. `mise secrets ls` lists key names and metadata but never values. `-J` prints JSON. Global, system and home-level `[secrets]` config is ignored, and `mise doctor` reports it. [#​13967](https://redirect.github.com/jdx/mise/pull/13967)
- **Tasks get only the secrets they list.** Add `secrets = [...]` to a task, or `#MISE secrets=[...]` in a file task header. Only that task gets the values, only while it runs, and they are redacted from its output. Dependencies, hooks, `mise env`, hook-env and shims get nothing. A task without grants never calls fnox. Tasks that list secrets need a trusted config, aren't artifact-cached, and ignore `--raw` unless the task sets `raw` or `interactive`. Hooks, `watch_files`, daemons and `mise bootstrap` can't run them, and remote or global-config tasks can't list secrets. [#​13974](https://redirect.github.com/jdx/mise/pull/13974)
```toml
min_version = "2026.10.4" # older mise rejects `secrets` on a task
[secrets.fnox]
profile = "prod"
[tasks.deploy]
depends = ["build"] # build receives nothing
secrets = ["DEPLOY_KEY", "DATABASE_URL"]
run = "./deploy.sh"
```
- **One-off grants from the command line.** `--secrets KEY[,KEY]` and `--secrets-all` work on `mise run`, `mise tasks run` and `mise x`. For `mise run`, only the tasks named on the command line get them, not their dependencies. `mise x` gets nothing unless you pass a flag, and it can't receive file secrets. Flags placed after the task name go to the task, and mise warns when that happens. [#​13975](https://redirect.github.com/jdx/mise/pull/13975)
```sh
mise run --secrets STRIPE_KEY deploy
mise x --secrets GH_TOKEN -- gh release list
```
- **`{{ secrets.X }}` in task env values.** A task can build an env var from a secret, for example `env.PGURL = "postgres://app:{{ secrets.DB_PASSWORD }}@db/app"`. The reference counts as the grant. References are rejected in `run`, `[env]`, `[vars]` and other fields. [#​13978](https://redirect.github.com/jdx/mise/pull/13978)
- **fnox daemon cache.** If the project's fnox config enables the daemon and it's running, an interactive run reads cached values over its socket without starting an fnox process. mise never starts the daemon itself. CI, non-TTY runs and Windows always use the fnox CLI. [#​13979](https://redirect.github.com/jdx/mise/pull/13979)
##### Automatic global tool updates
- **`auto_update` for global tools.** Set `auto_update` on a tool in your global config. When a shim or `mise x` is about to run that tool and its check interval is due, mise upgrades it within the configured range and then runs the new version. `true` uses the new `tool_update.check_duration` setting (default 24h), and a duration string sets that tool's own interval (minimum 1h). [#​14026](https://redirect.github.com/jdx/mise/pull/14026)
- Exact pins never update.
- It never runs offline, in CI, with `locked = true`, from tasks or hook-env, or from project configs.
- If an update fails, mise warns and runs the installed version. The failure shows in `mise doctor`.
```toml
# ~/.config/mise/config.toml
[tools]
claude = { version = "latest", auto_update = true }
node = { version = "22", auto_update = "6h" } # newest 22.x, never 23
```
- **Background `tool-update` service.** A built-in bootstrap service checks `auto_update` tools hourly, so launches don't wait for downloads and tools run directly from PATH under activation also stay current. It installs a systemd user unit, LaunchAgent or scheduled task. [#​14040](https://redirect.github.com/jdx/mise/pull/14040)
```toml
[bootstrap.services.mise-tool-update]
builtin = "tool-update"
```
##### Identity install layout (experimental, opt-in)
- **`install_layout = "identity"`.** With `experimental = true`, each installation lives in `installs/<label>-<hash>/`. The hash covers the canonical backend, version, platform and install-affecting options. `installs/<tool>/<version>` becomes a link to that directory, a real junction on Windows. As a result: [#​13951](https://redirect.github.com/jdx/mise/pull/13951)
- `age` and `aqua:FiloSottile/age` share one installation.
- Variants of one version with different options can exist side by side.
- Windows IDEs can follow the version links.
Existing installs keep working and aren't moved. Nothing changes unless you set this. `MISE_INSTALL_LAYOUT=identity` also turns it on. See the new install layout docs.
- On Windows, identity-layout installations go into the shorter `%LOCALAPPDATA%\mise\i\`, while version links stay in `installs\`. `MISE_INSTALL_STORE_DIR` sets the location on any platform. [#​13952](https://redirect.github.com/jdx/mise/pull/13952)
- `mise installs ls` lists installations as `selected`, `pinned` or `shared`. `mise installs select <dir>` chooses which installation requests without a lockfile use. When several installations match and none is selected, mise lists them instead of guessing. [#​13953](https://redirect.github.com/jdx/mise/pull/13953)
- `mise installs migrate [--dry-run] [TOOL[@VERSION]]` reinstalls legacy installations into the new layout and leaves a link at the old path. If a run is interrupted, the next run recovers it. [#​13955](https://redirect.github.com/jdx/mise/pull/13955)
- In the layout, `mise backends switch` installs the new backend's version and points the link at it. `mise where` and the other commands now resolve versions named on the command line the same way, and `mise where` lists variants instead of picking one. [#​13957](https://redirect.github.com/jdx/mise/pull/13957)
- `mise prune` handles templated tool versions such as `node = "{{ vars.node }}"`. It uses snapshots of what each project last rendered and keeps installs when it isn't sure they are unused. [#​14025](https://redirect.github.com/jdx/mise/pull/14025)
##### Other additions
- **Dotfile `merge` entries.** A `merge = true` entry sets only the keys from its source in a JSON, TOML or YAML file, and leaves keys added by the application (Codex, Claude Code, etc.) alone. TOML and YAML keep comments and formatting. `mise dot status` and `mise dot diff` only report drift in those keys. A target that doesn't parse is never overwritten. [#​14012](https://redirect.github.com/jdx/mise/pull/14012)
```toml
[dotfiles]
"~/.codex/config.toml/shared" = { source = "codex/shared.toml", merge = true }
```
- **`headers` for the `http:` backend.** You can now authenticate with bearer tokens or API keys, for example to download OCI blobs from `ghcr.io`. Values are templates. Headers are sent with downloads, `version_list_url` and `checksum_url` requests, and dropped on cross-host redirects unless the host is listed in `headers_forward`. Changing a token doesn't trigger a reinstall. [#​14022](https://redirect.github.com/jdx/mise/pull/14022)
```toml
[tools."http:polaris"]
version = "0.9.2"
headers = { Authorization = "Bearer {{ env.GITHUB_TOKEN | b64_encode }}" }
```
- **npm packages from git.** `git+` URLs and `github:`, `gitlab:` and `bitbucket:` specs now install. The version is a git ref, and `latest` is the default branch. [#​14044](https://redirect.github.com/jdx/mise/pull/14044)
```sh
mise use 'npm:github:owner/[email protected]'
```
- **`settings.write_targets`.** Sends new global `[tools]`, `[bootstrap.packages]` and `[dotfiles]` entries to separate `conf.d` files. Existing entries are updated where they're already declared. [#​14018](https://redirect.github.com/jdx/mise/pull/14018)
```toml
[settings.write_targets]
tools = "~/.config/mise/conf.d/10-tools.toml"
dotfiles = "~/.config/mise/conf.d/30-dotfiles.toml"
```
- **`prune.exclude`** (or `MISE_PRUNE_EXCLUDE`) lists tools that `mise prune`, `mise ls --prunable` and upgrade pruning never remove. Short and full names both work, e.g. `node` or `aqua:BurntSushi/ripgrep`. [#​14030](https://redirect.github.com/jdx/mise/pull/14030)
- **`lockfile_auto_prune = false`** keeps lockfile entries for tools missing from the active config. This is useful when profiles share one lockfile. The default (`tr
> [!IMPORTANT]
> ✂ PR body was truncated to here.
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMzQuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjE1NS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| redis | digest | `6f81e89` → `2c2dff7` |
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMzQuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjEzNC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [postgres](https://hub.docker.com/_/postgres) ([source](https://redirect.github.com/docker-library/postgres)) | digest | `5a5a84b` → `74935e7` |
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMzQuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjEzNC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
# Why
Re-implementation of #714 on top of #715.
# How
Prompt:
> add new error for pg code 55P03, use PR 714 as reference but a new error class
# Test Plan
CI
# Why
While reviewing #714, noticed that it was probably better if these knex/postgres-specific errors live in their package rather than the root package.
This is a breaking change but one that is detectable via tsc so within the scope of what's allowed via minor version bump.
# How
Have claude move them. Prompt:
> move knex-specific entity errors into the entity-database-adapter-knex package. no need for backwards
compatibility
# Test Plan
CI
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| redis | digest | `718f745` → `6f81e89` |
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMjUuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjEyNS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [ip-address](https://redirect.github.com/beaugunderson/ip-address) | [`10.4.0` → `10.5.1`](https://renovatebot.com/diffs/npm/ip-address/10.4.0/10.5.1) |  |  |
---
### ip-address: no classifier recognizes the NAT64 local-use range 64:ff9b:1::/48, allowing SSRF and trust-boundary bypass
[CVE-2026-101910](https://nvd.nist.gov/vuln/detail/CVE-2026-101910) / [GHSA-2vr4-cq9g-pvrc](https://redirect.github.com/advisories/GHSA-2vr4-cq9g-pvrc)
<details>
<summary>More information</summary>
#### Details
##### Summary
No classifier on `Address6` recognizes the NAT64 local-use range `64:ff9b:1::/48` (RFC 8215). `isPrivate()`, `isLoopback()`, `isLinkLocal()` and their siblings all return `false` for every address in it, so an internal IPv4 destination written through a local-use NAT64 prefix (`64:ff9b:1:7f00:0:100::` for `127.0.0.1`, `64:ff9b:1:a9fe:a9:fe00::` for `169.254.169.254`) reads as an ordinary global address. `getType()` names the range `'NAT64 (local-use)'`, so the library knows what the address is and classifies it as nothing.
An application that builds a network trust-boundary decision on these checks (for example a filter intended to block Server-Side Request Forgery, or SSRF) will classify an internal target as external and allow the request. SSRF is an attack in which a user-supplied address coaxes the server into making a request to an internal destination the user could not otherwise reach, such as a loopback service or a cloud metadata endpoint.
##### Details
The fix for GHSA-22jq-vg5j-6vgg (10.2.1) classifies IPv4-mapped (`::ffff:0:0/96`) and NAT64 well-known (`64:ff9b::/96`) addresses by their embedded IPv4 address: `embeddedIPv4()` in `src/ipv6.ts` decodes the trailing 32 bits and every special-use classifier delegates to the resulting `Address4`. Those are the only two ranges `embeddedIPv4()` handles.
The local-use range differs in kind from the well-known prefix, which is why extending the decoder does not fix it. RFC 8215 reserves `64:ff9b:1::/48` so an operator can carve their own NAT64 prefix out of it, of any length RFC 6052 allows (`/48`, `/56`, `/64`, or `/96`). Where the IPv4 address sits depends on that choice: `127.0.0.1` is `64:ff9b:1:7f00:0:100::` under a `/48` prefix and `64:ff9b:1::7f00:1` under a `/96` prefix, and each of those decodes to a different address under the other prefix length. There is no single embedded IPv4 address for the library to classify by.
What is well-defined is the range as a whole. The IANA IPv6 Special-Purpose Address Registry lists `64:ff9b:1::/48` as not globally reachable, and Python's `ipaddress` module reports `is_private` as `True` and `is_global` as `False` for every address in it. `isPrivate()` covered ULA (`fc00::/7`) plus the decoded mapped and well-known cases, and nothing in the local-use range.
##### Affected versions
`>= 10.2.0, <= 10.5.0`. The `is*` classification API was extended to `Address6` in 10.2.0; releases before it do not expose the method and are not affected through this vector.
##### Impact
Every address in `64:ff9b:1::/48` parses successfully, `isValid()` is `true`, and no classifier catches it. Which internal target is reached depends on the NAT64 prefix deployed on the server's network; the well-known prefix column is the patched control from GHSA-22jq-vg5j-6vgg.
| Internal target | Well-known form | Classified | Local-use form (`/48` prefix) | Classified |
|---|---|---|---|---|
| `127.0.0.1` | `64:ff9b::7f00:1` | loopback | `64:ff9b:1:7f00:0:100::` | nothing |
| `10.0.0.1` | `64:ff9b::a00:1` | private | `64:ff9b:1:a00:0:100::` | nothing |
| `169.254.169.254` | `64:ff9b::a9fe:a9fe` | link-local | `64:ff9b:1:a9fe:a9:fe00::` | nothing |
| `192.168.1.1` | `64:ff9b::c0a8:101` | private | `64:ff9b:1:c0a8:1:100::` | nothing |
##### Reachability
Reaching an internal host through one of these addresses requires that the server's network run a NAT64 translator on a prefix inside `64:ff9b:1::/48` and that the attacker guess or know the prefix length. That is the same precondition the well-known prefix carries (a translator on `64:ff9b::/96`), with the additional constraint that the prefix is operator-chosen rather than fixed. The severity reflects that precondition.
##### Proof of concept
`npm i [email protected]`, then:
```js
const { Address6 } = require('ip-address');
// A guard of the shape the library documents.
function isBlocked(host) {
const a = new Address6(host);
return a.isLoopback() || a.isLinkLocal() || a.isPrivate() || a.isMulticast() || a.isUnspecified();
}
for (const h of ['64:ff9b::7f00:1', '64:ff9b:1:7f00:0:100::', '64:ff9b:1::7f00:1']) {
console.log(isBlocked(h) ? 'BLOCK' : 'ALLOW', h, '-> getType()', new Address6(h).getType());
}
```
On affected versions:
```
BLOCK 64:ff9b::7f00:1 -> getType() NAT64 (well-known)
ALLOW 64:ff9b:1:7f00:0:100:: -> getType() NAT64 (local-use)
ALLOW 64:ff9b:1::7f00:1 -> getType() NAT64 (local-use)
```
##### Remediation
Upgrade to the patched release. In the fix, `isPrivate()` returns `true` for every address in `64:ff9b:1::/48`, alongside ULA and the decoded mapped and well-known cases. The range is reported private as a whole rather than by a decoded IPv4 address, for the reason given above; `toAddress4Nat64(prefix)` remains the way to decode an address under a known deployment prefix. `isLoopback()` and `isLinkLocal()` are unchanged for this range, since without the prefix length the library cannot know which IPv4 address is embedded.
If you cannot upgrade immediately, test the range directly:
```js
const NAT64_LOCAL_USE = new Address6('64:ff9b:1::/48');
const localUse = new Address6(host).isHostInSubnet(NAT64_LOCAL_USE);
```
##### A note on SSRF defense
These methods are address classifiers, not a complete SSRF defense. Regardless of this fix, a robust SSRF guard must resolve the hostname and validate the *resolved* IP against the socket it connects to, and account for DNS rebinding and redirects. Treat these checks as one layer, not the only one.
#### Severity
- CVSS Score: 6.9 / 10 (Medium)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N`
#### References
- [https://github.com/beaugunderson/ip-address/security/advisories/GHSA-2vr4-cq9g-pvrc](https://redirect.github.com/beaugunderson/ip-address/security/advisories/GHSA-2vr4-cq9g-pvrc)
- [https://nvd.nist.gov/vuln/detail/CVE-2026-101910](https://nvd.nist.gov/vuln/detail/CVE-2026-101910)
- [https://github.com/beaugunderson/ip-address/commit/ab3dc88bcf5374344168a2ba075ca7ac4ff257f8](https://redirect.github.com/beaugunderson/ip-address/commit/ab3dc88bcf5374344168a2ba075ca7ac4ff257f8)
- [https://github.com/beaugunderson/ip-address/releases/tag/v10.5.1](https://redirect.github.com/beaugunderson/ip-address/releases/tag/v10.5.1)
- [https://github.com/advisories/GHSA-2vr4-cq9g-pvrc](https://redirect.github.com/advisories/GHSA-2vr4-cq9g-pvrc)
This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-2vr4-cq9g-pvrc) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>
---
### Release Notes
<details>
<summary>beaugunderson/ip-address (ip-address)</summary>
### [`v10.5.1`](https://redirect.github.com/beaugunderson/ip-address/compare/v10.5.0...38b02d73cfc0724f9ad61c65b6328e116eac03ec)
[Compare Source](https://redirect.github.com/beaugunderson/ip-address/compare/v10.5.0...v10.5.1)
### [`v10.5.0`](https://redirect.github.com/beaugunderson/ip-address/releases/tag/v10.5.0)
[Compare Source](https://redirect.github.com/beaugunderson/ip-address/compare/v10.4.0...v10.5.0)
##### What's Changed
- Honor the fromURL graceful-failure contract for non-IPv6 hosts by [@​beaugunderson](https://redirect.github.com/beaugunderson) in [#​218](https://redirect.github.com/beaugunderson/ip-address/pull/218)
- Correct the documentation where it disagreed with the library by [@​beaugunderson](https://redirect.github.com/beaugunderson) in [#​219](https://redirect.github.com/beaugunderson/ip-address/pull/219)
**Full Changelog**: <https://github.com/beaugunderson/ip-address/compare/v10.4.0...v10.5.0>
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMTIuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjExMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [postgres](https://hub.docker.com/_/postgres) ([source](https://redirect.github.com/docker-library/postgres)) | digest | `86c951e` → `5a5a84b` |
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMTIuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjExMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| redis | digest | `8a1efc5` → `718f745` |
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMTIuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjExMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| redis | digest | `298e5b3` → `8a1efc5` |
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDMuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjEwMy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [postgres](https://hub.docker.com/_/postgres) ([source](https://redirect.github.com/docker-library/postgres)) | digest | `4ef4dbc` → `86c951e` |
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDMuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjEwMy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [jdx/mise](https://redirect.github.com/jdx/mise) | patch | `v2026.9.2` → `v2026.9.7` |
---
### Release Notes
<details>
<summary>jdx/mise (jdx/mise)</summary>
### [`v2026.9.7`](https://redirect.github.com/jdx/mise/releases/tag/v2026.9.7): : Lockfile revision 2 with npm and Python dependency graphs, dotfile conflict inspection
[Compare Source](https://redirect.github.com/jdx/mise/compare/v2026.9.6...v2026.9.7)
This release introduces `mise.lock` revision 2, which records complete transitive dependency graphs for npm tools (via embedded aube) and Python tools (via uv) in native sidecar files, and adds `mise bootstrap dotfiles conflicts` for inspecting dotfile sync conflicts before resolving them. It also lets dotfile templates consume bootstrap secrets, stops `minimum_release_age` from rejecting versions already committed to a lockfile, and closes a security gap in `history.describe_command`.
##### Added
- **lock:** Lockfile revision 2 records the full dependency graph of npm tools installed by embedded aube and of `pypi:` tools installed by uv, then replays it with a strict frozen install so two projects on the same top-level version can still receive their own reviewed transitive graph. Graphs live in native sidecar files (`uv.lock` / `aube-lock.yaml` plus a manifest) under `.mise/locks/<backend-tool>/<version>/`, referenced from `mise.lock` by relative path and SHA-256 digest, so the lockfile itself stays small. Commit the sidecar directory with `mise.lock`. New lockfiles use revision 2; existing revision 0 and 1 files keep their format until you run `mise lock --upgrade`. `mise lock --bump <tool>` refreshes a tool's transitive graph even when its top-level version is unchanged, ordinary `mise install` validates and accepts hand-edited sidecars, and `mise install --locked` rejects digest mismatches until you run `mise lock`. Python graph locking requires uv 0.12.10 or newer and published wheels for the target platform; Git sources, standalone pipx installs, and free-form `uvx_args`/`pipx_args` stay version-only. ([#​13131](https://redirect.github.com/jdx/mise/pull/13131), [#​13146](https://redirect.github.com/jdx/mise/pull/13146) by [@​jdx](https://redirect.github.com/jdx))
```sh
mise lock --upgrade # move an existing lockfile to revision 2 and resolve graphs
mise install --locked # replay the recorded graphs
mise lock --bump pypi:black # refresh Black's dependencies without changing its version
```
- **pypi:** `pypi:` is now the preferred name for the Python CLI backend; `pipx:` remains fully supported as an alias with no warnings, and settings accept both `pypi.*` and `pipx.*` names. The two spellings are distinct tool identities (`pypi-black` vs `pipx-black` install directories and lock entries), so switching spelling creates a new installation. ([#​13146](https://redirect.github.com/jdx/mise/pull/13146) by [@​jdx](https://redirect.github.com/jdx))
- **bootstrap:** `mise bootstrap dotfiles conflicts [PATH...]` shows a read-only comparison of the saved local and fetched remote versions of a conflicted dotfile so you can decide between `--take-remote` and `--keep-local` with full context. The default output is a unified diff including file-mode changes; `--difftool` opens the configured Git `diff.tool` (falling back to `merge.tool`) and `--tool <name>` picks one explicitly. Encrypted contents are decrypted only into private temporary files, and inspection never modifies either side or marks the conflict resolved. Bootstrap secrets are also now resolved from the same composed config maps as dotfile discovery, so root-scoped dotfile templates can use secrets declared by their bootstrap root. ([#​13144](https://redirect.github.com/jdx/mise/pull/13144) by [@​jdx](https://redirect.github.com/jdx))
```sh
mise bootstrap dotfiles conflicts ~/.config/mise/config.toml
mise bootstrap dotfiles conflicts --difftool ~/.config/mise/config.toml
```
- **dotfiles:** Dotfile templates (`mode = "template"`) can reference `[bootstrap.secrets]` values with `{{ secret(name="...") }}`, matching managed bootstrap file templates. Dotfiles commands that render templates (`add`, `apply`, `diff`, `edit`, `status`, `unapply`) accept `--prompt-secrets`; without an available value, rendering fails closed. A full `mise bootstrap` run preflights dotfile templates before making changes, `mise bootstrap status` reports secrets used only by dotfiles, and textual diffs redact resolved secret values. ([#​13140](https://redirect.github.com/jdx/mise/pull/13140) by [@​jdx](https://redirect.github.com/jdx))
```toml
[bootstrap.secrets]
api_token = "EXAMPLE_API_TOKEN"
[dotfiles."~/.config/example/credentials"]
source = "dotfiles/credentials.tmpl"
mode = "template"
```
##### Fixed
- **lock:** Installing from a committed `mise.lock` no longer fails when the locked release is younger than `minimum_release_age`. The cutoff still applies when resolving unlocked fuzzy requests and when generating or bumping a lockfile, and `npm:`/`pypi:` still forward it to unpinned transitive dependencies, but a reviewed lock entry now reproduces immediately in CI instead of waiting for the release to cool. ([#​13128](https://redirect.github.com/jdx/mise/pull/13128) by [@​jdx](https://redirect.github.com/jdx))
- **config:** A `.python-version` (or other idiomatic version file) containing `system` selects the system interpreter without printing the mise-specific `@system` deprecation warning, matching the existing `.tool-versions` exception. Explicit `python@system` requests from mise configuration or command arguments still warn. ([#​13132](https://redirect.github.com/jdx/mise/pull/13132) by [@​jdx](https://redirect.github.com/jdx))
- **npm:** Embedded aube is updated to 2.2.16, fixing the Bun checksum install regression and ensuring local npm tarballs keep their manifest package name. ([#​13145](https://redirect.github.com/jdx/mise/pull/13145) by [@​jdx](https://redirect.github.com/jdx))
- **registry:** The `mc` shorthand uses `aqua:minio/mc` again now that the upstream Aqua registry entry is restored, with `asdf:mise-plugins/mise-mc` kept as the fallback. ([#​13124](https://redirect.github.com/jdx/mise/pull/13124) by [@​jdx](https://redirect.github.com/jdx))
##### Security
- **history:** `history.describe_command` is now global-only. Previously an implicitly trusted project could set it and have a later dotfiles history checkpoint execute the project-controlled command with unencrypted tracked-file diffs. The setting is honored only from system/global configuration or `MISE_HISTORY_DESCRIBE_COMMAND`; project values are ignored with a warning. ([#​13134](https://redirect.github.com/jdx/mise/pull/13134) by [@​jdx](https://redirect.github.com/jdx))
- **oci:** `mise oci build` now renders dotfile templates with a restricted engine: `secret()` is rejected and the `env` context, `get_env()`, `exec()`, and `read_file()` are unavailable, so ambient credentials cannot be baked into a publishable image layer. ([#​13140](https://redirect.github.com/jdx/mise/pull/13140) by [@​jdx](https://redirect.github.com/jdx))
##### Breaking Changes
- **Lockfile revision 2 is not readable by older mise versions.** Newly created lockfiles use revision 2, and existing files switch only when you run `mise lock --upgrade`. Upgrade collaborators and CI to this release before committing a revision 2 `mise.lock`, and commit the `.mise/locks/` (or `.config/mise/locks/`) sidecar directory alongside it. Revision 2 `--locked` installs fail if a recorded graph is missing or its digest does not match. If you gitignore `mise.local.lock`, also ignore its matching sidecar subdirectory (for example `.mise/locks/mise.local/`).
- **`history.describe_command` in project configuration is ignored.** Move it to `~/.config/mise/config.toml` or set `MISE_HISTORY_DESCRIBE_COMMAND`.
- **`mise oci build` dotfile templates** can no longer call `secret()`, `get_env()`, `exec()`, or `read_file()` or read the `env` context.
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.9.6...v2026.9.7>
##### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.9.6`](https://redirect.github.com/jdx/mise/releases/tag/v2026.9.6): : Project daemons, mise doctor project, and vfox backend tool discovery
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.9.5...v2026.9.6)
This release adds experimental project daemons backed by pitchfork, a `mise doctor project` command for project-declared diagnostic checks, and tool discovery from vfox backend plugins in `mise search`. It also changes the HTTP backend's default install layout so uninstall and prune reclaim disk space, speeds up warm `lockfile_mode = "generate"` installs and repeated OCI builds, and fixes a batch of nushell, monorepo, lockfile, brew, and Windows bootstrap issues.
#### Highlights
- **Services next to tools:** `[daemons]` declares background processes and PostgreSQL/Redis presets in `mise.toml`, managed through `mise daemons` and optionally started when you enter the project. `[doctor.checks.<name>]` lets projects declare their own environment probes for `mise doctor project`.
- **Discovery and output:** `mise search`, shell completion, and interactive `mise use` now include tools published by installed vfox backend plugins, and `settings.truncate` / `--no-truncate` disable terminal-width truncation (automatically when a coding agent is detected).
- **Storage and speed:** HTTP tools now extract into their own install directory by default (opt back into deduplication with `shared_extraction = true`), warm generate-mode installs skip needless lockfile rewrites, and OCI builds share a local tool-layer cache.
#### Added
- **daemons:** New experimental `[daemons]` section and `mise daemons` command family (`start`, `stop`, `restart`, `ls`, `status`, `logs`, `tui`) manage project background processes with pitchfork. PostgreSQL and Redis presets install the database as a tool (participating in lockfiles), supply connection environment variables and readiness checks, and keep project data across stop/start. Daemons with `auto = ["start", "stop"]` start when entering the project from an activated Bash, Zsh, or Fish shell and are released when the last shell session leaves. Requires `experimental = true` and pitchfork 2.25.0 or later; database presets are Unix-only and PostgreSQL uses loopback trust authentication intended for local development. ([#​13085](https://redirect.github.com/jdx/mise/pull/13085) by [@​jdx](https://redirect.github.com/jdx))
```toml
[settings]
experimental = true
[daemons]
postgres = "18"
redis = "8"
[daemons.web]
run = "npm run dev"
port = 3000
auto = ["start", "stop"]
```
- **doctor:** `mise doctor project` runs checks declared in `[doctor.checks.<name>]` with the project's environment and installed tools, reporting PASS/FAIL/error/skipped per check in text or `--json`. Checks support `description`, `hint`, `timeout` (default `10s`), `dir`, `shell`, and `os` selectors, run concurrently under the `jobs` limit, and exit nonzero when any check fails. Ordinary `mise doctor` does not run them, and hints are never executed. A follow-up aligned `dir` resolution with task conventions (config root for project configs including `~/mise.toml`, `~/` expansion), fixed head-of-line blocking when one probe hangs, and kept `nohup mise doctor project` alive on SIGHUP. ([#​13062](https://redirect.github.com/jdx/mise/pull/13062), [#​13089](https://redirect.github.com/jdx/mise/pull/13089) by [@​jdx](https://redirect.github.com/jdx))
```toml
[doctor.checks.openssl]
description = "OpenSSL development files are discoverable"
run = "pkg-config --exists openssl"
hint = "Run `mise bootstrap packages apply` to install the declared build dependencies."
timeout = "5s"
os = ["linux", "macos"]
```
- **vfox:** Tools provided by installed vfox backend plugins now appear in `mise search`, shell completion, and interactive `mise use`, namespaced as `<plugin>:<tool>`. Plugins can implement `BackendListTools` for a finite catalog and/or `BackendSearchTools` for query-driven discovery in large ecosystems; a prefixed query like `npm:eslint` is routed only to that plugin. Results are cached, slow plugins fall back to stale cache, and existing plugins need no changes. `mise registry` remains registry-only. ([#​13111](https://redirect.github.com/jdx/mise/pull/13111) by [@​jdx](https://redirect.github.com/jdx))
- **cli:** New `settings.truncate` (and `MISE_TRUNCATE`, default `true`) controls terminal-width shortening of table cells and task metadata. `mise ls`, `mise config ls`, and `mise bootstrap dotfiles status` gain `--truncate` / `--no-truncate`, and output is kept complete automatically when a known coding agent is detected. ([#​13112](https://redirect.github.com/jdx/mise/pull/13112) by [@​jdx](https://redirect.github.com/jdx))
```sh
mise bootstrap dotfiles status --no-truncate
```
- **bootstrap:** `[bootstrap.macos.dock]` gains `apps`, an ordered list of pinned application paths. Status compares identity and order (ignoring Dock-added metadata), apply adds, removes, and reorders application tiles while preserving other tiles and `persistent-others`, and an empty list removes all application tiles. Paths must be absolute or home-relative `.app` bundles. ([#​13075](https://redirect.github.com/jdx/mise/pull/13075) by [@​azohra](https://redirect.github.com/azohra))
```toml
[bootstrap.macos.dock]
apps = [
"/System/Applications/Utilities/Terminal.app",
"/Applications/Firefox.app",
]
```
- **bootstrap:** `mise bootstrap packages where brew:<formula>` prints an installed formula's stable `opt` root (for example `/opt/homebrew/opt/unzip`), so scripts can put keg-only executables on PATH without hardcoding the Homebrew prefix or Cellar version. Missing installs exit nonzero with empty stdout. ([#​13083](https://redirect.github.com/jdx/mise/pull/13083) by [@​himkt](https://redirect.github.com/himkt))
- **dotfiles:** Destination `variants` can omit `source` when every variant sets a `target`; the entry key is then resolved as a relative path under `settings.dotfiles.root` instead of next to `mise.toml`. Parent traversal is rejected. ([#​13087](https://redirect.github.com/jdx/mise/pull/13087) by [@​jdx](https://redirect.github.com/jdx))
```toml
[dotfiles."vscode/settings.json"]
mode = "copy"
variants = [
{ os = "macos", target = "~/Library/Application Support/Code/User/settings.json" },
{ os = "linux", target = "~/.config/Code/User/settings.json" },
]
```
- **fmt:** `mise fmt` now sorts lists whose order has no meaning: `redactions` lexically, and task `sources`/`outputs`, `task_templates` sources/outputs, `task_config.global_inputs`, and `input_groups` by reach (`@group:` references, then globs, then literal paths). Lists containing `!` exclusions, entries starting with template syntax, or comments are left untouched, and precedence-sensitive lists such as `env_file`, `tools.*`, `includes`, and `depends` are never sorted. ([#​13058](https://redirect.github.com/jdx/mise/pull/13058) by [@​jrandolf](https://redirect.github.com/jrandolf))
- **oci:** `mise oci build` gains `--no-cache` to bypass the new local tool-layer cache; entries live under each tool's cache directory and are removed by `mise cache clear TOOL`. ([#​13056](https://redirect.github.com/jdx/mise/pull/13056) by [@​jdx](https://redirect.github.com/jdx))
#### Changed
- **http:** New `http:` installations extract directly into their own install directory, so `mise uninstall` and `mise prune` now remove their files instead of leaving payloads in `$MISE_DATA_DIR/http-tarballs/`. Set `shared_extraction = true` on a tool to keep the previous deduplicated symlink layout. Existing symlinked installs keep working; `mise install --force <tool>` migrates one to independent files without disturbing other installs that share the content. Legacy `http-tarballs` entries are not reclaimed automatically. Shared raw and compressed binary caches now also include the executable filename in their key, so differently named tools no longer reuse the wrong filename. ([#​13059](https://redirect.github.com/jdx/mise/pull/13059) by [@​jdx](https://redirect.github.com/jdx))
- **oci:** `mise oci push --no-cache` now bypasses both the remote registry cache and the local tool-layer cache. ([#​13056](https://redirect.github.com/jdx/mise/pull/13056) by [@​jdx](https://redirect.github.com/jdx))
- **registry:** `postgres`, `redis`, and `mongodb` now prefer `conda:` backends, installing prebuilt conda-forge binaries in seconds instead of compiling through vfox; vfox and asdf remain as fallbacks. `conda:redis-server` covers Linux and macOS only. ([#​13061](https://redirect.github.com/jdx/mise/pull/13061) by [@​jdx](https://redirect.github.com/jdx))
#### Performance
- **lockfile:** Warm `mise install` runs in `lockfile_mode = "generate"` skip scheduling work for tools whose artifact metadata is already reusable, and skip rebuilding, serializing, and staging the lockfile entirely when nothing was installed and the on-disk lock already matches (preserving comments in the file). Explicit `mise lock`, forced provenance verification, upgrades, and new platforms still regenerate. ([#​13101](https://redirect.github.com/jdx/mise/pull/13101), [#​13103](https://redirect.github.com/jdx/mise/pull/13103) by [@​jdx](https://redirect.github.com/jdx))
- **oci:** `mise oci push --from BASE` no longer downloads base layers when the base and target live in the same repository, and `oci build`, `oci run`, and `oci push` share a local cache of packaged tool layers keyed on file contents, so repeated builds with overlapping tools skip tar and gzip work. ([#​13055](https://redirect.github.com/jdx/mise/pull/13055), [#​13056](https://redirect.github.com/jdx/mise/pull/13056) by [@​jdx](https://redirect.github.com/jdx))
#### Fixed
- **nushell:** `mise activate nu` no longer throws `env_variable_not_found` on every prompt or `cd` when a variable to hide is absent from the current scope; `hide-env` is now wrapped in `try`, matching the no-op behavior of other shells. ([#​13071](https://redirect.github.com/jdx/mise/pull/13071) by [@​i-api](https://redirect.github.com/i-api))
- **task:** Task-level tools are now auto-installed for tasks referenced from `run` entries, including names rendered at runtime, right before they execute; `--skip-tools` is honored and install failures are reported as task failures without blocking siblings. ([#​13086](https://redirect.github.com/jdx/mise/pull/13086) by [@​jdx](https://redirect.github.com/jdx))
- **config:** `[monorepo]` settings are now merged across same-directory config layers (base plus `mise.<env>.toml` overlays): omitted fields are inherited, an overlay's `config_roots` replaces the base list, and `monorepo_root = false` in an overlay disables the root and its descendant trust. ([#​13084](https://redirect.github.com/jdx/mise/pull/13084) by [@​jdx](https://redirect.github.com/jdx))
- **lockfile:** Runtime tool requests such as `mise which hk --tool hk@latest` now use the lockfile belonging to the config that effectively defines the tool, instead of merging project and global pins and reporting a false "multiple resolutions" ambiguity or selecting an overridden pin. `mise which --tool` warns when a lower-precedence config has a matching pin the effective config lacks. ([#​13042](https://redirect.github.com/jdx/mise/pull/13042) by [@​nettlesh](https://redirect.github.com/nettlesh))
- **lockfile:** Complete lockfile generation for Packslip tools skips platforms with no published artifact while still writing supported targets, and a verified Packslip signer may now replace legacy `github-attestations` metadata on upgrade instead of being rejected as a provenance downgrade. ([#​13102](https://redirect.github.com/jdx/mise/pull/13102), [#​13105](https://redirect.github.com/jdx/mise/pull/13105) by [@​jdx](https://redirect.github.com/jdx))
- **upgrade:** `mise upgrade` now detects updates between letter-suffixed versions such as tmux `3.7b` to `3.7c`; `sub-N` aliases keep resolving numeric components as before. ([#​13119](https://redirect.github.com/jdx/mise/pull/13119) by [@​jdx](https://redirect.github.com/jdx))
- **brew:** Formulae that are keg-only solely because macOS ships them (such as `brew:zip` and `brew:unzip`) are now linked into `<prefix>/bin` on Linux, matching Homebrew. Kegs installed by earlier mise versions stay unlinked until the next `mise bootstrap packages upgrade` or a reinstall. ([#​13108](https://redirect.github.com/jdx/mise/pull/13108) by [@​lil-lon](https://redirect.github.com/lil-lon))
- **brew-cask:** Tap casks with `preflight_steps` or `postflight_steps` no longer fail during metadata extraction; declarative `run` steps are captured as structured steps and executed by mise, with support for `must_succeed = false`. ([#​13060](https://redirect.github.com/jdx/mise/pull/13060) by [@​jdx](https://redirect.github.com/jdx))
- **bootstrap:** `mise bootstrap remote` on Windows now finds `ssh.exe` and `tar.exe` on PATH instead of failing with `required command 'ssh' not found`. ([#​13117](https://redirect.github.com/jdx/mise/pull/13117) by [@​JamBalaya56562](https://redirect.github.com/JamBalaya56562))
- **bootstrap:** macOS defaults status explains type mismatches, showing for example `2 (real; expected integer)` instead of two identical-looking values marked `differs`. ([#​13096](https://redirect.github.com/jdx/mise/pull/13096) by [@​jdx](https://redirect.github.com/jdx))
- **dotfiles:** `mise bootstrap dotfiles track` honors the global `yes` setting for confirmations, and warns when tracking a symlink whose resolved source is not itself tracked, suggesting the command to enroll it. ([#​13072](https://redirect.github.com/jdx/mise/pull/13072) by [@​nettlesh](https://redirect.github.com/nettlesh), [#​13095](https://redirect.github.com/jdx/mise/pull/13095) by [@​jdx](https://redirect.github.com/jdx))
- **schema:** The JSON schema now models Git directory `manifest` dotfile entries, restricting explicit modes to `copy` or `symlink-each` and rejecting combinations with inline content or file-edit fields. ([#​12741](https://redirect.github.com/jdx/mise/pull/12741) by [@​risu729](https://redirect.github.com/risu729))
- **asdf:** `mise asdf install` and `mise asdf reshim` no longer re-enter the full CLI dispatch, avoiding stack overflows on small-stack Linux environments; `asdf install` now follows the same implicit config trust as `mise install`. Bash completions are regenerated for the updated usage-rs word-break handling. ([#​13114](https://redirect.github.com/jdx/mise/pull/13114) by [@​jdx](https://redirect.github.com/jdx))
#### Registry
- Added `mpv` (`conda:mpv`, Linux and macOS) ([#​13049](https://redirect.github.com/jdx/mise/pull/13049) by [@​i-api](https://redirect.github.com/i-api)), `agent-browser` (`aqua:vercel-labs/agent-browser`) ([#​13088](https://redirect.github.com/jdx/mise/pull/13088) by [@​3w36zj6](https://redirect.github.com/3w36zj6)), and `himalaya` (`github:pimalaya/himalaya`) ([#​13091](https://redirect.github.com/jdx/mise/pull/13091) by [@​i-api](https://redirect.github.com/i-api)).
- `editorconfig-checker` installs again after 4.0.1 renamed its assets and executable; the shorthand now uses the GitHub backend. ([#​13098](https://redirect.github.com/jdx/mise/pull/13098) by [@​jdx](https://redirect.github.com/jdx))
- `mc` installs from MinIO's GitHub releases instead of the retired Aqua download URL that returned HTTP 410. ([#​13113](https://redirect.github.com/jdx/mise/pull/13113) by [@​jdx](https://redirect.github.com/jdx))
#### Documentation
- The docs landing page gains interactive diagrams for project environment switching, bootstrap machine resources, tool configuration precedence, artifact cache execution, and tracked dotfile synchronization. ([#​13065](https://redirect.github.com/jdx/mise/pull/13065), [#​13066](https://redirect.github.com/jdx/mise/pull/13066), [#​13067](https://redirect.github.com/jdx/mise/pull/13067), [#​13068](https://redirect.github.com/jdx/mise/pull/13068), [#​13069](https://redirect.github.com/jdx/mise/pull/13069) by [@​jdx](https://redirect.github.com/jdx))
- The task-running guide is reorganized around finding and running tasks, passing arguments, then controlling execution. ([#​13077](https://redirect.github.com/jdx/mise/pull/13077) by [@​azohra](https://redirect.github.com/azohra))
#### New Contributors
- [@​lil-lon](https://redirect.github.com/lil-lon) made their first contribution in [#​13108](https://redirect.github.com/jdx/mise/pull/13108)
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.9.5...v2026.9.6>
#### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.9.5`](https://redirect.github.com/jdx/mise/releases/tag/v2026.9.5): : macOS defaults, per-platform dotfiles, and complete lockfiles
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.9.4...vfox-v2026.9.5)
This release deepens macOS bootstrap support with current-host and nested defaults, lets dotfiles and tasks adapt to the platform and to parsed arguments, and adds an opt-in trial of complete lockfile generation. It also carries a batch of install progress, self-update, brew-cask, and sandbox fixes.
#### Added
- **bootstrap:** New `[[bootstrap.macos.defaults_entries]]` blocks let you set macOS preferences explicitly with `domain`, `key`, `value`, and an optional `host` (`any` by default, or `current`), covering preferences normally written via `defaults -currentHost` while keeping the existing `[bootstrap.macos.defaults]` shorthand. Entries also accept an optional `path` to patch a nested dictionary value without replacing its siblings, preserving property-list types and creating missing parents. ([#​12983](https://redirect.github.com/jdx/mise/pull/12983) by [@​azohra](https://redirect.github.com/azohra), [#​12984](https://redirect.github.com/jdx/mise/pull/12984) by [@​azohra](https://redirect.github.com/azohra))
```toml
[[bootstrap.macos.defaults_entries]]
domain = "com.apple.dock"
key = "autohide"
value = true
host = "current"
```
- **bootstrap:** More friendly macOS preferences: Finder folder sorting and default cloud save location, Dock autohide delay and timing (integers or floats), and keyboard automatic capitalization and spelling correction, all using snake\_case names consistent with the existing sections. ([#​13032](https://redirect.github.com/jdx/mise/pull/13032) by [@​jdx](https://redirect.github.com/jdx))
- **bootstrap:** `[bootstrap.files]` and `[bootstrap.directories]` entries gain `phase = "pre-packages"` so repository definitions, apt sources, and signing keys can be applied before package installation instead of only afterward. Existing declarations default to `"post-packages"`. ([#​13052](https://redirect.github.com/jdx/mise/pull/13052) by [@​jdx](https://redirect.github.com/jdx))
```toml
[bootstrap.files."/etc/apt/sources.list.d/vendor.sources"]
source = "./files/vendor.sources"
phase = "pre-packages"
```
- **bootstrap:** Ordinary `[bootstrap.files]` templates can now reference resolved `[vars]` values, alongside the existing `config_root`, `target`, and `secret()` helpers. ([#​13033](https://redirect.github.com/jdx/mise/pull/13033) by [@​nettlesh](https://redirect.github.com/nettlesh))
- **dotfiles:** A single dotfiles source can deploy to different destinations per operating system, architecture, or mise profile using `variants` with an optional `target`. This works for `copy`, `symlink`, `symlink-each`, and `template` modes. ([#​13050](https://redirect.github.com/jdx/mise/pull/13050) by [@​jdx](https://redirect.github.com/jdx))
```toml
[dotfiles.settings]
source = "dotfiles/vscode/settings.json"
mode = "copy"
variants = [
{ os = "macos", target = "~/Library/Application Support/Code/User/settings.json" },
{ os = "linux", target = "~/.config/Code/User/settings.json" },
]
```
- **task:** Task `sources` and `outputs` can now use `{{usage.*}}` templates, resolved per invocation from parsed arguments and flags before freshness and artifact-cache checks run, so different argument values track freshness independently. ([#​13051](https://redirect.github.com/jdx/mise/pull/13051) by [@​jdx](https://redirect.github.com/jdx))
- **brew-cask:** Casks with structured `set_permissions` preflight/postflight steps now install correctly (for example `brew-cask:blender`), running an unprivileged `chmod` over resolved staged or appdir paths instead of failing with an unsupported step-type error. ([#​13043](https://redirect.github.com/jdx/mise/pull/13043) by [@​azohra](https://redirect.github.com/azohra))
- **lock:** Opt-in trial of complete lockfile generation via `lockfile_mode = "generate"` (or `MISE_LOCKFILE_MODE=generate`). The default remains incremental `merge`. Generate mode rebuilds lockfiles from current requests while treating the previous file as an immutable baseline, reusing unchanged artifacts and publishing through staged atomic writes so failures or concurrent edits do not clobber a good lockfile. This mode records only cryptographically verified provenance per target platform; `provenance_verified` is no longer treated as a trust signal. ([#​13031](https://redirect.github.com/jdx/mise/pull/13031) by [@​jdx](https://redirect.github.com/jdx))
- **self-update:** New `disable_update_warning` setting (`MISE_DISABLE_UPDATE_WARNING`) suppresses "newer mise available" notices in `mise version`, `mise --version`, and `mise doctor`. Explicit self-update and automatic updates are unaffected. ([#​13028](https://redirect.github.com/jdx/mise/pull/13028) by [@​jdx](https://redirect.github.com/jdx))
#### Fixed
- **install:** Interactive installs no longer leave a permanent line for every resolved, skipped, or already-installed tool; live progress shows what is happening while the final summary lists what changed (for example `installed 1 tool in 1.1s: [email protected]`). `mise upgrade` no longer duplicates its old to new version list. ([#​13030](https://redirect.github.com/jdx/mise/pull/13030) by [@​jdx](https://redirect.github.com/jdx))
- **install:** Long non-TTY installs no longer flood CI logs with a snapshot every three seconds. The heartbeat now scales to roughly 10% of elapsed time, clamped between 3 seconds and 1 minute. ([#​13036](https://redirect.github.com/jdx/mise/pull/13036) by [@​jdx](https://redirect.github.com/jdx))
- **self-update:** On 32-bit ARM, `mise self-update` now selects the correct `linux-armv7` archive instead of requesting a missing `linux-arm` one and falling back to an ARM64 binary that failed signature verification. A missing archive now fails asset selection rather than picking the wrong architecture. ([#​13023](https://redirect.github.com/jdx/mise/pull/13023) by [@​jdx](https://redirect.github.com/jdx))
- **self-update:** npm installs now ship the instructions file that redirects update guidance to the package manager, so they no longer advertise `mise self-update`. ([#​13028](https://redirect.github.com/jdx/mise/pull/13028) by [@​jdx](https://redirect.github.com/jdx))
- **brew-cask:** `mise bootstrap packages upgrade` no longer replaces the bundle of a running self-updating app (for example Chrome), which could strand helper processes and blank out tabs. Such apps are skipped while running and left to update themselves. ([#​13041](https://redirect.github.com/jdx/mise/pull/13041) by [@​azohra](https://redirect.github.com/azohra))
- **brew-cask:** The cask metadata fetch error no longer includes stale advice about installing with `brew` and a broken documentation anchor; it now gives a short, accurate message. ([#​12800](https://redirect.github.com/jdx/mise/pull/12800) by [@​Marukome0743](https://redirect.github.com/Marukome0743))
- **bootstrap:** `mise bootstrap dotfiles origin set <url>` now uses the repository's own default branch when `--branch` is omitted, so repositories on `master` connect correctly instead of publishing a second root branch. A missing requested branch is now reported clearly rather than mistaken for an empty repository. ([#​13037](https://redirect.github.com/jdx/mise/pull/13037) by [@​Dhaulagiri](https://redirect.github.com/Dhaulagiri))
- **dotfiles:** History watcher locks now live alongside the history store in the state directory instead of being hashed into the cache directory, so a launchd watcher and an interactive shell using different cache directories coordinate correctly and `dotfiles status` no longer misreports `declared-not-running`. Existing watchers must be stopped and restarted with the updated binary. ([#​13038](https://redirect.github.com/jdx/mise/pull/13038) by [@​ascarter](https://redirect.github.com/ascarter))
- **sandbox:** The macOS Seatbelt profile now allows `file-read-metadata` on the ancestors of readable paths, fixing `Operation not permitted` failures when a portable Ruby resolves its own executable during third-party tap evaluation. Symlinked data directories and allow-listed paths are also handled. ([#​13039](https://redirect.github.com/jdx/mise/pull/13039) by [@​Marukome0743](https://redirect.github.com/Marukome0743))
#### Registry
- Added `clipboard` ([github:Slackadays/Clipboard](https://redirect.github.com/Slackadays/Clipboard)) by [@​i-api](https://redirect.github.com/i-api) in [#​13044](https://redirect.github.com/jdx/mise/pull/13044)
#### New Contributors
- [@​Dhaulagiri](https://redirect.github.com/Dhaulagiri) made their first contribution in [#​13037](https://redirect.github.com/jdx/mise/pull/13037)
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.9.4...v2026.9.5>
#### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.9.4`](https://redirect.github.com/jdx/mise/releases/tag/v2026.9.4): : Nix Bootstrap, Environment Selectors, and Man Pages
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.9.3...vfox-v2026.9.4)
This release expands the bootstrap package model with Nix support and environment selectors, teaches packslip tools to ship man pages, and adds a task-scoped quiet setting. It also carries a wide batch of packslip, bootstrap, and cross-platform fixes plus a major speedup to dotfiles history rebuilds.
#### Added
- **bootstrap:** Nix is now a built-in `[bootstrap.packages]` manager on Linux and macOS. Declare packages with the `nix:` prefix and apply them through your normal Nix profile; the manager supports use, apply, status JSON, and targeted upgrades while leaving Nix sources, caches, trust, and profile rollback under Nix control. This also adds `mise bootstrap packages export --format nix` to emit a deterministic NixOS module from your `nix:` declarations and `packages use --no-install` to record declarations without touching package managers. ([#​13013](https://redirect.github.com/jdx/mise/pull/13013) by [@​jdx](https://redirect.github.com/jdx))
```toml
[bootstrap.packages]
"nix:ripgrep" = "latest"
```
- **bootstrap:** `[bootstrap.packages]` entries gain an `env` selector (a single environment or a list), so a package is only enabled when one of its listed mise environments is active via `-E` or `MISE_ENV`. When both `os` and `env` are set, both must match. Packages for inactive environments stay declared and are protected from pruning. ([#​12956](https://redirect.github.com/jdx/mise/pull/12956) by [@​jdx](https://redirect.github.com/jdx))
```toml
[bootstrap.packages]
"brew:postgresql" = { version = "latest", env = ["dev", "test"] }
```
- **packslip:** Packslip-installed tools can now ship man pages declared as static `man` resources, alongside completions and agent skills. While a tool version is active, mise prepends its man root to `MANPATH` and keeps system and caller-defined paths visible, so `man <tool>` works. Existing installs need to be reinstalled to pick up man pages. ([#​13012](https://redirect.github.com/jdx/mise/pull/13012) by [@​jdx](https://redirect.github.com/jdx))
- **task:** New `task.quiet` setting (and `MISE_TASK_QUIET`) suppresses mise's own task messages, prefixes, and command-echo headers without hiding task output or affecting other commands. The bundled `output = "quiet"` mode is deprecated in favor of explicit output style plus this setting; removal is scheduled for 2027.9.3. ([#​12980](https://redirect.github.com/jdx/mise/pull/12980) by [@​jdx](https://redirect.github.com/jdx))
#### Fixed
- **install:** A lazy tool whose `depends` target is also lazy now installs correctly on first use through a shim, `mise x`, or a task; mise installs the provider together with its still-missing configured dependencies instead of failing the preflight. ([#​12997](https://redirect.github.com/jdx/mise/pull/12997) by [@​balintant](https://redirect.github.com/balintant))
- **backend:** 32-bit ARM resolution now uses Go's canonical `arm` architecture name for Aqua (so registry replacements apply), and automatic GitHub release asset selection no longer picks a generic `source.tar.gz` when no published binary targets the host. ([#​13004](https://redirect.github.com/jdx/mise/pull/13004) by [@​jdx](https://redirect.github.com/jdx))
- **bootstrap:** Homebrew bottles with hard-linked Mach-O executables are now signed correctly on macOS. Every hard-link alias is tracked and included in the signing list after relocation, fixing cases like fish where an aliased binary was killed with SIGKILL after a successful install. ([#​12988](https://redirect.github.com/jdx/mise/pull/12988) by [@​nettlesh](https://redirect.github.com/nettlesh))
- **packslip:** `mise lock --platform` now verifies the signed release manifest and records the correct URL, checksum, size, and signer for each requested target platform (including Windows x64), so locked installs work across platforms. ([#​13002](https://redirect.github.com/jdx/mise/pull/13002) by [@​jdx](https://redirect.github.com/jdx))
- **packslip:** On glibc Linux, an artifact's `glibc_min` is now honored during selection: when the GNU build requires a newer glibc than the host, mise falls back to a matching static musl build if one exists. ([#​13009](https://redirect.github.com/jdx/mise/pull/13009) by [@​jdx](https://redirect.github.com/jdx))
- **packslip:** Windows installs now link shims with the correct `.exe` filename, while Unix keeps extensionless names. ([#​13006](https://redirect.github.com/jdx/mise/pull/13006) by [@​jdx](https://redirect.github.com/jdx))
- **packslip:** Activated man roots are now scoped to Packslip-backed tool versions, and the caller's original `MANPATH` is included in the environment-cache identity so one cached process cannot serve another caller's `MANPATH`. ([#​13016](https://redirect.github.com/jdx/mise/pull/13016) by [@​jdx](https://redirect.github.com/jdx))
- **prune:** `mise prune` no longer exits successfully without pruning when it cannot show a confirmation prompt; it now fails with guidance to pass `--yes` or set `MISE_YES=1`. Follow-up prunes from commands like `mise unuse` still leave installs in place when nobody can answer. ([#​13003](https://redirect.github.com/jdx/mise/pull/13003) by [@​jdx](https://redirect.github.com/jdx))
- **generate:** `mise generate tool-stub` now respects a stub's top-level `os` selector when deciding whether to write a Windows `.cmd` launcher, so a linux/macos-only stub no longer produces a launcher even with `--lock`. ([#​13008](https://redirect.github.com/jdx/mise/pull/13008) by [@​jdx](https://redirect.github.com/jdx))
- **dotfiles:** History path filters resolve correctly when `HOME` is a symlink, so aliased, canonical, and tilde paths address the same history entry and `show latest`/`diff` no longer report a missing checkpoint. ([#​12982](https://redirect.github.com/jdx/mise/pull/12982) by [@​azohra](https://redirect.github.com/azohra))
- **brew:** The published crate now includes the tap formula and cask metadata shims, fixing `cargo install --locked mise` builds from crates.io. ([#​13001](https://redirect.github.com/jdx/mise/pull/13001) by [@​jdx](https://redirect.github.com/jdx))
#### Changed
- **bootstrap:** `[bootstrap].config_roots` and the `mise bootstrap config-roots` command are now deprecated (hidden from help and removed from public docs), with removal scheduled for mise 2027.3.3. Existing configurations keep working during the compatibility window but emit a warning directing users to global or system bootstrap configuration. ([#​13010](https://redirect.github.com/jdx/mise/pull/13010) by [@​jdx](https://redirect.github.com/jdx))
- **registry:** Added basecamp to the registry. ([#​13024](https://redirect.github.com/jdx/mise/pull/13024))
#### Performance
- **history:** Dotfiles history index rebuilds are dramatically faster, reconstructing checkpoint metadata in-process with gix instead of spawning Git per checkpoint. On an 80-checkpoint, 44-file reproducer this cut a rebuild from roughly 26-28 seconds and thousands of Git processes down to under a second. Removed annotations are now correctly dropped after a rebuild, and SHA-256 history repositories are supported. ([#​13011](https://redirect.github.com/jdx/mise/pull/13011) by [@​jdx](https://redirect.github.com/jdx))
#### Deprecated
- The task `output = "quiet"` mode (use `task.quiet` instead; removal in 2027.9.3) ([#​12980](https://redirect.github.com/jdx/mise/pull/12980)).
- `[bootstrap].config_roots` and `mise bootstrap config-roots` (removal in mise 2027.3.3) ([#​13010](https://redirect.github.com/jdx/mise/pull/13010)).
#### New Contributors
- [@​balintant](https://redirect.github.com/balintant) made their first contribution in [#​12997](https://redirect.github.com/jdx/mise/pull/12997)
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.9.3...v2026.9.4>
#### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
### [`v2026.9.3`](https://redirect.github.com/jdx/mise/releases/tag/v2026.9.3): : Winget bootstrap, signed vfox plugins, and faster inline commands
[Compare Source](https://redirect.github.com/jdx/mise/compare/vfox-v2026.9.2...vfox-v2026.9.3)
This release brings Windows bootstrap into the package-manager era with WinGet support, extends the packslip signing model to vfox plugins, and speeds up simple tasks by skipping the shell on Unix. It also carries a batch of bootstrap, sandbox, and Windows ARM64 fixes.
##### Added
- **bootstrap:** WinGet is now a built-in `[bootstrap.packages]` manager on Windows, so `mise bootstrap packages` can check status, install, and upgrade apps by exact package ID. It supports version pins, source refresh, and automatic source-agreement acceptance. Scoop, Chocolatey, and package removal remain future work. ([#​12928](https://redirect.github.com/jdx/mise/pull/12928) by [@​jdx](https://redirect.github.com/jdx))
```toml
[bootstrap.packages]
"winget:Microsoft.PowerShell" = "latest"
```
- **vfox:** External vfox plugins can now be installed from signed packslip archives instead of a Git clone, reusing the packslip backend's release selection, signature verification, digest checks, and signer pins. This is aimed at non-registry plugins; registry defaults and embedded plugins are unchanged. ([#​12948](https://redirect.github.com/jdx/mise/pull/12948) by [@​jdx](https://redirect.github.com/jdx))
```sh
mise plugins install vfox:bfs 'packslip:mise-plugins/vfox-bfs#0.1.0'
```
- **bootstrap:** Dotfile line edits gain `position = "prepend"` to insert a managed line at the top of a file instead of appending (the default). An existing exact match is left in place, and unrelated bytes, CRLF endings, and a UTF-8 BOM are preserved. ([#​12941](https://redirect.github.com/jdx/mise/pull/12941) by [@​jdx](https://redirect.github.com/jdx))
```toml
[dotfiles]
"/etc/zshrc/zdotdir" = { line = 'ZDOTDIR=$HOME/.config/zsh/', position = "prepend" }
```
- **bootstrap:** macOS bootstrap `defaults` now support nested TOML arrays and tables (for example Dock `persistent-apps`), reading and writing preferences through Core Foundation so booleans, numbers, strings, arrays, and dictionaries keep their plist types. Collections apply as whole-value replacements; datetimes and binary plist data are still skipped with a warning. ([#​12947](https://redirect.github.com/jdx/mise/pull/12947) by [@​jdx](https://redirect.github.com/jdx))
##### Changed
- **bootstrap:** Adopting global configuration or a shared dotfile-history setup repository is now spelled `mise bootstrap --adopt` (and `mise bootstrap remote --adopt`), separate from `mise bootstrap --from` for running a bootstrap project. The dotfiles, history, setup, and services guides were reorganized to lead with usable examples. The previous `--from-git` spelling still works as a hidden alias but warns and is scheduled for removal in mise 2026.10.0. ([#​12953](https://redirect.github.com/jdx/mise/pull/12953) by [@​jdx](https://redirect.github.com/jdx))
##### Fixed
- **github:** Git operations (clones, fetches, submodules) that GitHub now challenges with HTTP 401 on public repositories can authenticate using mise's existing GitHub token sources via a command-scoped `github.com` HTTPS credential helper. Tokens are kept out of command arguments and URLs, and Enterprise hosts are out of scope. ([#​12945](https://redirect.github.com/jdx/mise/pull/12945) by [@​jdx](https://redirect.github.com/jdx))
- **config:** The default inline task shell is now `sh -o errexit -c` so shells that consume the argument right after `-c` (such as FreeBSD sh) run your command instead of trying to execute `-o`. ([#​12949](https://redirect.github.com/jdx/mise/pull/12949) by [@​jdx](https://redirect.github.com/jdx))
- **windows:** Fixed two Windows ARM64 issues: stale command-wrapper shims (like a leftover `cargo.exe`) that caused recursive `.exe`/`.cmd` dispatch after shim-mode changes are now pruned, and Aqua ARM64 emulation candidates apply the registry's `amd64` replacement so tools like LuaLS resolve their published `win32-x64` assets. ([#​12931](https://redirect.github.com/jdx/mise/pull/12931) by [@​jdx](https://redirect.github.com/jdx))
- **bootstrap:** Bootstrap no longer aborts on Arch when `pacman -Q` prints a file advisory for a missing package that shares its name with a directory in the current working directory (for example a `fish/` folder in a dotfiles checkout). ([#​12932](https://redirect.github.com/jdx/mise/pull/12932) by [@​nettlesh](https://redirect.github.com/nettlesh))
- **sandbox:** Read-restricted macOS Seatbelt profiles now allow metadata-only access to `/private`, fixing startup failures for load-relative binaries like Ruby 4.0.6 when run under `/private/tmp`. Directory listings and descendant reads stay denied. ([#​12940](https://redirect.github.com/jdx/mise/pull/12940) by [@​jdx](https://redirect.github.com/jdx))
- **bootstrap:** The macOS notification helper is now built and Developer ID-signed at release time and spawned with a start handshake, so short `dotfiles sync` runs no longer race the helper and macOS accepts it. Unsigned source builds (such as Homebrew) disable notifications and warn during origin setup. ([#​12946](https://redirect.github.com/jdx/mise/pull/12946) by [@​jdx](https://redirect.github.com/jdx))
- **vfox:** vfox install phases now flow through the active install progress reporter, mapping noisy download, checksum, attestation, and extraction lines into concise phases instead of scrolling log output. ([#​12944](https://redirect.github.com/jdx/mise/pull/12944) by [@​jdx](https://redirect.github.com/jdx))
- **java:** The `java -version` banner shown during install verification now stays inside the interactive install progress row instead of printing to the terminal. ([#​12943](https://redirect.github.com/jdx/mise/pull/12943) by [@​jdx](https://redirect.github.com/jdx))
- **version:** The auto-update hint from `mise version` now uses the `mise settings auto_update=true` syntax to match the rest of `mise settings`. ([#​12957](https://redirect.github.com/jdx/mise/pull/12957) by [@​jdx](https://redirect.github.com/jdx))
##### Performance
- On Unix, plain inline commands (like `node build.js`) now run directly when a conservative planner deems them safe, skipping the shell wrapper. Anything involving shell syntax, quoting, expansion, builtins, ambiguous PATH lookup, explicit shell settings, or sandboxed/audited tasks still uses the shell, and Windows is unchanged. In a microbenchmark of short commands this cut about 11% off elapsed time. ([#​12950](https://redirect.github.com/jdx/mise/pull/12950) by [@​jdx](https://redirect.github.com/jdx))
##### Registry
- Added cargo-deny, kingfisher, nushell, shellharden, sherif, and tauri-cli. ([#​12938](https://redirect.github.com/jdx/mise/pull/12938) by [@​jrandolf](https://redirect.github.com/jrandolf))
##### Documentation
- Restored the prominent project name and pronunciation on the homepage. ([#​12936](https://redirect.github.com/jdx/mise/pull/12936) by [@​jdx](https://redirect.github.com/jdx))
- Dropped the "you need Git installed" prerequisite from the install docs. ([#​12958](https://redirect.github.com/jdx/mise/pull/12958) by [@​jdx](https://redirect.github.com/jdx))
**Full Changelog**: <https://github.com/jdx/mise/compare/v2026.9.2...v2026.9.3>
##### 💚 Sponsor mise
mise is built and maintained by [@​jdx](https://redirect.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.
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC43OS4xIiwidXBkYXRlZEluVmVyIjoiNDQuNzkuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@jest/globals](https://redirect.github.com/jestjs/jest) ([source](https://redirect.github.com/jestjs/jest/tree/HEAD/packages/jest-globals)) | [`30.4.1` → `30.5.1`](https://renovatebot.com/diffs/npm/@jest%2fglobals/30.4.1/30.5.1) |  |  |
| [jest](https://jestjs.io/) ([source](https://redirect.github.com/jestjs/jest/tree/HEAD/packages/jest)) | [`30.4.2` → `30.5.1`](https://renovatebot.com/diffs/npm/jest/30.4.2/30.5.1) |  |  |
---
### Release Notes
<details>
<summary>jestjs/jest (@​jest/globals)</summary>
### [`v30.5.1`](https://redirect.github.com/jestjs/jest/blob/HEAD/CHANGELOG.md#3051)
[Compare Source](https://redirect.github.com/jestjs/jest/compare/v30.5.0...v30.5.1)
##### Fixes
- `[jest-config]` Don't warn about global-only options in the config that supplies the global config - the root config a project resolves to, or the first entry of `--projects` when no root config is passed ([#​16411](https://redirect.github.com/jestjs/jest/pull/16411))
- `[jest-config, jest-types]` Stop accepting `reporters`, `coverageReporters`, `workerIdleMemoryLimit`, `cwd` and `runnerOptions` in a project config - they were silently ignored, and now warn like the other global-only options ([#​16411](https://redirect.github.com/jestjs/jest/pull/16411))
- `[jest-config, jest-validate]` Warn about `maxWorkers` and `coverageThreshold` in a project config instead of dropping them without a word ([#​16411](https://redirect.github.com/jestjs/jest/pull/16411))
- `[jest-resolve]` Match `moduleNameMapper` patterns against the specifier as written again (reverting [#​16390](https://redirect.github.com/jestjs/jest/pull/16390)) ([#​16417](https://redirect.github.com/jestjs/jest/pull/16417))
- `[jest-runtime]` Resolve package `imports` specifiers like `#dep` under ESM again ([#​16413](https://redirect.github.com/jestjs/jest/pull/16413))
##### Chore & Maintenance
- `[jest-util]` Name the `testEnvironmentOptions.globalsCleanup` option and link the docs from the `JEST-01` deprecation warning, and document the option's modes ([#​16404](https://redirect.github.com/jestjs/jest/pull/16404))
### [`v30.5.0`](https://redirect.github.com/jestjs/jest/blob/HEAD/CHANGELOG.md#3050)
[Compare Source](https://redirect.github.com/jestjs/jest/compare/v30.4.1...v30.5.0)
##### Features
- `[@jest/expect-utils, jest-mock]` Add `mockFn.whenCalledWith(...args)` for configuring return values per argument list, with first-class asymmetric-matcher support ([#​16053](https://redirect.github.com/jestjs/jest/pull/16053))
- `[@jest/expect-utils]` Export `AsymmetricMatcher` and `FunctionParameters` types (previously private to `expect`) ([#​16053](https://redirect.github.com/jestjs/jest/pull/16053))
- `[jest-circus, jest-core, jest-jasmine2, jest-test-result, jest-types]` `--collectTests` now expands `test.each`/`describe.each` cases and reports per-status counts (skipped/todo via the new `wouldRun` flag for selected tests) plus a summary line that match a real run, including under `--testNamePattern` and `.only`/`fdescribe` focus on both the circus and jasmine2 runners ([#​16259](https://redirect.github.com/jestjs/jest/pull/16259))
- `[jest-circus, jest-environment, jest-runtime, jest-types]` Add describe-level retries via `jest.retryTimes(..., {entireDescribe: true})` ([#​16322](https://redirect.github.com/jestjs/jest/pull/16322))
- `[jest-circus, jest-message-util, jest-reporters, jest-types]` Add `retryMessages` to `AssertionResult` and export `formatErrorStack`, so the retry log renders nested `cause` and `AggregateError` sections with code frames instead of serialized `[cause]:`/`[errors]:` markers ([#​16316](https://redirect.github.com/jestjs/jest/pull/16316))
- `[jest-circus, jest-types]` Add `unhandledErrorsDetailed` to `Circus.RunResult`, so an unhandled rejection reports its `cause` chain and `AggregateError` entries with code frames instead of a pre-serialized stack ([#​16316](https://redirect.github.com/jestjs/jest/pull/16316))
- `[jest-haste-map]` Replace `NodeWatcher` and `FSEventsWatcher` with `@parcel/watcher` for the non-watchman watch path ([#​16188](https://redirect.github.com/jestjs/jest/pull/16188))
- `[jest-resolve]` Bump `unrs-resolver` to 1.12.1, remove `jest-pnp-resolver` and unnecessary checks ([#​15721](https://redirect.github.com/jestjs/jest/pull/15721))
- `[jest-resolve]` Honor Node's `--preserve-symlinks` / `NODE_PRESERVE_SYMLINKS` in the default resolver by passing `symlinks: false` to `unrs-resolver` ([#​16260](https://redirect.github.com/jestjs/jest/pull/16260))
- `[jest-runtime]` Apply automocking and manual `__mocks__` files to synchronously evaluable ESM graphs on Node 24.9+ - static imports, dynamic `import()` and `require()` of an ESM file now generate an automock from the real module's namespace instead of failing with "Attempting to import a mock without a factory". Graphs that need async evaluation (top-level await) or an async-only resolver or transformer still throw ([#​16391](https://redirect.github.com/jestjs/jest/pull/16391))
- `[jest-runtime]` Route `process.getBuiltinModule` through the sandbox, so it returns the sandbox `process` and the hooked `node:module` instead of the host's ([#​16391](https://redirect.github.com/jestjs/jest/pull/16391))
- `[jest-runtime]` Throw an actionable error from `module.register()` and `module.registerHooks()` inside a test - the hooks attached to the loader running Jest itself, never saw the sandboxed requires they were meant for, and stayed registered for every later test file in the worker ([#​16391](https://redirect.github.com/jestjs/jest/pull/16391))
- `[jest-runtime]` Surface resolution and import-attribute errors in an ESM graph before executing any of its CJS dependencies on Node 24.9+, matching Node's run-nothing-on-a-broken-graph behavior; the legacy loader on older versions keeps its linking-time execution order ([#​16391](https://redirect.github.com/jestjs/jest/pull/16391))
- `[jest-runtime]` Throw `ERR_SOURCE_PHASE_NOT_DEFINED` with an actionable message for `import source` and `import.source()`, instead of failing at instantiation with V8's bare "Source phase import object is not defined" ([#​16391](https://redirect.github.com/jestjs/jest/pull/16391))
- `[jest-runtime]` Emit the JSON-without-import-attribute deprecation warning once per test file instead of once per worker, so it is no longer silently swallowed for every file after the first ([#​16391](https://redirect.github.com/jestjs/jest/pull/16391))
- `[jest-runtime]` Set `import.meta.main` to `true` in the test file and `false` in every module it loads, matching Node 24+ ([#​16367](https://redirect.github.com/jestjs/jest/pull/16367))
- `[jest-runtime]` Resolve the `module-sync` export condition, so a package that exposes its ESM entry point for `require()` loads the same file Node would ([#​16336](https://redirect.github.com/jestjs/jest/pull/16336))
- `[jest-snapshot]` Add external snapshot paths to custom reporter failure details ([#​16374](https://redirect.github.com/jestjs/jest/pull/16374))
##### Fixes
- `[jest-console, jest-reporters]` `CustomConsole` now buffers console output so `TestResult.console` is populated for reporters when `verbose` is enabled, while `GitHubActionsReporter` avoids replaying buffered output in verbose mode ([#​16155](https://redirect.github.com/jestjs/jest/pull/16155))
- `[expect, jest-message-util, jest-pattern, jest-regex-util, jest-util]` Revert `node:` protocol imports to restore webpack/browser-bundle compatibility ([#​16167](https://redirect.github.com/jestjs/jest/pull/16167))
- `[expect]` Widen `toMatchObject` and `objectContaining` parameter type from `Record<string, unknown>` to `object` so class instances are accepted ([#​16196](https://redirect.github.com/jestjs/jest/pull/16196))
- `[jest-circus]` Call a generator test body with the shared test context, so `this` matches what a regular test function receives ([#​16347](https://redirect.github.com/jestjs/jest/pull/16347))
- `[jest-circus]` Capture the error listeners of the parent process instead of the in-sandbox `process`, so listeners registered before the test file survive teardown and sandbox listeners no longer leak onto the parent ([#​16347](https://redirect.github.com/jestjs/jest/pull/16347))
- `[jest-circus]` Clear `currentlyRunningTest` after skipped and todo tests ([#​16342](https://redirect.github.com/jestjs/jest/pull/16342))
- `[jest-circus]` Prevent late `done()` callbacks from affecting later test or hook invocations ([#​16343](https://redirect.github.com/jestjs/jest/pull/16343))
- `[jest-circus, jest-jasmine2]` Honor `--expand` when formatting `node:assert` failures, instead of always collapsing the diff ([#​16347](https://redirect.github.com/jestjs/jest/pull/16347))
- `[jest-circus, jest-jasmine2, jest-message-util]` Serialize the inner errors of an `AggregateError` into `failureMessages`, `retryReasons` and `unhandledErrors`, so `--json` output and reporter annotations include them ([#​16316](https://redirect.github.com/jestjs/jest/pull/16316))
- `[jest-circus, jest-snapshot]` Keep snapshot state and counts correct when a test retries ([#​16344](https://redirect.github.com/jestjs/jest/pull/16344))
- `[@jest/create-cache-key-function]` Include the caller support flags in the generated key, so a transformer that emits ESM or CJS based on them no longer shares one cache entry between the two ([#​16331](https://redirect.github.com/jestjs/jest/pull/16331))
- `[@jest/create-cache-key-function]` Include the stringified project config in the generated key, so editing a transformer's own settings invalidates what it cached ([#​16331](https://redirect.github.com/jestjs/jest/pull/16331))
- `[@jest/transform]` Include the caller support flags in a transform's cache key, so a file transformed both as ESM and as CJS no longer serves one shape's output for the other ([#​16331](https://redirect.github.com/jestjs/jest/pull/16331))
- `[jest-config]` Add missing `findRelatedTests`, `outputFile`, and `replname` entries to `ValidConfig` so they no longer trigger spurious "Unknown option" warnings ([#​16224](https://redirect.github.com/jestjs/jest/pull/16224))
- `[jest-config]` Use `--config` for the global config when multiple `--projects` are specified ([#​16273](https://redirect.github.com/jestjs/jest/pull/16273))
- `[jest-core]` Serialize `bigint` values in `--json` and `--outputFile` output as their literal form (`4n`), instead of failing the run with `TypeError: Do not know how to serialize a BigInt` ([#​16338](https://redirect.github.com/jestjs/jest/pull/16338))
- `[jest-core]` Do not report a `CustomGC` async resource (used by N-API addons such as napi-rs for per-isolate GC bookkeeping) as an open handle, since it is `napi_unref`'d by the addon and can never keep the event loop alive ([#​16379](https://redirect.github.com/jestjs/jest/pull/16379))
- `[jest-each]` Keep a `$&`, `` $` ``, `$'` or `$$` inside a `%p` param value out of the replacement, so the title shows the value instead of the text around it ([#​16338](https://redirect.github.com/jestjs/jest/pull/16338))
- `[jest-each]` Interpolate a `bigint` into a `%j` title as its literal form (`"4n"`) at any depth, instead of throwing `TypeError: Do not know how to serialize a BigInt` while collecting the tests ([#​16338](https://redirect.github.com/jestjs/jest/pull/16338))
- `[jest-environment, jest-runtime]` Bind `sandboxInjectedGlobals` to the right values when `injectGlobals` is `false`, instead of shifting every one of them by a position ([#​16377](https://redirect.github.com/jestjs/jest/pull/16377))
- `[jest-environment-node, jest-util]` Only warn about a conflicting `globalsCleanup` mode when one was explicitly configured, and follow the mode that is actually in effect ([#​16323](https://redirect.github.com/jestjs/jest/pull/16323))
- `[jest-environment-node, jest-util]` Stop resolving lazy globals when setting up an environment, so Node 26's builtin module globals are no longer loaded (and no longer emit their deprecation warnings) for every test file ([#​16324](https://redirect.github.com/jestjs/jest/pull/16324))
- `[jest-haste-map]` Keep watch mode alive when an outside process briefly makes a file unreadable on Windows, instead of tearing the watcher down on `EPERM` ([#​16295](https://redirect.github.com/jestjs/jest/pull/16295))
- `[jest-haste-map]` Keep indexing when an outside process holds a file open on Windows, instead of failing the whole crawl on `EPERM` ([#​16358](https://redirect.github.com/jestjs/jest/pull/16358))
- `[jest-haste-map]` Keep a duplicated manual mock resolving when the file it pointed at is deleted in watch mode ([#​16360](https://redirect.github.com/jestjs/jest/pull/16360))
- `[jest-haste-map]` Shut the worker farm down when a duplicate manual mock aborts the build under `throwOnModuleCollision` ([#​16354](https://redirect.github.com/jestjs/jest/pull/16354))
- `[jest-haste-map]` Attach the watchman client's `error` listener before the first command, so a watchman failure falls back to the node crawler instead of crashing on an unhandled `error` event, and always end the client ([#​16355](https://redirect.github.com/jestjs/jest/pull/16355))
- `[jest-haste-map]` Stop delivering watch events after `WatchmanWatcher` is closed, and route its warnings through the configured console ([#​16355](https://redirect.github.com/jestjs/jest/pull/16355))
- `[jest-haste-map]` Restore the nested `duplicates` index correctly in `ModuleMap.fromJSON`, so a haste collision reported inside a test worker raises `DuplicateHasteCandidatesError` instead of a `TypeError` ([#​16353](https://redirect.github.com/jestjs/jest/pull/16353))
- `[jest-haste-map]` Match watched files on a full extension, so `moduleFileExtensions: ['js']` no longer accepts `foo.mjs` ([#​16352](https://redirect.github.com/jestjs/jest/pull/16352))
- `[jest-haste-map]` Delimit the fields that make up the haste map cache key, so two different option sets cannot hash to the same cache file ([#​16352](https://redirect.github.com/jestjs/jest/pull/16352))
- `[jest-message-util]` Print the inner errors of an `AggregateError` thrown inside a test ([#​16316](https://redirect.github.com/jestjs/jest/pull/16316))
- `[jest-message-util]` Indent nested `cause` and `AggregateError` sections of a test failure by one level per depth, so the nesting is legible instead of rendering flat ([#​16316](https://redirect.github.com/jestjs/jest/pull/16316))
- `[jest-message-util]` Color stack traces line by line so blank lines stay blank ([#​16316](https://redirect.github.com/jestjs/jest/pull/16316))
- `[jest-message-util]` Detect Jest's own frames without assuming the checkout directory's name, and cover `@jest/*` packages, so stack traces and code frames point at user code ([#​16326](https://redirect.github.com/jestjs/jest/pull/16326))
- `[jest-mock]` `mockResolvedValue` / `mockRejectedValue` now see all overload return types, so a Promise-returning overload survives even when a later overload returns a non-Promise (e.g. `pg.Client['end']`) ([#​16237](https://redirect.github.com/jestjs/jest/pull/16237))
- `[@jest-environment/jsdom-abstract]` Make `@types/jsdom` a peer dependency ([#​16166](https://redirect.github.com/jestjs/jest/pull/16166))
- `[jest-mock]` Remove the leftover own accessor descriptor when restoring a `spyOn` of an inherited getter or setter, so the instance keeps reflecting the prototype ([#​16226](https://redirect.github.com/jestjs/jest/pull/16226))
- `[jest-resolve]` Include `extensionsToTreatAsEsm` in the `shouldLoadAsEsm` cache key, so projects with different extension lists don't read each other's answers ([#​16369](https://redirect.github.com/jestjs/jest/pull/16369))
- `[jest-resolve]` Make `getModuleIDAsync` build and cache `data:` URI module IDs the same way as `getModuleID` ([#​16370](https://redirect.github.com/jestjs/jest/pull/16370))
- `[jest-resolve]` Keep the `node:` prefix when resolving a core module asynchronously, so a builtin that only exists prefixed (`node:sea`, `node:sqlite`, `node:test`, `node:test/reporters`) resolves instead of failing as a missing bare package ([#​16388](https://redirect.github.com/jestjs/jest/pull/16388))
- `[jest-resolve]` Look up manual mocks for `node:` protocol specifiers under the unprefixed name they are stored as ([#​16388](https://redirect.github.com/jestjs/jest/pull/16388))
- `[jest-resolve]` Apply `moduleNameMapper` consistently to both spellings of core module specifiers (`fs` vs `node:fs`) ([#​16390](https://redirect.github.com/jestjs/jest/pull/16390))
- `[jest-resolve]` Keep virtual and ordinary mock module IDs isolated across test files ([#​16296](https://redirect.github.com/jestjs/jest/pull/16296))
- `[jest-resolve]` Guard missing `require.resolve.paths` ([#​16052](https://redirect.github.com/jestjs/jest/pull/16052))
- `[jest-resolve, jest-config, jest-runner]` Support a user resolver written as an ES module ([#​16332](https://redirect.github.com/jestjs/jest/pull/16332))
- `[jest-resolve, jest-runtime]` Throw the CJS parse error for ESM syntax in a `"type": "commonjs"` package or a `.cjs` file instead of loading it as ESM, matching Node ([#​16368](https://redirect.github.com/jestjs/jest/pull/16368))
- `[@jest/source-map]` Keep source map sources that name a scheme, such as `webpack:///`, instead of resolving them into a path that does not exist ([#​16327](https://redirect.github.com/jestjs/jest/pull/16327))
- `[@jest/source-map]` Look up `--testLocationInResults` positions at the right column, and keep a mapping to the first column instead of discarding it ([#​16327](https://redirect.github.com/jestjs/jest/pull/16327))
- `[@jest/source-map]` Warn when a source map cannot be parsed, instead of silently leaving its frames untranslated ([#​16327](https://redirect.github.com/jestjs/jest/pull/16327))
- `[jest-runner, @jest/source-map]` Keep a source-mapped stack for an error thrown after the test environment was torn down ([#​16327](https://redirect.github.com/jestjs/jest/pull/16327))
- `[jest-runtime, @jest/source-map]` Keep source maps past teardown and past the next test file's `install`, so a stack from a file no earlier stack mentioned still points at the original source ([#​16330](https://redirect.github.com/jestjs/jest/pull/16330))
- `[jest-runtime]` Report that no coverage was collected when `getAllV8CoverageInfoCopy` is called after `teardown`, instead of returning an empty result ([#​16385](https://redirect.github.com/jestjs/jest/pull/16385))
- `[jest-runtime]` Cache a CJS module's parsed exports before walking its re-exports, so two modules that re-export each other no longer overflow the stack when imported from ESM ([#​16363](https://redirect.github.com/jestjs/jest/pull/16363))
- `[jest-runtime]` Keep a re-exported ES module's parse failure from marking the re-exporting CommonJS file as ESM, so `module.exports = require('./dep.mjs')` loads instead of failing with `module is not defined` ([#​16363](https://redirect.github.com/jestjs/jest/pull/16363))
- `[jest-runtime]` Scope module mocks instantiated inside `jest.isolateModules`/`isolateModulesAsync` to that block, so a mock first imported there no longer outlives it - matching how CommonJS mocks already behave ([#​16365](https://redirect.github.com/jestjs/jest/pull/16365))
- `[jest-runtime]` Suspend module isolation while generating an automock, so loading the real module to read its shape no longer populates the isolated registry ([#​16365](https://redirect.github.com/jestjs/jest/pull/16365))
- `[jest-runtime]` Check a cached ES module's status before `require()` returns it, so a module whose evaluation threw rethrows that error and one left linked by a failed sibling is evaluated instead of returning uninitialized bindings ([#​16364](https://redirect.github.com/jestjs/jest/pull/16364))
- `[jest-runtime]` Report the original `ERR_REQUIRE_ASYNC_MODULE` when a `require()` of a top-level-await graph is retried, instead of a spurious "concurrent `import()`" error ([#​16364](https://redirect.github.com/jestjs/jest/pull/16364))
- `[jest-runtime]` Throw the evaluation error when another caller's `import()` of the same module failed while we awaited it, instead of resolving with the errored module ([#​16364](https://redirect.github.com/jestjs/jest/pull/16364))
- `[jest-runtime]` Mark the result of `require()`ing an ES module that has a default export with `__esModule: true` through a live-binding facade, and serve the same object from `require.cache`, matching Node ([#​16367](https://redirect.github.com/jestjs/jest/pull/16367))
- `[jest-runtime]` Provide a CommonJS module's exports under the `'module.exports'` named export when imported from ESM, matching Node 23+ ([#​16367](https://redirect.github.com/jestjs/jest/pull/16367))
- `[jest-runtime]` Give the test file itself a non-null `require.main` ([#​16367](https://redirect.github.com/jestjs/jest/pull/16367))
- `[jest-runtime]` Populate `module.children` with the modules a file loads, matching Node ([#​16368](https://redirect.github.com/jestjs/jest/pull/16368))
- `[jest-runtime]` Provide `import.meta.resolve` and `import.meta.jest` in `data:` URI modules, accept any-case mediatype parameters, and use Node's error codes for invalid `data:` URIs ([#​16368](https://redirect.github.com/jestjs/jest/pull/16368))
- `[jest-runtime]` Key ES modules by full URL, so query and fragment suffixes create the same module instances as Node and show up in `import.meta.url` ([#​16375](https://redirect.github.com/jestjs/jest/pull/16375))
- `[jest-runtime]` Share modules between overlapping graphs when a CommonJS module `require()`s an ES module mid-load, instead of evaluating shared dependencies twice ([#​16375](https://redirect.github.com/jestjs/jest/pull/16375))
- `[jest-runtime]` Throw `ERR_REQUIRE_CYCLE_MODULE` like Node when a CommonJS module `require()`s an ES module that is still being loaded, instead of evaluating the module a second time ([#​16366](https://redirect.github.com/jestjs/jest/pull/16366))
- `[jest-runtime]` Key builtin modules in the ESM registry by one canonical specifier ([#​16341](https://redirect.github.com/jestjs/jest/pull/16341))
- `[jest-runtime]` `import.meta.resolve()` for a builtin uses its `node:` specifier ([#​16341](https://redirect.github.com/jestjs/jest/pull/16341))
- `[jest-runtime]` Fall back to native ESM when a `.js` file contains ESM syntax but has no `"type":"module"` marker ([#​16152](https://redirect.github.com/jestjs/jest/pull/16152))
- `[jest-runtime]` Allow `require()` of ESM-marked files on Node < 24.9 via transform fallback ([#​16244](https://redirect.github.com/jestjs/jest/pull/16244))
- `[jest-runtime, @jest/transform]` Surface actionable `ERR_REQUIRE_ESM` error for files with untransformed ESM syntax instead of the generic "unexpected token" message ([#​16244](https://redirect.github.com/jestjs/jest/pull/16244))
- `[jest-runtime]` Support older test environments whose `moduleMocker` does not implement `clearMocksOnScope` ([#​16169](https://redirect.github.com/jestjs/jest/pull/16169))
- `[jest-runtime]` Apply `jest.unstable_mockModule` when the mocked file itself is `require()`d, not only when it is imported as a dependency ([#​16389](https://redirect.github.com/jestjs/jest/pull/16389))
- `[jest-runtime]` Apply `jest.unstable_mockModule` to statically imported `data:` URIs on Node 24.9+, matching dynamic `import()` ([#​16389](https://redirect.github.com/jestjs/jest/pull/16389))
- `[jest-runtime]` Run an async `jest.unstable_mockModule` factory once per module instead of twice, and fail the import instead of crashing the worker when the factory rejects ([#​16389](https://redirect.github.com/jestjs/jest/pull/16389))
- `[jest-runtime]` Hide a `require(esm)` module that failed to evaluate from `require.cache`, as Node does, instead of exposing a namespace with uninitialized bindings ([#​16389](https://redirect.github.com/jestjs/jest/pull/16389))
- `[jest-runtime]` Strip the byte-order mark when importing a JSON module, matching `require()` and Node ([#​16389](https://redirect.github.com/jestjs/jest/pull/16389))
- `[jest-runtime]` Throw `ERR_REQUIRE_ASYNC_MODULE` when `require(esm)` runs under an async-only custom resolver, instead of silently resolving with the default resolver ([#​16389](https://redirect.github.com/jestjs/jest/pull/16389))
- `[jest-runtime]` Parse imported JSON modules with the test realm's `JSON`, so their objects pass `instanceof Object` inside the test like `require()`d JSON does ([#​16389](https://redirect.github.com/jestjs/jest/pull/16389))
- `[jest-runtime]` Accept every `file:` URL string in the sandboxed `module.createRequire`, including one with a `localhost` authority, as Node does ([#​16389](https://redirect.github.com/jestjs/jest/pull/16389))
- `[jest-runtime]` Point at `{virtual: true}` when `jest.mock` or `jest.unstable_mockModule` is given a module that cannot be resolved ([#​16389](https://redirect.github.com/jestjs/jest/pull/16389))
- `[jest-reporters]` Fix coverage report table formatting in CI/GitHub Actions environments where `process.stdout.columns` is undefined by falling back to the `COLUMNS` env var or `80` columns in CI, preserving existing behaviour in other non-TTY environments ([#​16227](https://redirect.github.com/jestjs/jest/pull/16227))
- `[jest-runtime]` Support CJS-in-ESM exports via `"module.exports"` named exports ([#​16277](https://redirect.github.com/jestjs/jest/pull/16277))
- `[jest-snapshot]` Keep a skipped or failed test's hinted snapshots, instead of reporting them obsolete ([#​16348](https://redirect.github.com/jestjs/jest/pull/16348))
- `[jest-util]` Stop `globsToMatcher` reusing a cached matcher compiled with different picomatch options, and keep its `dot: true` default when `dot` is passed as `undefined` ([#​16381](https://redirect.github.com/jestjs/jest/pull/16381))
- `[pretty-format]` Move the `react-is` aliases into the `@jest` scope, so they cannot be shadowed by unrelated packages published under the alias names ([#​16333](https://redirect.github.com/jestjs/jest/pull/16333))
##### Chore & Maintenance
- `[docs]` Document the intentional divergences from Node's module system in the ECMAScript Modules page ([#​16368](https://redirect.github.com/jestjs/jest/pull/16368))
- `[docs]` Note deprecation of `react-test-renderer` in React Native tutorial and `pretty-format` README ([#​16294](https://redirect.github.com/jestjs/jest/pull/16294))
- `[docs]` Use `@testing-library/react-native` in the React Native tutorial instead of the deprecated `react-test-renderer` ([#​16318](https://redirect.github.com/jestjs/jest/pull/16318))
- `[babel-jest, @jest/transform]` Update `babel-plugin-istanbul` to v8 ([#​16049](https://redirect.github.com/jestjs/jest/pull/16049))
- `[jest-config, @jest/reporters, jest-runtime]` Update `glob` to v13 ([#​16397](https://redirect.github.com/jestjs/jest/pull/16397))
- `[jest-haste-map]` Refactor massive class into multiple files ([#​16180](https://redirect.github.com/jestjs/jest/pull/16180))
- `[jest-haste-map]` Drop `walker` dependency; replace hand-rolled directory recursion in the JS crawler and watcher startup with `fdir` ([#​16187](https://redirect.github.com/jestjs/jest/pull/16187))
- `[jest-haste-map]` Reuse cached metadata for files whose haste name is a known duplicate, instead of re-reading and re-parsing them on every startup ([#​16351](https://redirect.github.com/jestjs/jest/pull/16351))
- `[jest-haste-map]` Cache the watchman socket path and replace the `watchman --version` probe with `get-sockname`, so warm runs spawn no watchman processes ([#​16386](https://redirect.github.com/jestjs/jest/pull/16386))
- `[jest-resolve]` Store the per-directory package-type lookup in the cache it reads, so it actually memoizes ([#​16369](https://redirect.github.com/jestjs/jest/pull/16369))
- `[jest-resolve, jest-runtime]` Cut repeated work on the resolution hot path: hoist the platform-extension list to construction, memoize `isCoreModule` and the options cache-key serialization, skip mapper preparation when no `moduleNameMapper` is configured, run each mapper regex once, and stop re-parsing `NODE_OPTIONS` on every default-resolver call ([#​16371](https://redirect.github.com/jestjs/jest/pull/16371))
- `[jest-resolve]` Cut warm resolution cost to about a third: reuse one `unrs-resolver` factory per options shape instead of cloning per resolution, compose the factory cache key from per-array cached strings instead of serializing options, and stop constructing an `Error` for misses that `findNodeModule` swallows; add a `__benchmarks__` suite for the default resolver ([#​16373](https://redirect.github.com/jestjs/jest/pull/16373))
- `[jest-runner, @jest/source-map]` Replace `source-map-support` with an implementation in `@jest/source-map` ([#​16327](https://redirect.github.com/jestjs/jest/pull/16327))
- `[jest-snapshot]` Load babel, semver and synckit lazily, so requiring the package (which every test process does through `@jest/expect`) no longer loads \~200 modules that only writing inline snapshots needs ([#​16387](https://redirect.github.com/jestjs/jest/pull/16387))
- `[jest-runtime]` Reduce per-require overhead: skip module ID resolution when no mock can apply, answer core modules before probing for a manual mock, share one `require.cache` proxy across modules, and cache empty files ([#​16376](https://redirect.github.com/jestjs/jest/pull/16376))
- `[@jest/source-map]` Deprecate `getCallsite` in favour of `SourceMapSupport#getCallsite` ([#​16327](https://redirect.github.com/jestjs/jest/pull/16327))
- `[jest-runtime]` Avoid magical `null` value in ESM loader ([#​16160](https://redirect.github.com/jestjs/jest/pull/16160))
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- "before 9am on monday"
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/expo/entity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC42MS4zIiwidXBkYXRlZEluVmVyIjoiNDQuNjEuMyIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
- declare runtime dependencies imported by published packages ([#717](https://github.com/expo/entity/issues/717)) ([3c96f3b](https://github.com/expo/entity/commit/3c96f3b9ea2b097c979447354f0abe35ed5e8d57))
- add ID-based and field-based knex database loaders for use with locking modifiers ([#706](https://github.com/expo/entity/issues/706)) ([e87e2a3](https://github.com/expo/entity/commit/e87e2a3a28f4279f5911bfd0189964b94a2ced7f))
- declare runtime dependencies imported by published packages ([#717](https://github.com/expo/entity/issues/717)) ([3c96f3b](https://github.com/expo/entity/commit/3c96f3b9ea2b097c979447354f0abe35ed5e8d57))
- declare runtime dependencies imported by published packages ([#717](https://github.com/expo/entity/issues/717)) ([3c96f3b](https://github.com/expo/entity/commit/3c96f3b9ea2b097c979447354f0abe35ed5e8d57))
- add ID-based and field-based knex database loaders for use with locking modifiers ([#706](https://github.com/expo/entity/issues/706)) ([e87e2a3](https://github.com/expo/entity/commit/e87e2a3a28f4279f5911bfd0189964b94a2ced7f))
* Authorization-result-based version of the EnforcingKnexEntityLoader method by the same name.
* @returns entity result where uniqueFieldName equals fieldValue, or null if no entity matches the condition, where result error can be UnauthorizedError.
* @throws when multiple entities match the condition
* Load the first entity matching the conjunction of field equality operands and
* query modifiers.
@@ -88,7 +225,7 @@ export class EnforcingKnexEntityLoader<
* query modifiers.
*
* Typically this is used for complex queries that cannot be expressed through simpler
* convenience methods such as {@link loadManyByFieldEqualingAsync}.
* convenience methods such as {@link "@expo/entity"!EnforcingEntityLoader.loadManyByFieldEqualingAsync | EnforcingEntityLoader.loadManyByFieldEqualingAsync}.
*
* @throws EntityNotAuthorizedError if viewer is not authorized to view the entity
- declare runtime dependencies imported by published packages ([#717](https://github.com/expo/entity/issues/717)) ([3c96f3b](https://github.com/expo/entity/commit/3c96f3b9ea2b097c979447354f0abe35ed5e8d57))
- declare runtime dependencies imported by published packages ([#717](https://github.com/expo/entity/issues/717)) ([3c96f3b](https://github.com/expo/entity/commit/3c96f3b9ea2b097c979447354f0abe35ed5e8d57))
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.