v2026.10.4
invoke-ai/InvokeAIv2026.10.4Oct 7, 2026by mise-en-dev
Upgrading?
AI Summary
This release introduces experimental task-scoped secrets backed by fnox, automatic global tool updates, and an experimental identity install layout. It also adds various backend improvements including dotfile merging, HTTP headers auth, and npm installs from git.
Key Highlights
- Experimental task-scoped secrets backed by fnox
- Automatic global tool updates via `auto_update` setting
- Experimental opt-in identity install layout
- Dotfile `merge` entries to preserve app-added keys
- Headers authentication for the `http:` backend
New Features
- Task-scoped secrets with `secrets = [...]`
- Automatic updates for global tools
- Identity install layout with `install_layout = "identity"`
- Dotfile merge entries for TOML/YAML
- npm packages from git URLs
- Settings write targets for separate conf.d files
Full Release Notes
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://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://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://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://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://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://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://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://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://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://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://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://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://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://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://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://github.com/jdx/mise/pull/14044)
```sh
mise use 'npm:github:owner/repo@v1.2.0'
```
- **`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://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://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 (`true`) keeps the current pruning behavior. [#13980](https://github.com/jdx/mise/pull/13980)
- **`mise dot notify`** sends a test desktop notification, which also triggers the macOS permission prompt. `mise doctor` and `mise dot status` now show whether notifications can be delivered. [#14009](https://github.com/jdx/mise/pull/14009)
## Changed
- **mise's own auto-update settings moved under `self_update.*`.** `auto_update` is now `self_update.auto` (`MISE_SELF_UPDATE_AUTO`), and `auto_update_check_duration` is now `self_update.check_duration` (`MISE_SELF_UPDATE_CHECK_DURATION`). The old names keep working. The new key wins when both are set. Deprecation warnings start in 2027.4.0. Older mise versions ignore a settings file that has unknown `self_update` keys, so keep the old spelling if a config has to work with both. [#14038](https://github.com/jdx/mise/pull/14038)
- `mise prune`, `mise unuse --prune`, `mise ls --prunable` and deferred pruning after an upgrade now keep any version a running process was started from, on Linux, macOS and Windows. They say which process kept it. [#14020](https://github.com/jdx/mise/pull/14020)
- `pypi:`/`pipx:` tools installed with uv are now built on mise's Python when mise manages one. Previously uv could use its own downloaded interpreter, which broke CI caches that only restore the mise data dir. A package whose `requires-python` excludes mise's Python now fails; to override, pass `--python` in `uvx_args`. [#14024](https://github.com/jdx/mise/pull/14024)
- With `python.uv_venv_auto`, `mise install` now creates the project venv with mise's Python instead of whatever uv found. [#13981](https://github.com/jdx/mise/pull/13981) by @halms
- Inherited secrets: when a parent mise marks variables as secrets in `__MISE_SECRET_KEYS`, a nested mise now does the following [#13966](https://github.com/jdx/mise/pull/13966):
- redacts them from logs
- hides them from templates, `get_env()` and `exec()`
- disables the env cache
- keeps them out of `__MISE_DIFF`, other tasks and pitchfork
`mise x` and shims still pass them through.
## Fixed
- **Install state**
- A failed tool-level `postinstall` hook no longer leaves its version listed as installed or selectable. The next install retries it. [#14037](https://github.com/jdx/mise/pull/14037)
- Incomplete-install markers moved from the cache to `$MISE_STATE_DIR`, so `mise cache clear` no longer makes a half-installed version look installed. Existing markers are migrated. [#14051](https://github.com/jdx/mise/pull/14051)
- **Lockfiles and backends**
- `mise install --locked` now works for `dotnet:` tools. [#13971](https://github.com/jdx/mise/pull/13971) by @james-newell-forge
- `mise lock` for `pypi:` tools on registries with a `<root>/pypi/{}/json` template, such as Artifactory, now uses `<root>/simple/`. [#14007](https://github.com/jdx/mise/pull/14007) by @deiga
- Parallel `cargo:` installs that fall back to `cargo install` no longer corrupt the shared rustup toolchain. [#14042](https://github.com/jdx/mise/pull/14042)
- `mise upgrade --bump` and `mise outdated --bump` no longer rewrite vendor-only requests like `java = "temurin"` to a bare version from another vendor. [#14031](https://github.com/jdx/mise/pull/14031)
- A registry move within the same backend kind, such as `vfox:mise-plugins/*` to `vfox:jdx/*`, no longer triggers the backend-switch warning or appears in `mise backends switch` or `mise doctor`. [#14032](https://github.com/jdx/mise/pull/14032)
- `mise doctor` only warns about a backend mismatch when the registry's backend actually serves the installed version. It now suggests `mise backends switch`. [#14005](https://github.com/jdx/mise/pull/14005)
- `mise uninstall --dry-run` lists each version once. [#13992](https://github.com/jdx/mise/pull/13992)
- **Network**
- Downloads are retried when an HTTP/2 stream reset breaks reading the response body. [#14049](https://github.com/jdx/mise/pull/14049)
- mise no longer retries a 429 whose `Retry-After` is longer than the backoff. [#14027](https://github.com/jdx/mise/pull/14027)
- Fewer duplicate requests: concurrent callers share one fetch of a cached GitHub release, and packslip release lists are read once per command. [#13990](https://github.com/jdx/mise/pull/13990), [#13991](https://github.com/jdx/mise/pull/13991)
- `mise oci push` uploads layers larger than 64 MiB in a single streamed PATCH. GHCR previously rejected these with `416`. [#14017](https://github.com/jdx/mise/pull/14017)
- **GitHub attestations**
- mise warns when some attestations were skipped because the Sigstore or GitHub TUF trust root couldn't be reached, even if verification passed on the others. [#14036](https://github.com/jdx/mise/pull/14036)
- Attestations that failed partway are now logged at debug level. [#14035](https://github.com/jdx/mise/pull/14035)
- **Config and bootstrap**
- A project's `ignored_config_paths` no longer hides your global config when `~/.config/mise` is a symlink into that project. A global config can no longer be ignored only through its symlink target. [#14006](https://github.com/jdx/mise/pull/14006)
- `mise bootstrap` no longer fails with `another history operation is running` when it has no file history to record. Parallel CI jobs that share a state dir no longer block each other. [#14029](https://github.com/jdx/mise/pull/14029)
- **Dotfiles**
- Conflicting declaration errors now explain when a source file is missing. [#13973](https://github.com/jdx/mise/pull/13973) by @himkt
- Group entries no longer go through legacy link discovery. [#14023](https://github.com/jdx/mise/pull/14023)
- **Secrets, MCP and tasks**
- Secrets are fully redacted when redaction values overlap. [#13962](https://github.com/jdx/mise/pull/13962)
- The MCP `run_task` tool rejects task names that start with a dash. [#13961](https://github.com/jdx/mise/pull/13961)
- The `mise://tasks` MCP resource now lists tasks from monorepo subprojects. [#14053](https://github.com/jdx/mise/pull/14053)
- Changing a Ruby version file that a Gemfile references no longer prints a `watch_file hook has neither run nor task set` warning. [#13985](https://github.com/jdx/mise/pull/13985) by @DahanItamar
## Documentation
- `url_replacements` docs now include a package proxy example. [#14050](https://github.com/jdx/mise/pull/14050)
## Breaking Changes
- `mise secrets` is now a built-in command. If you have a task named `secrets`, run it with `mise run secrets`. [#13967](https://github.com/jdx/mise/pull/13967)
## New Contributors
* @james-newell-forge made their first contribution in [#13971](https://github.com/jdx/mise/pull/13971)
* @deiga made their first contribution in [#14007](https://github.com/jdx/mise/pull/14007)
* @DahanItamar made their first contribution in [#14034](https://github.com/jdx/mise/pull/14034)
**Full Changelog**: https://github.com/jdx/mise/compare/vfox-v2026.10.3...v2026.10.4
## 💚 Sponsor mise
mise is built and maintained by [@jdx](https://github.com/jdx), an open source developer at [**entire.io**](https://entire.io/), the title sponsor of his open source work.
If mise saves you or your team time, please consider becoming an [individual or company sponsor](https://jdx.dev/sponsors.html). Your support funds ongoing development and helps keep mise fast, free, and independent.
Related Repositories
openclaw/openclaw★ 392,690
The AI that really does things. Any OS. Any Platform. The lobster way. 🦞
nilbuild/developer-roadmap★ 370,064
Interactive roadmaps, guides and other educational content to help developers grow in their careers.
morluto/rea★ 357,493
Reverse engineer anything with agents, from app behavior down to native binaries.
anomalyco/opencode★ 219,655
The open source coding agent.
n8n-io/n8n★ 208,248
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.