mise-en-place

jdx/mise last check 666 releases today
Notes

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

Release notes
view on github
2026.10.23 · v2026.10.23: Dotfile groups can apply edits, INI merges, and fnox-stored dotfiles · today

Dotfile groups can now carry block, line and merge edits, merge entries work on INI files, and mode = "fnox" deploys files kept encrypted in fnox. mise secrets also no longer lets a project grant itself keys from your personal fnox config. The rest of the release adds compact-index version listing for gem sources such as GitHub Packages, plus fixes for uninstall, lockfiles, command wrappers, Windows and MSYS2.

Added

  • Edits inside dotfile groups. A [dotfile_groups.<name>.entries] table can now hold block, line and merge edits alongside whole-file entries. These edits apply only on machines that select the group in [bootstrap] dotfile_groups. Before, edits had to live under [dotfiles], which applies on every machine. Edit entries use the <path>/<id> key form, and a relative source starts at the group root. The edited file must be inside the group's target. Deselecting a group leaves the content its edits already wrote. #15131 (@jdx, @thernstig)

    [dotfile_groups.common]
    root = "common"
    mode = "copy"
    
    [dotfile_groups.common.entries]
    "~/.config/mise/conf.d/private.local.toml/defaults" = { source = "../templates/private.toml", merge = "missing", permissions = "0600" }
    
  • Dotfile merges into INI files. A merge entry can now set keys in INI files such as pip.conf, tox.ini and setup.cfg. Changed keys are replaced in place, new keys go into their section, and missing sections are added at the end of the file. Comments, other keys, indentation, CRLF line endings and a BOM are all kept. Targets ending in .ini are detected automatically. For any other file name, set format = "ini". Parsing follows Python's configparser, and a target that doesn't parse is reported and left unchanged. This change also fixes merges in any format whose target is a symlink to its own source: if the source fails to parse, mise now keeps the link instead of replacing it with a copy. #15135 (@jdx, @Mossop)

    [dotfiles]
    "~/.config/pip/pip.conf/shared" = { source = "pip/shared.conf", merge = true, format = "ini" }
    
  • mode = "fnox" for dotfiles containing secrets. This entry writes the file that fnox stores for the target path, so files like ~/.npmrc or ~/.kube/config stay out of your dotfiles repository. It requires fnox 1.44.0 or newer on PATH. Files are written with mode 0600 unless permissions says otherwise. mise dot edit runs fnox edit --file. mise dot diff never prints the content, and dry runs never call fnox. mise dot unapply removes the target only while it still matches what fnox stores, unless you pass --force. mise oci build skips these entries. One limitation: mise dot rollback journals the previous plaintext in the local state directory. Only UTF-8 text files are supported. #15134 (@jdx, @owpac)

    fnox set --file ~/.npmrc
    
    [dotfiles]
    "~/.npmrc" = { mode = "fnox" }
    
  • Gem sources without the JSON versions API. If a gem source returns 404 for api/v1/versions/<gem>.json, mise now lists versions from the source's compact index (info/<gem>), the same file Bundler uses. As a result, latest, version prefixes, mise outdated and mise upgrade work for gems from GitHub Packages (rubygems.pkg.github.com/<org>) and similar registries. GitHub Packages doesn't publish release dates, so minimum_release_age can't filter its versions. A 401 from GitHub Packages now comes with a hint about the read:packages token scope. #15122 (@waynehoover)

Fixed

  • mise uninstall ruby 3.4.1 no longer removes ruby@3.4.12 when 3.4.1 isn't installed. A version now matches only when it equals the query or continues it after ., - or +, the same way mise matches versions elsewhere. #15116 (@jdx, @Aqualon)
  • mise ls now shows lazy tools that haven't been installed as a dimmed (lazy) instead of a red (missing). A bare mise upgrade no longer lists them among the tools it resolves. mise ls --json still reports "installed": false, and mise ls --missing still includes them. #15114 (@jdx)
  • Installing a packageManager entry with a checksum (for example pnpm@11.7.0+sha512...) no longer forces every later install of that tool onto the npm backend. Installs that an earlier version already pinned recover on their next install. #15124 (@jdx, @foobear)
  • A command run through a [wrappers] entry now still goes through other wrappers. For example, node run from a wrapped pnpm now gets the node wrapper's args and env. A wrapper is skipped only for its own nested calls, and that skip is tracked in __MISE_ACTIVE_WRAPPERS. #15126 (@jdx)
  • Locked installs inside a dotfiles checkout that is linked into your global config, such as ~/.config/mise/conf.d/dotfiles -> ~/dotfiles, no longer fail with "No lockfile URL found". The checkout's mise.lock is now trusted as global config. A project mise.toml that symlinks to your global config still can't vouch for the project's lockfile. #15130 (@jdx, @soodoh)
  • When ~/.config/mise is a symlink into a dotfiles repository, mise lock --global writes npm and Python sidecars to locks/ again instead of .mise/locks/. Existing pointers are rewritten on the next lock. You can delete the old .mise/locks/ directory by hand. #15125 (@jdx)
  • When a backend (cargo, go, gem, pipx, ...) runs a program that isn't on PATH, the error now names it, for example `cargo` not found. Before, it only said "No such file or directory". #15119 (@jdx, @Mossop)
  • Under MSYS2, Git Bash and Cygwin, mise activate for bash, zsh and fish now exports MANPATH in POSIX form, so man can use it. Empty entries are kept so man still uses its default paths. #15117 (@jdx, @PTechoueyres-mic)
  • On Windows, mise self-update retries for about 6 seconds when antivirus briefly locks mise.exe. If replacing the binary fails after the old one has been moved aside, mise copies the new binary into place, so the install directory is never left without mise.exe. #15138 (@jdx)

Changed

  • mise dot status and mise dot sync no longer start one git process per tracked file. In one test with about 860 tracked files, a warm mise dot status dropped from about 7s to 1.4s. Output is unchanged. #15127 (@waynehoover)
  • The README has been rewritten. It now shows a full mise.toml example up front, an updated quickstart, a table of everyday commands, and a section on mise bootstrap. #15136 (@jdx)

Security

  • Projects can no longer grant themselves your personal fnox keys. A key defined in fnox's global config, or in a fnox.toml in or above $HOME, now counts as yours rather than the project's. If a task's secrets list or a {{ secrets.NAME }} reference names such a key, the task fails before any secret is resolved. The error names the file that defines the key. --secrets-all leaves these keys out, while mise run --secrets NAME and mise x --secrets NAME still pass them because you named them yourself. mise secrets ls and mise tasks validate report these grants as problems of kind personal. To give a key to the project, define it in the project's fnox.toml. This needs a fnox release that reports where each key is defined. With older fnox, behavior is unchanged. mise secrets is still experimental. #15133 (@jdx)

Full Changelog: https://github.com/jdx/mise/compare/v2026.10.22...v2026.10.23

💚 Sponsor mise

mise is built and maintained by @jdx, an open source developer at entire.io, the title sponsor of his open source work.

If mise saves you or your team time, please consider becoming an individual or company sponsor. Your support funds ongoing development and helps keep mise fast, free, and independent.