MISE(1)

πŸ“¦
version 2026.10.25 Β· 4 versions
, in arch rolling

πŸ¦‹ MISE(1) πŸ¦‹

okay bestie, welcome to the MISE(1) page, General Commands Manual edition β€” and honestly? It's giving β€œyour dev environment finally has its life together.” πŸ’…

✨ NAME ✨

mise - Dev tools, env vars, and tasks in one CLI

🌸 SYNOPSIS 🌸

mise [OPTIONS] [<TASK>] [<TASK_ARGS>] ... [<TASK_ARGS_LAST>] ...
[COMMAND]

πŸ’– DESCRIPTION πŸ’–

mise installs the development tools your projects need, sets their environment variables, and runs their tasks. No cap, it's the whole package. 🫢

You declare tools, environment variables, and tasks in mise.toml. mise use <TOOL> installs a tool and adds it to the project's mise.toml, mise install installs everything the config requests, and mise run <TASK> runs a task. Docs: https://mise.jdx.dev

πŸ”₯ OPTIONS πŸ”₯

  • -c, --continue-on-error β€” Keep running tasks even if one of them fails. The show must go on. 😭
  • -C, --cd <DIR> β€” Run as if mise were started in DIR. Like β€œpretend we're in this folder,” but make it real.
  • -E, --env <ENV> β€” Load the mise.<ENV>.toml config files (same as MISE_ENV). Repeat the flag or separate names with commas to load several environments. Multi-env slay. ✨
  • -f, --force β€” Force the operation. Respectfully, it means business.
  • -j, --jobs <JOBS> β€” How many jobs to run in parallel; defaults to the jobs setting. Values below 1 are treated as 1. Environment: MISE_JOBS.
  • -n, --dry-run β€” Dry run, don't actually do anything. Rehearsal mode, basically. πŸŽ€
  • -P, --profile <PROFILE> β€” Set the profile (environment).
  • -q, --quiet β€” Suppress non-error messages. Environment: MISE_QUIET. Shhh, only errors get to speak. 🀫
  • -s, --shell <SHELL> β€” no description in the source here, bestie, just the flag itself. The mystery is the moment. πŸ’€
  • -t, --tool <TOOL@VERSION> β€” Tools to load in addition to those in mise.toml, such as node@24 python@3.13.
  • -v, --verbose β€” Show extra output (use -vv for even more). Let it yap. πŸ—£οΈ
  • -V, --version β€” no description in the source here, just the flag itself.
  • -y, --yes β€” Answer yes to all confirmation prompts. Consent to the whole vibe, automatically. βœ…
  • --debug β€” Set the log level to debug.
  • --log-level <LEVEL> β€” no description in the source here, just the flag itself.
  • --no-config β€” Do not load any config files. Same as MISE_NO_CONFIG=1.
  • --no-env β€” Do not load environment variables from config files. Same as MISE_NO_ENV=1.
  • --no-hooks β€” Do not run hooks from config files. Same as MISE_NO_HOOKS=1.
  • --no-timings β€” Hide the elapsed time printed after each task completes. Set MISE_TASK_TIMINGS=0 to hide it by default.
  • --output <OUTPUT> β€” How task output is displayed when running a task (same as mise run --output).
  • --raw β€” Connect tasks and install commands directly to the terminal. Commands then run one at a time. Same as MISE_RAW=1 or the raw setting.
  • --locked β€” Require download URLs from the lockfile when installing. Installing fails when the lockfile has no pre-resolved URL for a tool on the current platform, so mise does not call the GitHub or aqua registry APIs to find one. Same as MISE_LOCKED=1 or the locked setting.
  • --silent β€” Suppress all task output and mise non-error messages. Full ghost mode. πŸ‘»
  • --timings β€” Show the elapsed time after each task completes. Set MISE_TASK_TIMINGS=1 to show it by default.
  • --trace β€” Set the log level to trace.
  • -h, --help β€” Print help. The classic β€œwhat does anything mean” button. 🫢

🌈 ARGUMENTS 🌈

  • <TASK> β€” Task to run. Shorthand for mise run <TASK>.
  • <TASK_ARGS> β€” Task arguments.

πŸ‘‘ COMMANDS πŸ‘‘

  • activate β€” Print the script to activate mise in an interactive shell.
  • tool-alias β€” Manage tool backend and version aliases. Aliases: alias, aliases.
    • tool-alias get β€” Show the version a tool's version alias stands for.
    • tool-alias ls β€” List tool version aliases. Aliases: list.
    • tool-alias set β€” Set a backend alias or a version alias in the global config. Aliases: add, create.
    • tool-alias unset β€” Remove a backend alias or a version alias from the global config. Aliases: rm, remove, delete, del.
  • backends β€” Manage backends. Aliases: b, backend, backend-list.
    • backends ls β€” List built-in backends. Aliases: list.
    • backends switch β€” Switch tools to the backend the registry now installs them from.
  • bin-paths β€” List the bin directories of the active tools.
  • bootstrap β€” Set up this machine from your mise config. Aliases: bs.
    • bootstrap accounts β€” Manage Linux users and groups.
      • bootstrap accounts apply β€” Create, update, or remove the configured Linux users and groups.
      • bootstrap accounts status β€” Show the state of the configured Linux users and groups.
    • bootstrap compose β€” Manage Docker Compose projects from [bootstrap.compose].
      • bootstrap compose apply β€” Apply Docker Compose projects from [bootstrap.compose].
      • bootstrap compose status β€” Show the state of Docker Compose projects from [bootstrap.compose].
    • bootstrap files β€” Manage system files and directories declared in [bootstrap].
      • bootstrap files apply β€” Create, update, or remove the configured system files and directories.
      • bootstrap files status β€” Show the state of the configured system files and directories.
    • bootstrap firewall β€” Manage the Linux host firewall from [bootstrap.linux.firewall].
      • bootstrap firewall apply β€” Apply the firewall from [bootstrap.linux.firewall].
      • bootstrap firewall status β€” Show the state of the firewall from [bootstrap.linux.firewall].
    • bootstrap linux β€” Manage systemd user units from [bootstrap.linux.systemd.units].
      • bootstrap linux systemd-units β€” Manage systemd user units from [bootstrap.linux.systemd.units]. Aliases: systemd.
        • bootstrap linux systemd-units apply β€” Install and start the configured systemd user units.
        • bootstrap linux systemd-units status β€” Show the state of the configured systemd user units.
    • bootstrap macos β€” Manage macOS preferences and LaunchAgents from [bootstrap.macos].
      • bootstrap macos defaults β€” Manage macOS preferences such as Dock, Finder, and keyboard settings.
        • bootstrap macos defaults apply β€” Write the configured macOS preferences.
        • bootstrap macos defaults status β€” Show the state of the configured macOS preferences.
      • bootstrap macos launchd-agents β€” Manage macOS LaunchAgents from [bootstrap.macos.launchd.agents]. Aliases: launchd.
        • bootstrap macos launchd-agents apply β€” Install and load LaunchAgents from [bootstrap.macos.launchd.agents].
        • bootstrap macos launchd-agents status β€” Show the state of the configured LaunchAgents.
    • bootstrap mise-shell-activate β€” Manage mise shell activation from [bootstrap.mise_shell_activate]. Aliases: shell.
      • bootstrap mise-shell-activate apply β€” Write mise activation into the configured shell startup files.
      • bootstrap mise-shell-activate status β€” Show the state of the configured shell activation.
    • bootstrap packages β€” Manage packages from [bootstrap.packages].
      • bootstrap packages apply β€” Install or remove packages to match [bootstrap.packages]. Aliases: i, install.
      • bootstrap packages brew β€” Manage Homebrew tap URLs in [bootstrap.brew.taps].
        • bootstrap packages brew tap β€” Add a Homebrew tap URL to the global [bootstrap.brew.taps].
        • bootstrap packages brew untap β€” Remove Homebrew tap URLs from [bootstrap.brew.taps]. Aliases: remove, rm.
      • bootstrap packages export β€” Print the configured nix: packages as a NixOS module.
      • bootstrap packages import β€” Record installed Homebrew formulae in [bootstrap.packages].
      • bootstrap packages prune β€” Uninstall packages that no config declares.
      • bootstrap packages status β€” Show the state of packages from [bootstrap.packages]. Aliases: ls, list.
      • bootstrap packages upgrade β€” Upgrade installed packages from [bootstrap.packages]. Aliases: up.
      • bootstrap packages use β€” Add packages to [bootstrap.packages] and install them. Aliases: u.
      • bootstrap packages where β€” Print the opt path of an installed Homebrew formula.
    • bootstrap plan β€” Show what applying bootstrap resources would change.
    • bootstrap plugins β€” Manage package manager plugins declared in [bootstrap.plugins].
      • bootstrap plugins apply β€” Install package manager plugins declared in [bootstrap.plugins].
      • bootstrap plugins status β€” Show whether declared package manager plugins are installed.
    • bootstrap remote β€” Bootstrap one or more machines over SSH.
    • bootstrap repos β€” Manage Git repositories from [bootstrap.repos].
      • bootstrap repos apply β€” Clone missing Git repositories and check out configured refs.
      • bootstrap repos exec β€” Run a command in each configured Git repository.
      • bootstrap repos status β€” Show the state of Git repositories from [bootstrap.repos].
      • bootstrap repos update β€” Clone missing Git repositories and fast-forward the rest.
    • bootstrap secrets β€” Inspect bootstrap secret inputs without revealing their values.
      • bootstrap secrets status β€” Show whether declared bootstrap secret inputs are available.
    • bootstrap services β€” Manage services from [bootstrap.services].
      • bootstrap services apply β€” Apply the service state declared in [bootstrap.services].
      • bootstrap services remove β€” Uninstall a user-scope service.
      • bootstrap services status β€” Show the state of services from [bootstrap.services].
    • bootstrap status β€” Show the state of every configured bootstrap part. Aliases: ls.
    • bootstrap unapply β€” Remove what a config environment's bootstrap sections created.
    • bootstrap user β€” Manage your login shell from [bootstrap.user].
      • bootstrap user apply β€” Set your login shell from [bootstrap.user].
      • bootstrap user status β€” Show whether your login shell matches [bootstrap.user].
  • cache β€” Manage the mise cache.
    • cache clear β€” Delete cached data. Aliases: c, clean.
    • cache path β€” Print the cache directory path. Aliases: dir.
    • cache prune β€” Remove cache files that have not been accessed recently. Aliases: p.
    • cache task β€” [experimental] Inspect artifact cache entries for a task.
  • completion β€” Generate shell completions. Aliases: complete, completions.
  • config β€” Manage config files. Aliases: cfg, toml.
    • config explain β€” Describe each key in a mise TOML file.
    • config get β€” Print a value from one mise TOML file.
    • config ls β€” List config files currently in use, from lowest to highest precedence. Aliases: list.
  • config set β€” sets a value in one mise TOML file ✨
  • deactivate β€” prints the script that turns mise off in your current shell session, no cap
  • daemons β€” [experimental] manages project daemons with pitchfork 🧚
    • Aliases: daemon
  • daemons providers β€” [experimental] manages shared servers straight from the global [daemon_providers] 🫢
  • daemons providers ls β€” [experimental] lists those shared servers πŸ’…
  • daemons providers start β€” [experimental] starts the shared servers up
  • daemons providers stop β€” [experimental] stops the shared servers (and yes, the data is kept, breathe)
  • daemons providers restart β€” [experimental] restarts the shared servers with whatever config they currently have πŸ”
  • daemons start β€” [experimental] starts project daemons plus the daemons they depend on, the whole friend group
  • daemons register β€” [experimental] registers project daemons so they can start on demand ✨
  • daemons stop β€” [experimental] stops project daemons
  • daemons restart β€” [experimental] restarts project daemons
  • daemons ls β€” [experimental] lists project daemons
    • Aliases: list
  • daemons urls β€” [experimental] shows each daemon's URL and port πŸ”—
  • daemons logs β€” [experimental] shows the output of project daemons
  • daemons status β€” [experimental] shows the status of project daemons
  • daemons tui β€” [experimental] opens the pitchfork dashboard, main character energy πŸ–₯️
  • daemons prune β€” [experimental] removes daemon state left behind by deleted projects 🧹
  • dotfiles β€” deploys, tracks, and syncs your dotfiles πŸŽ€
    • Aliases: dot
  • dotfiles add β€” starts deploying a file, or copies its edits back to the source
  • dotfiles apply β€” links, copies, and renders [dotfiles] entries into place ✨
  • dotfiles capture β€” runs a command and saves tracked files before and after it
  • dotfiles conflicts β€” compares both sides of a sync conflict, so you can see who did what 😭
  • dotfiles diff β€” shows what mise dot apply would change
  • dotfiles edit β€” opens a dotfile's source in your editor πŸ“
  • dotfiles exclude β€” never saves paths matching a glob, boundaries bestie
  • dotfiles history β€” browses saved versions of your tracked files πŸ•°οΈ
  • dotfiles history describe β€” sets the description of a checkpoint
  • dotfiles history diff β€” compares checkpoints, or compares your files against one
  • dotfiles history ls β€” lists checkpoints, newest first
    • Aliases: list
  • dotfiles history purge β€” erases a path's saved versions from history πŸ’€
  • dotfiles history show β€” shows a checkpoint: its trigger, changes, and operation journal
  • dotfiles include β€” stops excluding paths matching a glob (undoes your exclude, iconique)
  • dotfiles notify β€” sends a test desktop notification πŸ””
  • dotfiles origin β€” shows, connects, or disconnects the origin repository
  • dotfiles origin set β€” connects an origin repository
  • dotfiles paths β€” lists tracked paths and how they're saved
  • dotfiles pull β€” writes fetched changes from other machines into your tracked files 🫢
  • dotfiles recover β€” recovers an interrupted dotfile operation, we love a comeback
  • dotfiles rollback β€” returns files to the version a checkpoint holds βͺ
  • dotfiles save β€” saves a checkpoint of the tracked files, right now, periodt
  • dotfiles status β€” shows the state of your dotfiles and their history
    • Aliases: ls
  • dotfiles sync β€” pushes saved checkpoints and fetches incoming changes πŸ”„
  • dotfiles track β€” tracks a file or directory in place
  • dotfiles unapply β€” removes files that mise dot apply deployed
  • dotfiles undo β€” reverses the tracked-file changes from an operation ↩️
  • dotfiles untrack β€” stops tracking a file or directory
  • dotfiles watch β€” saves tracked files as they change πŸ‘€
  • doctor β€” checks your mise setup for problems 🩺
    • Aliases: dr
  • doctor path β€” prints the directories mise adds to PATH
    • Aliases: paths
  • doctor project β€” runs the project's diagnostic checks
  • en β€” starts a subshell with mise's tools and environment 🐚
  • env β€” prints the environment for the current configuration
    • Aliases: e
  • exec β€” runs a command with mise's tools and environment
    • Aliases: x
  • fmt β€” formats mise TOML configuration πŸ’…
  • generate β€” generates project files like CI workflows, git hooks, and scripts
    • Aliases: gen, g
  • generate config β€” generates a mise.toml file
  • generate devcontainer β€” generates a devcontainer configuration that installs mise and the project's tools πŸ“¦
  • generate git-pre-commit β€” generates a git hook that runs a mise task
    • Aliases: pre-commit
  • generate github-action β€” generates a GitHub Actions workflow that runs a mise task βš™οΈ
  • generate install-script β€” generates a script that downloads and runs a pinned mise
  • generate task-docs β€” generates Markdown documentation for project tasks πŸ“„
  • generate task-stubs β€” generates scripts that run mise tasks
  • generate tool-stub β€” generates or updates a tool stub
  • implode β€” removes the mise CLI and all related data πŸ’₯ (yes, all of it, so dramatic)
  • edit β€” edits mise.toml interactively ✏️
  • install β€” installs the tools in your config, or specific tool versions
    • Aliases: i
  • install-into β€” installs a tool version into a directory outside mise
  • installs β€” [experimental] inspects and chooses identity-layout installations
  • installs ls β€” lists the installations of the identity install layout
    • Aliases: list
  • installs migrate β€” reinstalls legacy installations into the identity install layout
  • installs select β€” chooses which installation mise uses when no lockfile pins one 🎯
  • latest β€” prints the latest version that matches a version request
  • link β€” symlinks a tool version into mise
    • Aliases: ln
  • lock β€” creates or refreshes lockfile versions, checksums, and download URLs πŸ”
  • ls β€” lists installed and active tool versions
    • Aliases: list
  • ls-remote β€” lists tool versions available to install
    • Aliases: list-all, list-remote
  • lsp β€” runs the language server for mise config files over stdin/stdout
  • mcp β€” runs the Model Context Protocol server over stdin/stdout πŸ€–
  • oci β€” [experimental] builds, pushes, and runs OCI images of a project's tools
  • oci build β€” [experimental] builds an OCI image from the current mise.toml
  • oci push β€” [experimental] builds an OCI image and pushes it to a registry πŸš€
  • oci run β€” [experimental] builds the project's image and runs a command inside it
  • packslip β€” inspects and resets the signers mise has pinned for packslip tools
  • packslip forget β€” forgets a project's pinned signer so the next accepted release sets it
  • packslip pins β€” lists the signer mise has pinned for each packslip project πŸ”
    • Aliases: list
  • outdated β€” shows outdated tool versions πŸ‘΅
  • patrons β€” shows the individuals supporting mise as Patron-tier members πŸ’–
  • plugins β€” manages plugins
    • Aliases: p, plugin, plugin-list
  • plugins install β€” installs plugins from a configured source, Git URL, or archive
    • Aliases: i, a, add
  • plugins link β€” links a local plugin directory into mise for development
    • Aliases: ln
  • plugins ls β€” lists installed plugins
    • Aliases: list
  • plugins ls-remote β€” lists registry tools that have an asdf or vfox plugin backend
    • Aliases: list-remote, list-all
  • plugins uninstall β€” removes an installed plugin
    • Aliases: remove, rm
  • plugins update β€” updates installed plugins
    • Aliases: up, upgrade
  • deps β€” [experimental] manages project dependencies
    • Aliases: dep, prepare
  • deps add β€” adds packages to the project's dependencies βž•
  • deps install β€” installs project dependencies
  • deps remove β€” removes packages from the project's dependencies βž–
  • prune β€” deletes tool versions that nothing uses 🧹
  • registry β€” lists registry shorthand names and their backends
  • reshim β€” creates shims for executables provided by installed tools
  • run β€” runs tasks and their dependencies πŸƒβ€β™€οΈ
    • Aliases: r
  • search β€” searches for available tools πŸ”
  • secrets β€” [experimental] inspects the project's secrets source 🀫
  • secrets ls β€” [experimental] lists secret names from the project's secrets source
    • Aliases: list
  • self-update β€” updates mise itself ✨
  • set β€” sets, shows, or lists environment variables in mise.toml
    • Aliases: ev, env-vars
  • settings β€” manages settings βš™οΈ
  • settings add β€” appends a value to an array setting
  • settings get β€” shows the effective value of a setting
  • settings ls β€” lists configured settings and their sources
    • Aliases: list
  • settings set β€” sets a setting
    • Aliases: create
  • settings unset β€” removes a setting from the global or project config
    • Aliases: rm, remove, delete, del
  • shell β€” sets a tool version for the current shell session 🐚
    • Aliases: sh
  • ssh β€” opens an SSH session, optionally borrowing read-only GitHub access πŸ”‘
  • shell-alias β€” manages shell aliases
  • shell-alias get β€” shows the command for a shell alias
  • shell-alias ls β€” lists shell aliases
    • Aliases: list
  • shell-alias set β€” sets a shell alias in the global config
    • Aliases: add, create
  • shell-alias unset β€” removes a shell alias from the global config
    • Aliases: rm, remove, delete, del
  • skills β€” lists and links the agent skills that active tools ship 🧠
    • Aliases: skill
  • skills ls β€” lists the skills the active tools declare
    • Aliases: list
  • skills sync β€” links the active tools' skills where an agent looks for them
  • sponsors β€” shows the companies sponsoring mise and the jdx.dev open source tools 🫢
  • sync β€” uses tool versions installed by other version managers
  • sync node β€” symlinks node versions installed by nvm, nodenv, or Homebrew into mise
  • sync python β€” symlinks python versions installed by pyenv or uv into mise 🐍
  • sync ruby β€” symlinks ruby versions installed by Homebrew into mise πŸ’Ž
  • tasks β€” manages tasks
    • Aliases: t, task
  • tasks add β€” adds a task
  • tasks deps β€” shows the dependency tree of tasks 🌳
  • tasks edit β€” opens a task in your editor
  • tasks graph β€” shows the monorepo project graph πŸ“Š
  • tasks info β€” shows a task's definition
  • tasks ls β€” lists available tasks

tasks rm

Removes tasks for you 🧹

Aliases: remove

tasks set

Changes the fields of an existing TOML task ✏️

tasks validate

Checks your task definitions for errors β€” the vibe check for your tasks πŸ”

test-tool

Tests that a tool actually installs and runs πŸ§ͺ (yes bestie, a real end-to-end test)

token

Shows you which Git provider token mise is using πŸ”‘

token forgejo

Shows the Forgejo token mise uses for a host

token github

Shows the GitHub token mise uses for a host

token gitlab

Shows the GitLab token mise uses for a host

tool

Shows information about a tool πŸ‘€

tool-stub

Runs a tool stub file

trust

Marks a config file as trusted 🫢

uninstall

Removes installed tool versions πŸ—‘οΈ

unset

Removes environment variables from mise.toml

untrust

Removes explicit trust for a config πŸ™…β€β™€οΈ

unuse

Removes tool requests from config files and prunes the ignored/unused installations 🧼

Aliases: rm, remove

upgrade

Upgrades your outdated tools ⬆️

Aliases: up

use

Installs a tool and adds it to your configuration ✨

Aliases: u

vars

Lists, sets, and asks for config vars πŸ—‚οΈ

vars ls

Lists every var, along with the file it comes from

Aliases: list

vars prompt

Asks for the prompt vars that have no saved answer yet, or sets answers directly

vars unset

Forgets saved answers so they get asked for again πŸ™ˆ

Aliases: rm, remove

version

Shows the version of mise

Aliases: v

watch

Runs tasks and reruns them whenever files change πŸ‘οΈ

Aliases: w

where

Shows the install directory of a tool version πŸ“

which

Shows the path a tool's executable resolves to


✨ MISE ACTIVATE ✨

Prints the script that activates mise in an interactive shell πŸšπŸ’–

You evaluate this command's output using the syntax for your shell β€” running it on its own just prints the script, it doesn't do anything. Activation is the thing that updates your tools and environment variables as the shell changes directories. So yeah, it's kind of the main character of the whole setup.

Add the matching example below once to your interactive startup file:

  • ~/.bashrc for Bash
  • ~/.zshrc for Zsh
  • ~/.config/fish/config.fish for Fish
  • $PROFILE for PowerShell

For Nushell, Elvish and other shells, see https://mise.jdx.dev/shell-setup.html 🌈

The mise executable has to be on PATH before that line runs. If it isn't, use its absolute path instead, for example eval "$(~/.local/bin/mise activate zsh)".

Use mise exec -- command for scripts and CI that don't need interactive hooks. The status.* settings control the messages mise prints when you change directories.

Usage: mise activate [OPTIONS] [<SHELL_TYPE>]

πŸ’… Options

  • -q, --quiet β€” suppresses non-error messages from the hook that runs at each prompt
  • -s, --shell <SHELL> β€” the shell type to generate the script for
  • --no-hook-env β€” don't run hook-env automatically

Use this one for debugging: after eval "$(mise activate zsh --no-hook-env)", run mise hook-env yourself to print the shell code it would evaluate, or mise hook-env --trace if you want more detail πŸ”

  • --shims β€” puts the shims directory on PATH instead of updating PATH at each prompt

Roughly equivalent to:

PATH="$HOME/.local/share/mise/shims:$PATH"

Shims don't support every feature of mise activate; see https://mise.jdx.dev/dev-tools/shims.html#shims-vs-path

  • --status β€” shows a mise: <TOOL>@<VERSION> message when you change directories
  • -h, --help β€” prints help

πŸŽ€ Arguments

  • <SHELL_TYPE> β€” the shell type to generate the script for

Defaults to the shell named by MISE_SHELL or SHELL. mise reports an error when neither of those names a supported shell β€” which is exactly what happens in PowerShell and cmd on Windows, jsyk πŸ™ƒ

🌸 Examples

Activate mise in Bash

eval "$(mise activate bash)"

Activate mise in Zsh

eval "$(mise activate zsh)"

Activate mise in Fish

mise activate fish | source

Activate mise in Xonsh

execx($(mise activate xonsh))

Activate mise in PowerShell

(&mise activate pwsh) | Out-String | Invoke-Expression

πŸ¦‹ MISE TOOL-ALIAS πŸ¦‹

Manages tool backend aliases and version aliases 🏷️

A backend alias makes a tool name install from another backend, like [tool_alias] ripgrep = "aqua:BurntSushi/ripgrep". A version alias gives a name to a version request β€” [tool_alias.node.versions] project = "20" means you can just write node@project. Iconic, honestly.

With no subcommand, it lists version aliases (same as mise tool-alias ls; the flags below get passed along to it). See https://mise.jdx.dev/dev-tools/aliases.html

Usage: mise tool-alias [OPTIONS] [COMMAND]

Options

  • -p, --tool <TOOL> β€” filter aliases by tool
  • --no-header β€” don't print the table header
  • -h, --help β€” prints help

πŸ’œ MISE TOOL-ALIAS GET

Shows the version that a tool's version alias stands for

It reads [tool_alias.TOOL.versions] from every loaded config file, plus the aliases the tool's backend provides (like node's lts-* aliases). It prints the stored request, which might itself still be a prefix πŸ‘€

Usage: mise tool-alias get [OPTIONS] <TOOL> <ALIAS>

Options

  • -h, --help β€” prints help

Arguments

  • <TOOL> β€” the tool to show the alias for
  • <ALIAS> β€” the alias to show

Examples

Show the version node's lts alias stands for

mise tool-alias get node lts

Output:

26

Read back an alias you set

mise tool-alias set node project 20
mise tool-alias get node project

Output:

20

🧚 MISE TOOL-ALIAS LS

Lists tool version aliases

It lists version aliases from [tool_alias.<tool>.versions] in any loaded config file, plus the aliases that tool backends provide β€” like node's lts-* names or an asdf plugin's bin/list-aliases. For example:

[tool_alias.node.versions]
project = "20"

Backend aliases ([tool_alias] tool = "backend") are not listed here; run mise tool <TOOL> to see the backend a tool uses.

Usage: mise tool-alias ls [OPTIONS] [<TOOL>]

Options

  • --no-header β€” don't print the table header
  • -h, --help β€” prints help

Arguments

  • <TOOL> β€” only show aliases for this tool

Examples

List node's version aliases

mise tool-alias ls node
tool  alias      version
node  lts        26
node  lts-jod    22
node  project    20

⭐ MISE TOOL-ALIAS SET

Sets a backend alias or a version alias in the global config

mise tool-alias set TOOL BACKEND makes TOOL install from BACKEND, written out as [tool_alias] TOOL = "BACKEND". And mise tool-alias set TOOL ALIAS VERSION makes TOOL@ALIAS mean VERSION, written under [tool_alias.TOOL.versions].

It writes the global config (~/.config/mise/config.toml by default). If you want to share aliases with the whole project, add them to a project's mise.toml instead 🫢

Usage: mise tool-alias set [OPTIONS] <TOOL> <ALIAS> [<VALUE>]

Options

  • -h, --help β€” prints help

Arguments

  • <TOOL> β€” the tool to alias
  • <ALIAS> β€” the version alias to set, or the backend when VALUE is omitted
  • <VALUE> β€” the version request the alias stands for

Examples

Install ripgrep from its aqua backend

mise tool-alias set ripgrep aqua:BurntSushi/ripgrep

Make node@project mean node@20

mise tool-alias set node project 20

πŸ’€ MISE TOOL-ALIAS UNSET

Removes a backend alias or a version alias from the global config

With only TOOL, it removes that tool's backend alias. With TOOL and ALIAS, it removes that version alias. It edits the global config (~/.config/mise/config.toml by default).

Usage: mise tool-alias unset [OPTIONS] <TOOL> [<ALIAS>]

Options

  • -h, --help β€” prints help

Arguments

  • <TOOL> β€” the tool to remove the alias from
  • <ALIAS> β€” the version alias to remove; omit it to remove the backend alias

Examples

Remove ripgrep's backend alias

mise tool-alias unset ripgrep

Remove node's project version alias

mise tool-alias unset node project

🌈 MISE BACKENDS 🌈

Manages backends

A backend is where mise installs a tool from: a package registry like npm or cargo, a release host like GitHub, or a plugin. Every tool uses exactly one, either written as a prefix (npm:prettier) or chosen by the registry. With no subcommand, it lists the built-in backends. See https://mise.jdx.dev/dev-tools/backends/

Usage: mise backends [OPTIONS] [COMMAND]

Options

  • -h, --help β€” prints help

πŸ“ MISE BACKENDS LS

Lists the built-in backends

Backends that plugins add are listed by mise plugins ls instead.

Usage: mise backends ls [OPTIONS]

Options

  • -h, --help β€” prints help

Examples

List the backends built into mise

mise backends ls

πŸ”₯ MISE BACKENDS SWITCH

Switches tools over to the backend the registry now installs them from

Okay so here's the situation: when the registry moves a tool to another backend, mise keeps installing it from the backend recorded in mise.lock and warns you that the registry has a newer one. This command moves those lock entries to the registry's backend at the same versions, relocks them so they record the new backend's checksums and URLs, and reinstalls the installed versions so they actually come from the new backend. A whole glow-up for your lockfile πŸ’…

It covers the lockfiles that mise lock writes: the current project's, or the global config's with --global.

Usage: mise backends switch [OPTIONS] [<TOOL@VERSION>] ...

Options

  • -n, --dry-run β€” show what would switch without changing the lockfile or installs
  • -g, --global β€” switch tools in the global config's lockfile instead of the project's
  • -h, --help β€” prints help

Arguments

  • <TOOL@VERSION> β€” the tools to switch

Defaults to every configured tool whose locked backend the registry has replaced. A version (hk@1.58.1) limits the switch to just that version.

Examples

Move communique to the registry's current backend

mise backends switch communique

List every locked tool the registry now installs from another backend

mise backends switch --dry-run

πŸŽ€ MISE BIN-PATHS πŸŽ€

Lists the bin directories of the active tools

It prints the bin directories of the tool versions your current config selects. It does not include _.path entries from [env] β€” if you want everything mise adds to PATH, that's mise doctor path 🩺

Usage: mise bin-paths [OPTIONS] [<TOOL@VERSION>] ...

Options

  • --bin-names β€” print executable names instead of bin directories
  • -J, --json β€” print executables as JSON objects with name, path, and symlink (implies --bin-names)
  • -h, --help β€” prints help

Arguments

  • <TOOL@VERSION> β€” only list these tools, such as ruby@3

🌸 Examples

Print the bin directory of every active tool

mise bin-paths

Print only node's bin directory

mise bin-paths node

List the executables the active tools provide

mise bin-paths --bin-names

πŸŽ€ MISE BOOTSTRAP πŸŽ€

Set up this whole machine from your mise config. Like, the whole machine. Bestie, this is the main character of machine setup πŸ’…

It applies each part your config declares, in this exact order. Every step names its parts the same way --only and --skip accept them, followed by any condition it has.

  1. accounts, then plugins (package manager plugins)
  2. files with phase = "pre-packages", then built-in packages
  3. The remaining files, then services, firewall, and compose
  4. repos, then dotfiles
  5. mise-shell-activate, macos-defaults, and macos-launchd-agents
  6. linux-systemd-units, then user (the login shell)
  7. tools
  8. Plugin packages, then user services with requires_tools = true
  9. task (the bootstrap task, if defined), then final-hook

Hooks run before and after packages, repos, dotfiles, macOS defaults, the login shell, and tools. The post-packages hook runs right after built-in packages, or after plugin packages when any are configured. Full deets: https://mise.jdx.dev/bootstrap.html#how-it-runs.

Parts that already match the config get left alone, but heads up β€” hooks and the bootstrap task run every time, so please make them safe to repeat, okay? πŸ™ Also, checking dotfile state can render templates, which may run exec(). Yeah. Just so you know.

Preview it all with --dry-run. And if you wanna inspect without applying anything, use mise bootstrap status for current state, or mise bootstrap plan for resource-level changes. Obsessed with a dry run, honestly.

Usage: mise bootstrap [OPTIONS] [COMMAND]

✨ Options ✨

  • --from <GIT_URL> β€” Clone a bootstrap project (a Git repository with a mise.toml) and apply it

The checkout gets reused on later runs; add --update to fast-forward it first. Append ?ref=<branch|tag|commit> to check out a ref instead of the default branch, like https://github.com/example/workstation.git?ref=v1. More at https://mise.jdx.dev/bootstrap/from-repository.html πŸ’–

  • --adopt <GIT_URL|OWNER/REPO> β€” Clone a repository of global mise config or dotfile history, then apply it

A repository of global config (config.toml, conf.d/, tasks/) gets cloned into the global config directory, normally ~/.config/mise. A setup repository shared with mise dotfiles origin set restores its tracked files instead. OWNER/REPO is short for https://github.com/OWNER/REPO.git. Append ?ref=<branch> to adopt a branch other than the default branch.

  • --replace-history β€” Discard this machine's dotfile history and adopt the repository's

Use it with --adopt when the two histories are unrelated. Files that differ from the repository still stop the adoption until you resolve them, or you can add --take-remote-all to take the repository's version of each. No cap.

  • --take-remote-all β€” Take the setup repository's version of every existing file that differs while adopting

The replaced versions get saved first, so mise dot undo restores them. Lifesaver fr 🫢

  • --from-dir <DIR> β€” Directory for the --from checkout (default: $MISE_DATA_DIR/bootstrap-repo)
  • --config-dir <DIR> β€” Link the global config directory to this directory of the --from checkout

mise links its config directory, normally ~/.config/mise, to the directory, then bootstraps from it, so its config.toml, config.<env>.toml, conf.d/, and miserc.toml are the global config from this run on. The directory must exist in the checkout, and the path to it is relative to the checkout and must stay inside it; . is the checkout itself. mise's config directory, where the link goes, must be missing, empty, or already this link. See https://mise.jdx.dev/bootstrap/from-repository.html#global-config-elsewhere.

  • -n, --dry-run β€” Show what would change without changing anything

Hooks and the bootstrap task are printed instead of run. Iconic behavior tbh.

  • -y, --yes β€” Skip confirmation prompts
  • --skip-dirty β€” Skip configured repositories with local changes instead of failing
  • --force-dotfiles β€” Overwrite existing files that conflict with whole-file dotfile entries
  • --prune-dotfiles β€” Remove files that dotfile groups deployed but no active entry deploys now

The same pruning as mise dot apply --prune, run at the end of the dotfiles phase before its post hook: files of a group that is no longer selected or declared, and files a group stopped deploying because of a new exclude or a deleted source. Changed copies stay in place, and mise asks before removing anything unless --yes is given or there is no terminal. With --dry-run, nothing is removed. Safety first, bestie πŸ¦‹

  • --only <PART> β€” Run only these parts

Repeat the flag or separate parts with commas. Cannot be combined with --skip. Pick one lane, babe.

  • --prompt-secrets β€” Prompt securely for missing bootstrap secret inputs
  • --prompt-vars β€” Ask for [vars] entries that declare a prompt and have no saved answer

mise saves each answer under $MISE_STATE_DIR, not in any config file, and never asks for it again. Without a terminal, a var keeps its default. A --dry-run still saves the answers it asks for. Sneaky but correct πŸ’€

  • --skip <PART> β€” Skip these parts

Repeat the flag or separate parts with commas. Cannot be combined with --only.

  • --update β€” Refresh package metadata and update repositories before applying

Also fast-forwards a checkout that --from or --adopt reuses. Without --update, a reused checkout stays at its current commit.

  • --upgrade β€” Upgrade installed packages and tools as well as installing missing ones

In the packages phase, runs the equivalent of mise bootstrap packages upgrade after installing; in the tools phase, runs mise upgrade (without --bump) after installing. Package pins and tool version ranges are respected. Does not update mise itself, repositories, or container images, and does not restart services; see --update for repositories and mise self-update for mise. Read that again, bestie β€” it's giving "not a magic wand" 😭

  • -h, --help β€” Print help

🌸 Examples 🌸

Preview every configured part:

mise bootstrap --dry-run

Apply every configured part:

mise bootstrap

Apply only dotfiles and tools:

mise bootstrap --only dotfiles,tools

Apply everything except tools and the bootstrap task:

mise bootstrap --skip tools,task

Replace files that conflict with whole-file dotfile entries:

mise bootstrap --force-dotfiles

Clone a bootstrap project and apply it:

mise bootstrap --from git@github.com:example/workstation.git

Do the same and also load the project's mise.work.toml:

mise -E work bootstrap --from git@github.com:example/workstation.git

Clone a dotfiles repository and link ~/.config/mise to its .config/mise:

mise bootstrap --from https://github.com/example/dotfiles.git --from-dir ~/.dotfiles --config-dir .config/mise

Clone global config into ~/.config/mise, then apply it:

mise bootstrap --adopt example/mise-config

Use a setup repository's dotfile history instead of this machine's:

mise bootstrap --adopt example/setup --replace-history --yes

Refresh package metadata and fast-forward repositories first:

mise bootstrap --update

πŸ‘‘ MISE BOOTSTRAP ACCOUNTS πŸ‘‘

Manage Linux users and groups.

Creates, updates, or removes the local accounts declared in [bootstrap.users] and [bootstrap.groups] on Linux. Run status or apply --dry-run before changing user IDs, group memberships, or account state. Like, please β€” user IDs are not a vibe to mess with blindly πŸ’€

Usage: mise bootstrap accounts [OPTIONS] <COMMAND>

Options

  • -h, --help β€” Print help

MISE BOOTSTRAP ACCOUNTS APPLY

Create, update, or remove the configured Linux users and groups.

Usage: mise bootstrap accounts apply [OPTIONS]

Options

  • -n, --dry-run β€” Show what would change without changing anything
  • -y, --yes β€” Skip the confirmation prompt
  • -h, --help β€” Print help

MISE BOOTSTRAP ACCOUNTS STATUS

Show the state of the configured Linux users and groups.

Usage: mise bootstrap accounts status [OPTIONS]

Options

  • -J, --json β€” Output in JSON format
  • --missing β€” Exit with status 1 if any account differs from the config (all are still listed). Perfect for CI, iykyk ✨
  • -h, --help β€” Print help

MISE BOOTSTRAP COMPOSE 🐳

Manage Docker Compose projects from [bootstrap.compose].

Needs a running Docker engine and the Docker Compose command on this machine. No engine, no slay. Periodt.

Usage: mise bootstrap compose [OPTIONS] <COMMAND>

Options

  • -h, --help β€” Print help

Examples

Show the state of every declared project:

mise bootstrap compose status

Show what would change:

mise bootstrap compose apply --dry-run

MISE BOOTSTRAP COMPOSE APPLY

Apply Docker Compose projects from [bootstrap.compose].

Usage: mise bootstrap compose apply [OPTIONS]

Options

  • -n, --dry-run β€” Show what would change without changing anything
  • -y, --yes β€” Skip the confirmation prompt
  • -h, --help β€” Print help

MISE BOOTSTRAP COMPOSE STATUS

Show the state of Docker Compose projects from [bootstrap.compose].

Usage: mise bootstrap compose status [OPTIONS]

Options

  • -J, --json β€” Output in JSON format
  • --missing β€” Exit with status 1 if any Compose project differs from the config (all are still listed)
  • -h, --help β€” Print help

🧚 MISE BOOTSTRAP FILES 🧚

Manage system files and directories declared in [bootstrap].

Applies [bootstrap.files] and [bootstrap.directories]: paths that need a specific owner, group, or mode, or that must exist or be absent system-wide, such as configuration under /etc. For files in your home directory that you actually edit, use [dotfiles] and mise dotfiles instead. Different tool, different vibe πŸ’…

Usage: mise bootstrap files [OPTIONS] <COMMAND>

Options

  • -h, --help β€” Print help

Examples

Exit with status 1 if any file or directory differs from the config:

mise bootstrap files status --missing

Show what would change:

mise bootstrap files apply --dry-run

Apply without a prompt:

mise bootstrap files apply --yes

MISE BOOTSTRAP FILES APPLY

Create, update, or remove the configured system files and directories.

Usage: mise bootstrap files apply [OPTIONS]

Options

  • -n, --dry-run β€” Show what would change without changing anything
  • -y, --yes β€” Skip the confirmation prompt
  • --prompt-secrets β€” Prompt securely for missing bootstrap secret inputs
  • -h, --help β€” Print help

πŸ“‚ MISE BOOTSTRAP FILES STATUS

bestie this one's the vibe check for all your configured system files and directories β€” it shows you the state of everything πŸ’…

Usage: mise bootstrap files status [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” spit it out in JSON format, for when you want your data looking all structured and slay πŸ”₯
  • --missing β€” exit with status 1 if any file or directory differs from the config (don't worry, everything still gets listed, no gatekeeping) 🫢
  • --prompt-secrets β€” securely prompt you for any missing bootstrap secret inputs, very discreet, very demure πŸ™ˆ
  • -h, --help β€” print help, the classic, the icon πŸ‘‘

πŸ”₯ MISE BOOTSTRAP FIREWALL

manage the Linux host firewall straight from [bootstrap.linux.firewall] β€” yes, that firewall πŸ”₯

It works with nftables, firewalld, or UFW, and it keeps mise's rules totally separate from all your other host rules (boundaries, we love her ✨).

⚠️ ok listen, this part is serious: over SSH, mise refuses a default incoming policy of deny or reject unless a rule allows the current connection or the config sets allow_lockout = true. That's your lockout protection, no cap. Always check apply --dry-run before applying a policy to a remote machine β€” fr fr, do not skip this πŸ’€
Usage: mise bootstrap firewall [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help πŸ‘‘

🌸 EXAMPLES 🌸

Show the firewall's state:

mise bootstrap firewall status

Show the policy and rules that would change:

mise bootstrap firewall apply --dry-run

βœ… MISE BOOTSTRAP FIREWALL APPLY

apply the firewall from [bootstrap.linux.firewall] β€” make it real, bestie ✨

Usage: mise bootstrap firewall apply [OPTIONS]

✨ OPTIONS ✨

  • -n, --dry-run β€” show what would change without changing anything, a little peek, a little window shopping πŸ›οΈ
  • -y, --yes β€” skip the confirmation prompt, living dangerously (respectfully) πŸ’…
  • -h, --help β€” print help πŸ‘‘

πŸ” MISE BOOTSTRAP FIREWALL STATUS

show the state of the firewall from [bootstrap.linux.firewall] β€” the glow-up report card πŸŽ€

Usage: mise bootstrap firewall status [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format πŸ”₯
  • --missing β€” exit with status 1 if the firewall differs from the config (everything still gets listed tho, we don't hide things) 🫢
  • -h, --help β€” print help πŸ‘‘

🐧 MISE BOOTSTRAP LINUX

manage systemd user units from [bootstrap.linux.systemd.units] β€” Linux girlies rise 🐧✨

real talk: the host firewall in [bootstrap.linux.firewall] is managed by mise bootstrap firewall, not here. Different department, different queen πŸ‘‘

Usage: mise bootstrap linux [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help πŸ‘‘

βš™οΈ MISE BOOTSTRAP LINUX SYSTEMD-UNITS

manage systemd user units from [bootstrap.linux.systemd.units] β€” the group chat admin of your services βš™οΈ

So what it does: it writes unit files to ~/.config/systemd/user, then enables and starts them as configured. Slay.

An entry with state = "absent" gets stopped, disabled, and deleted instead β€” she's leaving the chat πŸ’€

⚠️ Units run with your permissions and need a reachable systemd user manager. That's the whole vibe requirement, no exceptions.

For system units, or a user service that also works on macOS and Windows, use [bootstrap.services] instead β€” different tool, same energy πŸ¦‹

Usage: mise bootstrap linux systemd-units [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help πŸ‘‘

πŸš€ MISE BOOTSTRAP LINUX SYSTEMD-UNITS APPLY

install and start the configured systemd user units β€” let's get her running πŸš€

Usage: mise bootstrap linux systemd-units apply [OPTIONS]

✨ OPTIONS ✨

  • -n, --dry-run β€” show what would change without changing anything, zero commitment, all information πŸ‘€
  • -y, --yes β€” skip the confirmation prompt πŸ’…
  • -h, --help β€” print help πŸ‘‘

πŸ“Š MISE BOOTSTRAP LINUX SYSTEMD-UNITS STATUS

show the state of the configured systemd user units β€” the receipts 🧾✨

Usage: mise bootstrap linux systemd-units status [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format πŸ”₯
  • --missing β€” exit with status 1 if any unit differs from the config (all still listed, we show everything) 🫢
  • -h, --help β€” print help πŸ‘‘

🍎 MISE BOOTSTRAP MACOS

manage macOS preferences and LaunchAgents from [bootstrap.macos] β€” Apple girlies, this one's for you πŸŽπŸ’–

Usage: mise bootstrap macos [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help πŸ‘‘

πŸŽ€ MISE BOOTSTRAP MACOS DEFAULTS

manage macOS preferences such as Dock, Finder, and keyboard settings β€” the aesthetic settings, the little details that matter πŸŽ€

It applies [bootstrap.macos.defaults], [[bootstrap.macos.defaults_entries]], and the [bootstrap.macos.dock], finder, keyboard, and trackpad sections. Preferences are written the way defaults write writes them. Iconic.

⚠️ mise does not restart apps. Dock, Finder, and some others show a change only after they relaunch. So don't come for mise when Finder's still acting brand new β€” she needs a minute 😭
Usage: mise bootstrap macos defaults [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help πŸ‘‘

✍️ MISE BOOTSTRAP MACOS DEFAULTS APPLY

write the configured macOS preferences β€” time to set the vibe, permanently ✍️✨

Usage: mise bootstrap macos defaults apply [OPTIONS]

✨ OPTIONS ✨

  • -n, --dry-run β€” show what would change without changing anything, window shopping only πŸ›οΈ
  • -y, --yes β€” skip the confirmation prompt πŸ’…
  • -h, --help β€” print help πŸ‘‘

πŸ”Ž MISE BOOTSTRAP MACOS DEFAULTS STATUS

show the state of the configured macOS preferences β€” the before-&-after ✨

Usage: mise bootstrap macos defaults status [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format πŸ”₯
  • --missing β€” exit with status 1 if any preference differs from the config (all still listed, always transparent) 🫢
  • -h, --help β€” print help πŸ‘‘

πŸš€ MISE BOOTSTRAP MACOS LAUNCHD-AGENTS

manage macOS LaunchAgents from [bootstrap.macos.launchd.agents] β€” startup queen behaviour πŸ‘‘

It writes each agent to ~/Library/LaunchAgents/dev.mise.<name>.plist and loads it into your GUI login session.

⚠️ Run it as the user who owns the agents, bestie. An SSH session without a GUI login may not be able to load them β€” that's just how it is, no cap 😭

For a user service that also works on Linux and Windows, use [bootstrap.services] with scope = "user" instead πŸ¦‹

Usage: mise bootstrap macos launchd-agents [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help πŸ‘‘

πŸ’« MISE BOOTSTRAP MACOS LAUNCHD-AGENTS APPLY

install and load LaunchAgents from [bootstrap.macos.launchd.agents] β€” get her up and running πŸ’«

Usage: mise bootstrap macos launchd-agents apply [OPTIONS]

✨ OPTIONS ✨

  • -n, --dry-run β€” show what would change without changing anything πŸ‘€
  • -y, --yes β€” skip the confirmation prompt πŸ’…
  • -h, --help β€” print help πŸ‘‘

πŸ“‹ MISE BOOTSTRAP MACOS LAUNCHD-AGENTS STATUS

show the state of the configured LaunchAgents β€” the status update nobody had to ask for but everyone needed πŸ“‹βœ¨

Usage: mise bootstrap macos launchd-agents status [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format πŸ”₯
  • --missing β€” exit with status 1 if any LaunchAgent differs from the config (all still listed, we stay showing receipts) 🫢
  • -h, --help β€” print help πŸ‘‘

🐚 MISE BOOTSTRAP MISE-SHELL-ACTIVATE

manage mise shell activation from [bootstrap.mise_shell_activate] β€” the "have you tried turning mise on" of it all 🐚✨

It writes a managed activation block into each configured shell startup file.

⚠️ It does not activate mise in the shell you run it from. You gotta open a new shell afterward β€” that's the whole thing, that's the assignment πŸ’…
Usage: mise bootstrap mise-shell-activate [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help πŸ‘‘

πŸͺ„ MISE BOOTSTRAP MISE-SHELL-ACTIVATE APPLY

write mise activation into the configured shell startup files β€” she's getting in, bestie πŸͺ„

Usage: mise bootstrap mise-shell-activate apply [OPTIONS]

✨ OPTIONS ✨

  • -n, --dry-run β€” show what would change without changing anything πŸ‘€
  • -y, --yes β€” skip the confirmation prompt πŸ’…
  • -h, --help β€” print help πŸ‘‘

🌸 MISE BOOTSTRAP MISE-SHELL-ACTIVATE STATUS

show the state of the configured shell activation β€” is she activated or is she not 🌸

Usage: mise bootstrap mise-shell-activate status [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format πŸ”₯
  • --missing β€” exit with status 1 if any shell activation differs from the config (all still listed, we're not hiding anything from you) 🫢
  • -h, --help β€” print help πŸ‘‘

πŸ“¦ MISE BOOTSTRAP PACKAGES

manage packages from [bootstrap.packages] β€” the main event, the haul, the shopping spree πŸ“¦πŸ’–

So here's how you declare them: as "manager:package" = "version".

  • apply installs what's missing and removes what is declared absent
  • use adds an entry and installs it
  • upgrade updates configured packages that are installed
  • prune uninstalls Homebrew formulae, casks, or package plugin packages that no config declares
  • import records installed Homebrew formulae
  • status shows what differs from the config

Each package manager has its own little lore over at https://mise.jdx.dev/bootstrap/packages/ ✨

Usage: mise bootstrap packages [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help πŸ‘‘

πŸ›οΈ MISE BOOTSTRAP PACKAGES APPLY

install or remove packages to match [bootstrap.packages] β€” the haul, executed πŸ›οΈβœ¨

OK so the details matter here, bestie, pay attention:

It installs each configured package that is missing or does not match its declared version, and removes packages declared state = "absent" on the managers that support removal β€” that's pacman, scoop, snap, and zypper πŸ’…

⚠️ On other managers, an installed package declared absent is left in place with a warning. apply fails for it only when you pass --manager or name the package. Awkward but that's the rule, no cap.

Built-in managers may use sudo when not running as root (see the system_packages.sudo setting); package plugins never do. Managers that are not available on this machine are skipped β€” no drama, no error.

Name packages as manager:package, for example apt:curl or brew:jq, to install them without adding them to config; use mise bootstrap packages use to record them as well.

⚠️ When you name packages or pass --manager, an unavailable manager is an error instead of a skip. Different rules when you're being specific, iykyk.
Usage: mise bootstrap packages apply [OPTIONS] [<PACKAGE>] ...

✨ OPTIONS ✨

  • -m, --manager <MANAGER> β€” only apply packages for this built-in or plugin manager 🎯
  • -n, --dry-run β€” show what would change without changing anything πŸ‘€
  • -y, --yes β€” skip the confirmation prompt πŸ’…
  • --update β€” refresh package manager metadata first, where the manager supports it. For example, apt runs apt-get update and dnf adds --refresh. Meanwhile brew, brew-cask, flatpak, flatpak-user, macos-app, mas, and snap ignore this flag entirely (not them being unbothered 😭)
  • -h, --help β€” print help πŸ‘‘

🧾 ARGUMENTS 🧾

  • <PACKAGE> β€” packages as manager:package; defaults to every package in [bootstrap.packages]

🌟 EXAMPLES 🌟

Install missing packages and remove ones declared absent:

mise bootstrap packages apply

Show what would change:

mise bootstrap packages apply --dry-run

Apply only apt packages, without a prompt:

mise bootstrap packages apply --manager apt --yes

On Debian or Ubuntu, install one package without adding it to config:

mise bootstrap packages apply apt:curl

On macOS, install a formula and a cask without adding them to config:

mise bootstrap packages apply brew:jq brew-cask:firefox

🍺 MISE BOOTSTRAP PACKAGES BREW

manage Homebrew tap URLs in [bootstrap.brew.taps] β€” the inside scoop on your taps 🍺✨

Here's the tea: mise finds a third-party tap such as acme/tools at https://github.com/acme/homebrew-tools without an entry. So you only add one when the tap's repository lives at a different GitHub URL β€” and heads up, only GitHub taps are supported 🫢

These commands edit config; they do not run Homebrew. Just so we're clear πŸ’…

⚠️ Not available on Windows. Sorry Windows besties 😭
Usage: mise bootstrap packages brew [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help πŸ‘‘

🍺 MISE BOOTSTRAP PACKAGES BREW TAP

ok so bestie, this one is literally just "add a Homebrew tap URL to the global [bootstrap.brew.taps]" πŸ’–

Usage: mise bootstrap packages brew tap [OPTIONS] <TAP> [<URL>]

✨ Options ✨

  • -l, --local β€” write it to the local config instead of the global config, no cap
  • -n, --dry-run β€” just show you the config change, don't actually write it πŸ‘€
  • -p, --path, --file <PATH> β€” write to this config file or directory
  • -h, --help β€” print help

🌸 Arguments 🌸

  • <TAP> β€” the tap name, like owner/repo
  • <URL> β€” the GitHub URL of the tap; defaults to https://github.com/<owner>/homebrew-<repo>.git

πŸŽ€ Examples πŸŽ€

Record a tap whose repository is not acme/homebrew-tools:

mise bootstrap packages brew tap acme/tools https://github.com/acme/brew-tools.git

Write the entry to the local config instead:

mise bootstrap packages brew tap acme/tools https://github.com/acme/brew-tools.git --local

πŸ’… MISE BOOTSTRAP PACKAGES BREW UNTAP

the opposite vibes fr β€” remove Homebrew tap URLs from [bootstrap.brew.taps] 🫢

Usage: mise bootstrap packages brew untap [OPTIONS] <TAPS> ...

✨ Options ✨

  • -l, --local β€” write to the local config instead of the global config
  • -n, --dry-run β€” show the config change without writing it
  • -p, --path, --file <PATH> β€” write to this config file or directory
  • -h, --help β€” print help

🌸 Arguments 🌸

  • <TAPS> β€” tap names, like owner/repo

πŸŽ€ Examples πŸŽ€

Remove a tap entry from the global config:

mise bootstrap packages brew untap acme/tools

🧚 MISE BOOTSTRAP PACKAGES EXPORT

this one's giving "print the configured nix: packages as a NixOS module" πŸ’œ

It prints out a module that adds each package to environment.systemPackages, and it does that without running Nix. You import it into a NixOS configuration, and the packages resolve against that configuration's pkgs. Entries for another OS or environment get left out, and so do entries with state = "absent". Also, heads up: only shorthand attributes like nix:ripgrep can be exported β€” a flake reference or a version pin is an error, because the importing configuration is the one that decides where packages come from. 😀

Usage: mise bootstrap packages export [OPTIONS]

✨ Options ✨

  • --format <FORMAT> β€” output format
  • -h, --help β€” print help

πŸŽ€ Examples πŸŽ€

Write the module to a file you can import from a NixOS configuration:

mise bootstrap packages export --format nix > packages.nix

πŸ“ MISE BOOTSTRAP PACKAGES IMPORT

ok so this is "record installed Homebrew formulae in [bootstrap.packages]" β€” icon behaviour honestly ✨

It adds a brew: entry for each linked formula that you installed yourself, and it skips the ones that only got pulled in as dependencies β€” unless you pass --all, then those come along too. Formulae from third-party taps get written with their full name, and each tap gets a [bootstrap.brew.taps] entry with the URL that's already in your config, or the default GitHub URL. It writes to the local config unless you pass -g, -e, or -p. πŸ’…

Usage: mise bootstrap packages import [OPTIONS]

✨ Options ✨

  • -e, --env <ENV> β€” write to the config file for this environment (mise.<ENV>.toml)
  • -g, --global β€” write to the global config (~/.config/mise/config.toml). New entries go to the write_targets.packages file when that setting is set.
  • -m, --manager <MANAGER> β€” package manager to import from. Default: brew
  • --all β€” import every linked formula, including dependencies
  • -n, --dry-run β€” show the entries that would be written without writing them
  • -p, --path, --file <PATH> β€” write to this config file or directory
  • -h, --help β€” print help

πŸŽ€ Examples πŸŽ€

Show the entries that would be written:

mise bootstrap packages import --dry-run

Write them to the local config:

mise bootstrap packages import

Include formulae installed as dependencies:

mise bootstrap packages import --all

Write to the global config:

mise bootstrap packages import -g

πŸ’€ MISE BOOTSTRAP PACKAGES PRUNE

"uninstall packages that no config declares" β€” yeah this one is highkey scary so read carefully bestie 😭

⚠️ For brew (the default), it removes every linked formula that is neither declared nor needed by a declared formula or cask β€” and yes, that includes formulae you installed with Homebrew yourself. So run with --dry-run first, or record your existing formulae with mise bootstrap packages import before you go feral. πŸ™ˆ

For brew-cask, it removes only casks mise installed and can prove are unchanged. For a package plugin that supports uninstalling, it removes only packages mise installed. A package is kept while the current config, or any trusted config mise has tracked, still declares it. 🫢

Usage: mise bootstrap packages prune [OPTIONS]

✨ Options ✨

  • -m, --manager <MANAGER> β€” package manager to prune: brew, brew-cask, or a package plugin. Default: brew
  • -n, --dry-run β€” show what would be removed without removing anything
  • -y, --yes β€” skip the confirmation prompt
  • --force β€” remove brew-cask casks that mise installed even when it cannot prove they are unchanged, like self-updating apps or casks with install scripts. mise removes the files it recorded installing that are still in place, but not what a cask's own install scripts created.
  • -h, --help β€” print help

πŸŽ€ Examples πŸŽ€

Preview which Homebrew formulae would be removed:

mise bootstrap packages prune --dry-run

Remove them without a prompt:

mise bootstrap packages prune --yes

Preview which casks would be removed:

mise bootstrap packages prune --manager brew-cask --dry-run

Preview removals for a package plugin named vscode:

mise bootstrap packages prune --manager vscode --dry-run

🌈 MISE BOOTSTRAP PACKAGES STATUS

vibe check time β€” show the state of packages from [bootstrap.packages] πŸ¦‹

Usage: mise bootstrap packages status [OPTIONS]

✨ Options ✨

  • -J, --json β€” output in JSON format
  • --missing β€” exit with status 1 if any package differs from the config (all are still listed, don't worry)
  • -h, --help β€” print help

πŸŽ€ Examples πŸŽ€

List every configured package and its state:

mise bootstrap packages status

Print the state as JSON:

mise bootstrap packages status --json

Exit with status 1 if any package differs from the config:

mise bootstrap packages status --missing

πŸ”₯ MISE BOOTSTRAP PACKAGES UPGRADE

"upgrade installed packages from [bootstrap.packages]" β€” glow-up szn ✨

It refreshes package manager metadata first, then upgrades the configured packages that are already installed. Each manager decides which version is current. Version pins in config are honored where the manager can install them; other pinned entries get skipped with a warning. Packages that aren't installed yet are skipped too β€” install those with mise bootstrap packages apply. See https://mise.jdx.dev/bootstrap/packages/ for what each manager does.

Name packages as manager:package to upgrade only those. πŸ‘‘

Usage: mise bootstrap packages upgrade [OPTIONS] [<PACKAGE>] ...

✨ Options ✨

  • -m, --manager <MANAGER> β€” only upgrade packages for this built-in or plugin manager
  • -n, --dry-run β€” show what would change without changing anything
  • -y, --yes β€” skip the confirmation prompt
  • -h, --help β€” print help

🌸 Arguments 🌸

  • <PACKAGE> β€” packages as manager:package; defaults to every package in [bootstrap.packages]

πŸŽ€ Examples πŸŽ€

Show what would be upgraded:

mise bootstrap packages upgrade --dry-run

Upgrade every configured package that is already installed:

mise bootstrap packages upgrade

Upgrade only apt packages, without a prompt:

mise bootstrap packages upgrade --manager apt --yes

Upgrade one Homebrew formula:

mise bootstrap packages upgrade brew:postgresql@17

πŸ‘‘ MISE BOOTSTRAP PACKAGES USE

"add packages to [bootstrap.packages] and install them" β€” literally the main character of this whole thing πŸ’–

It works like mise use for tools: it writes a "manager:package" = "version" entry to the local mise.toml (or the global config with -g), then installs anything missing. If the manager isn't available on this machine β€” think apt: on macOS β€” the entry is written without installing. No drama, no error, it just chills there. 🧚

Pin a version with @, like apt:curl@8.5.0-2; with no @, or with @latest, the entry is "latest". Homebrew puts versions in formula and cask names (brew:postgresql@17, brew-cask:temurin@17), so there @ is part of the name. mas takes numeric App Store IDs and nix takes attribute paths or flake references, so neither accepts @version. And aur, flatpak, flatpak-user, pacman, and snap accept @version but cannot install a pin β€” so installing skips those entries with a warning. ⭐

Usage: mise bootstrap packages use [OPTIONS] <PACKAGE> ...

✨ Options ✨

  • -e, --env <ENV> β€” write to the config file for this environment (mise.<ENV>.toml)
  • -g, --global β€” write to the global config (~/.config/mise/config.toml) instead of the local one. New entries go to the write_targets.packages file when that setting is set.
  • -n, --dry-run β€” show what would change without writing config or installing
  • -p, --path, --file <PATH> β€” write to this config file or directory
  • -y, --yes β€” skip the confirmation prompt
  • --no-install β€” write the package declarations without checking or installing packages
  • -h, --help β€” print help

🌸 Arguments 🌸

  • <PACKAGE> β€” packages in manager:package[@version] form

πŸŽ€ Examples πŸŽ€

Declare apt and winget packages; each machine installs the ones it can:

mise bootstrap packages use apt:curl winget:BurntSushi.ripgrep.MSVC

On macOS, add a formula and a cask:

mise bootstrap packages use brew:jq brew-cask:firefox

Add a versioned Homebrew formula to the global config:

mise bootstrap packages use -g brew:postgresql@17

Pin an apt package to a version:

mise bootstrap packages use apt:curl@8.5.0-2

🌸 MISE BOOTSTRAP PACKAGES WHERE

"print the opt path of an installed Homebrew formula" β€” lowkey the most useful little helper ever 🫢

It prints a path like /opt/homebrew/opt/openssl@3 that keeps pointing at the installed version across upgrades. Name the formula as brew:<formula> or brew:<owner>/<tap>/<formula>, using its installed name β€” aliases are not resolved, and a tap-qualified name matches by formula name only. The command does not read mise config files, so only environment variables and global flags apply. If the formula isn't installed, it prints nothing and exits with a nonzero status. Works on macOS on Apple silicon and on Linux (x86_64 and arm64). πŸ’…

Usage: mise bootstrap packages where [OPTIONS] <PACKAGE>

✨ Options ✨

  • -h, --help β€” print help

🌸 Arguments 🌸

  • <PACKAGE> β€” formula to locate, as brew:<formula> or brew:<owner>/<tap>/<formula>

πŸŽ€ Examples πŸŽ€

Put a formula's bin directory on PATH when it is installed:

if root="$(mise bootstrap packages where brew:unzip)"; then
  export PATH="$root/bin:$PATH"
fi

πŸŽ€ MISE BOOTSTRAP PLAN

Okay bestie, this one is literally a preview era β€” it shows what applying your bootstrap resources would change. No cap, no actual changes, just the vibe check first. πŸ’…

It covers accounts, packages, files and directories, system and user services, the firewall, and Compose projects β€” in dependency order, because we're organized like that. ✨

Heads up though: repositories, dotfiles, shell activation, macOS defaults, LaunchAgents, systemd user units, the login shell, tools, hooks, and the bootstrap task are not planned here. If you want the whole run previewed, do mise bootstrap --dry-run instead. iykyk 🫢
Usage: mise bootstrap plan [OPTIONS]

✨ Options ✨

  • -J, --json β€” spits out a stable machine-readable plan in JSON format, for when you need the data and not the drama πŸ¦‹
  • --detailed-exitcode β€” exits 0 if nothing would change, 2 if something would, and 1 on errors or unknown state A resource's state is "unknown" when mise can't reach its declared state on its own β€” like a package whose manager isn't available on this machine or can't install the pinned version, or a service whose unit doesn't exist. 😭
  • --prompt-secrets β€” prompts securely for any missing bootstrap secret inputs πŸ”
  • -h, --help β€” print help, the classic

🌸 Examples 🌸

Show the planned changes:

mise bootstrap plan

Print the plan as JSON:

mise bootstrap plan --json

Exit with status 2 if anything would change:

mise bootstrap plan --detailed-exitcode

🧚 MISE BOOTSTRAP PLUGINS

Manage the package manager plugins declared in [bootstrap.plugins]. Obsessed. πŸŽ€

So a package plugin adds a package manager β€” think one for VS Code extensions β€” that [bootstrap.packages] entries can use. mise bootstrap installs plugins before packages, but when you're running the narrower commands, run plugins apply before packages apply. Order matters, bestie. ✨

Important: installing a plugin does not install its packages. Two separate things, don't conflate them. πŸ’€
Usage: mise bootstrap plugins [OPTIONS] <COMMAND>

✨ Options ✨

  • -h, --help β€” print help

πŸ¦‹ MISE BOOTSTRAP PLUGINS APPLY

Installs the package manager plugins declared in [bootstrap.plugins]. πŸ’–

It does not ask for confirmation β€” it just goes. Main character energy fr.

Usage: mise bootstrap plugins apply [OPTIONS]

✨ Options ✨

  • -n, --dry-run β€” show which plugins would be installed without actually installing them πŸ‘€
  • -h, --help β€” print help

🌈 MISE BOOTSTRAP PLUGINS STATUS

Shows whether the declared package manager plugins are actually installed. The receipts, basically. 🧾✨

Usage: mise bootstrap plugins status [OPTIONS]

✨ Options ✨

  • --missing β€” exit with status 1 if a declared plugin is not installed
  • -h, --help β€” print help

πŸ‘‘ MISE BOOTSTRAP REMOTE

Bootstrap one or more machines over SSH. This is the remote glow-up command, and yes it's a whole thing. πŸ”₯

Here's the flow: it packs a local project directory, copies it to each target, stages mise there, and runs mise bootstrap. The directory it packs is --source. Without it? An inventory host uses its own source, then the one in [bootstrap.remote], then the current directory β€” while a --host target just uses the current directory. Pick targets by name, --tag, or --all from [bootstrap.remote.hosts], or hand it any SSH destination with --host. 🫢

Targets need a POSIX shell plus tar, mktemp, cksum, and uname. Windows targets are not supported. Periodt. πŸ’€

--dry-run still connects, uploads, and inspects each target β€” it just changes nothing there. And with --adopt, each target adopts the repository exactly as mise bootstrap --adopt does, instead of receiving a project directory. 🌸

The --github-relay-* flags let targets read private GitHub repositories through this machine's credentials for the length of the run β€” without copying a token to them. Iconic. See https://mise.jdx.dev/bootstrap/github-relay.html πŸŽ€

Usage: mise bootstrap remote [OPTIONS] [<TARGET>] ...

✨ Options ✨

  • --adopt <GIT_URL|OWNER/REPO> β€” adopt global configuration or shared dotfile history on each target
  • --all β€” select every inventory host
  • --bootstrap-command <COMMAND> β€” shell command, run on each target, that installs mise and puts it on PATH
  • --connect-timeout <SECONDS> β€” SSH connection timeout in seconds Default: 10
  • --copy-link <PATH> β€” copy the target of this source-relative symbolic link instead of the link; repeat for more
  • --copy-links β€” copy the targets of every symbolic link in the source instead of the links
  • --exclude <PATTERN> β€” another pattern to leave out of the archive; repeat for more
  • --fail-fast β€” stop after the first failed target
  • --force-dotfiles β€” overwrite files on each target that conflict with whole-file dotfile entries
  • --host <[USER@]HOST> β€” SSH destination that is not in the inventory ([user@]host); repeat for more
  • -i, --identity-file <PATH> β€” SSH identity file, overriding the inventory and SSH config
  • -n, --dry-run β€” show what would change on each target without changing it It still connects to each target, uploads the project, stages mise, and inspects the target.
  • --install-mise <PATH> β€” install the provisioned mise on each host instead of only staging it Defaults to ~/.local/bin/mise; pass --install-mise=<PATH> for another path.
  • --keep-staging β€” keep the remote staging directory for debugging
  • --mise-bin <PATH> β€” upload this local mise executable, for platforms without an official release binary
  • --no-install-mise β€” do not install mise on the host, even when the selected hosts configure it
  • --only <PART> β€” run only these parts on each target Repeat the flag or separate parts with commas. Cannot be combined with --skip.
  • --port <PORT> β€” SSH port, overriding the inventory and SSH config
  • --prompt-secrets β€” prompt securely for missing secret inputs on the remote host
  • --remote-env <ENV> β€” config environments to load on each target; repeat or separate with commas (for example, ci,dotfiles)
  • --remote-mise <COMMAND> β€” existing mise executable name or path; relative paths use the staged project
  • --skip <PART> β€” skip these parts on each target Repeat the flag or separate parts with commas. Cannot be combined with --only.
  • --source <DIR> β€” local directory to archive and send to each target
  • --ssh-option <OPTION> β€” OpenSSH -o option; repeat for multiple options
  • --tag <TAG> β€” select configured hosts with this tag; repeat to match any tag
  • --update β€” refresh package metadata and update repositories on each target
  • -y, --yes β€” skip confirmation prompts on each target
  • --github-relay-read-only β€” borrow read-only GitHub access for this run (Linux and macOS only) Needs exactly one of --github-relay-repo or --github-relay-all-repos.
  • --github-relay-repo <OWNER/REPO> β€” repository the targets may read through the relay; repeat for more (needs --github-relay-read-only)
  • --github-relay-all-repos β€” let targets read every repository your local credentials can read (needs --github-relay-read-only)
  • --github-relay-log-requests β€” log sanitized relay requests on local stderr (needs --github-relay-read-only)
  • --github-relay-no-log-requests β€” turn off request logging, overriding the github_relay settings (needs --github-relay-read-only)
  • --github-relay-log-format <FORMAT> β€” relay log and summary format, text or jsonl (needs --github-relay-read-only)
  • --github-relay-max-duration <DURATION> β€” end borrowed access after a duration such as 1h; 0s lasts the whole run (needs --github-relay-read-only)
  • -h, --help β€” print help

🌟 Arguments 🌟

  • <TARGET> β€” inventory host names from [bootstrap.remote.hosts]

πŸ’œ Examples πŸ’œ

Preview a run on a host that is not in the inventory:

mise bootstrap remote --host devbox --dry-run

Bootstrap one inventory host:

mise bootstrap remote cache

Bootstrap every inventory host tagged canary, without prompts:

mise bootstrap remote --tag canary --yes

Bootstrap every inventory host and stop at the first failure:

mise bootstrap remote --all --fail-fast

Leave mise installed on the host after the run:

mise bootstrap remote --host ubuntu@cache.example.com -i
~/.ssh/mise-cache --install-mise

Let the host read one private GitHub repository during the run:

mise bootstrap remote --host devbox --github-relay-read-only
--github-relay-repo example/setup

πŸ“ MISE BOOTSTRAP REPOS

Manage the Git repositories from [bootstrap.repos]. Git girlies rise 🫢

Situation check: a repository with uncommitted changes, a different origin, or something that isn't a Git checkout at its path will stop apply and update before anything changes. Pass --skip-dirty to skip the repositories with uncommitted changes and just keep going with the rest. πŸ™ˆ

Usage: mise bootstrap repos [OPTIONS] <COMMAND>

✨ Options ✨

  • -h, --help β€” print help

⭐ MISE BOOTSTRAP REPOS APPLY

Clones missing Git repositories and checks out the configured refs. Slay. ✨

Usage: mise bootstrap repos apply [OPTIONS]

✨ Options ✨

  • -n, --dry-run β€” show what would change without changing anything
  • -y, --yes β€” skip the confirmation prompt
  • --skip-dirty β€” skip repositories with local changes instead of failing
  • -h, --help β€” print help

πŸ’« MISE BOOTSTRAP REPOS EXEC

Runs a command in each configured Git repository. Batch content fr. πŸ’…

Put the command and its arguments after --. Paths before -- select repositories. Real talk: the command runs directly, without a shell, so pipes and && do not work. Missing or conflicting repositories get skipped with a warning. Use --continue-on-error to visit the rest after a failure. πŸ¦‹

Usage: mise bootstrap repos exec [OPTIONS] [<PATH>] ... <COMMAND> ...

✨ Options ✨

  • -c, --continue-on-error β€” continue running in other repositories after a command fails
  • -n, --dry-run β€” print the commands that would run without running them
  • -h, --help β€” print help

🌟 Arguments 🌟

  • <PATH> β€” run only in repositories at these paths, as written in config or expanded
  • <COMMAND> β€” command and arguments to run in each repository

πŸ’œ Examples πŸ’œ

Show uncommitted changes in every repository:

mise bootstrap repos exec -- git status --short

Run a command in one repository:

mise bootstrap repos exec ~/src/mise -- git log -1

Fetch every repository, even after one fails:

mise bootstrap repos exec --continue-on-error -- git fetch

🌸 MISE BOOTSTRAP REPOS STATUS

Shows the state of the Git repositories from [bootstrap.repos]. The vibe check, but for Git. πŸ‘€βœ¨

Usage: mise bootstrap repos status [OPTIONS]

✨ Options ✨

  • -J, --json β€” output in JSON format
  • --missing β€” exit with status 1 if any repository differs from the config (they're all still listed, don't worry 🫢)
  • -h, --help β€” print help

πŸ’… MISE BOOTSTRAP REPOS UPDATE πŸ’…

Clone missing Git repositories and fast-forward the rest β€” like a little repo shepherd, no cap πŸ‘

For a repository without a ref, it fetches and fast-forwards the current branch; one with a detached HEAD is skipped with a warning (rude but fair πŸ’€). A repository with a ref gets checked out at that ref.

Usage: mise bootstrap repos update [OPTIONS] [<PATH>] ...

✨ Options ✨

  • -n, --dry-run β€” show what would change without actually changing anything πŸ‘€
  • -y, --yes β€” skip the confirmation prompt, we're brave today
  • --skip-dirty β€” skip repositories with local changes instead of failing 🫢
  • -h, --help β€” print help

🫢 Arguments 🫢

  • <PATH> β€” only update repositories at these paths, as written in config or expanded (for example ~/src/mise)

🌈 Examples 🌈

Show the Git commands that would run:

mise bootstrap repos update --dry-run

Update one repository:

mise bootstrap repos update ~/src/mise

πŸ” MISE BOOTSTRAP SECRETS πŸ”

Inspect bootstrap secret inputs without revealing their values β€” we're nosy but polite πŸ™ˆ

Secret inputs are values declared in [bootstrap.secrets] that file and dotfile templates read with secret(). mise reads them from environment variables, or prompts for missing ones with --prompt-secrets.

Usage: mise bootstrap secrets [OPTIONS] <COMMAND>

✨ Options ✨

  • -h, --help β€” print help

πŸ•΅οΈ MISE BOOTSTRAP SECRETS STATUS πŸ•΅οΈ

Show whether declared bootstrap secret inputs are actually available πŸ‘‘

Usage: mise bootstrap secrets status [OPTIONS]

✨ Options ✨

  • -J, --json β€” output in JSON format
  • --missing β€” exit with status 1 if a declared secret input is unset, empty, or not valid Unicode 😭
  • -h, --help β€” print help

πŸ› οΈ MISE BOOTSTRAP SERVICES πŸ› οΈ

Manage services from [bootstrap.services] β€” the little guys that just run things for you πŸ’…

System-scope entries β€” the default for entries without builtin β€” start, stop, enable, disable, or mask systemd units that already exist on Linux.

User-scope entries (scope = "user", or any builtin service) define a service for the current user on every platform: a systemd user unit on Linux, a LaunchAgent on macOS, or a Scheduled Task on Windows πŸ–₯️🍎πŸͺŸ

For options that only one platform has, see mise bootstrap linux systemd-units and mise bootstrap macos launchd-agents.

Usage: mise bootstrap services [OPTIONS] <COMMAND>

✨ Options ✨

  • -h, --help β€” print help

🌈 Examples 🌈

Show the state of every declared service:

mise bootstrap services status

Show what would change:

mise bootstrap services apply --dry-run

Uninstall a user service:

mise bootstrap services remove mise-history

⚑ MISE BOOTSTRAP SERVICES APPLY ⚑

Apply the service state declared in [bootstrap.services] β€” make it match, periodt ✨

Usage: mise bootstrap services apply [OPTIONS]

✨ Options ✨

  • -n, --dry-run β€” show what would change without changing anything
  • -y, --yes β€” skip the confirmation prompt
  • -h, --help β€” print help

πŸ—‘οΈ MISE BOOTSTRAP SERVICES REMOVE πŸ—‘οΈ

Uninstall a user-scope service β€” breaking up is hard, but it's for the best 😭

Removing a user-scope entry from config does not uninstall its systemd unit, LaunchAgent, or Scheduled Task. Use this command to uninstall it, whether or not it is still declared. If the entry is still declared, the next mise bootstrap installs it again (it literally cannot let go πŸ’€).

It removes the dev.mise.NAME.service unit or dev.mise.NAME.plist agent, so it also removes one that [bootstrap.linux.systemd.units] or [bootstrap.macos.launchd.agents] wrote under that name. It does not remove .timer units. ⏰

Usage: mise bootstrap services remove [OPTIONS] <NAME>

✨ Options ✨

  • -n, --dry-run β€” show what would be removed without removing it
  • -h, --help β€” print help

🫢 Arguments 🫢

  • <NAME> β€” name of the installed user service

🌈 Examples 🌈

Preview uninstalling the user service named mise-history:

mise bootstrap services remove mise-history --dry-run

πŸ“Š MISE BOOTSTRAP SERVICES STATUS πŸ“Š

Show the state of services from [bootstrap.services] β€” vibe check on every single one πŸ¦‹

Usage: mise bootstrap services status [OPTIONS]

✨ Options ✨

  • -J, --json β€” output in JSON format
  • --missing β€” exit with status 1 if any service differs from the config (all are still listed)
  • -h, --help β€” print help

πŸ‘‘ MISE BOOTSTRAP STATUS πŸ‘‘

Show the state of every configured bootstrap part β€” the full main-character tour 🌈

It lists secret inputs, packages, accounts, files and directories, services, the firewall, Compose projects, repositories, dotfiles, shell activation, macOS defaults, LaunchAgents, systemd user units, the login shell, [tools], and the system dependencies of those tools β€” all without changing anything.

⚠️ Careful bestie: checking dotfiles can render trusted templates, which may run exec(). So it's not purely a look-only situation πŸ™ˆ

--missing exits with status 1 if anything differs from the config; it still lists every entry.

Usage: mise bootstrap status [OPTIONS]

✨ Options ✨

  • -J, --json β€” output in JSON format
  • --missing β€” exit with status 1 if anything differs from the config (all entries are still listed)
  • --prompt-secrets β€” prompt securely for missing bootstrap secret inputs πŸ”
  • -h, --help β€” print help

🌈 Examples 🌈

List every configured part and its state:

mise bootstrap status

Exit with status 1 if anything differs from the config:

mise bootstrap status --missing

Print the state as JSON:

mise bootstrap status --json

🧹 MISE BOOTSTRAP UNAPPLY 🧹

Remove what a config environment's bootstrap sections created β€” the ultimate undo button, lowkey iconic β†©οΈβœ¨

Removes the files, directories, user services, systemd user units, and dotfile entries and edits that the named environments declare. Each named environment's config is loaded for this command even when -E or MISE_ENV does not select it.

mise plans the removal from the current config, not from a record of past runs, so keep the environment's config files until cleanup is done. Anything another selected config still declares is kept, and so is anything changed since it was applied β€” unless you pass --force. A directory is removed only if it is empty afterward. Dotfile sources and config entries are left in place.

It asks before removing anything unless --yes, MISE_YES, or the yes setting is set, and it fails when there is no terminal to ask. mise turns on the yes setting when CI is set.

πŸ’€ Heads up: packages, repositories, and Compose projects are not removed; the output says how to clean them up. Accounts, system services, the firewall, and other sections are left alone.
Usage: mise bootstrap unapply [OPTIONS] <ENV> ...

✨ Options ✨

  • -f, --force β€” remove targets that changed since they were applied
  • -n, --dry-run β€” show what would be removed without removing anything
  • -y, --yes β€” skip the confirmation prompt
  • --prompt-secrets β€” prompt securely for missing bootstrap secret inputs
  • -h, --help β€” print help

🫢 Arguments 🫢

  • <ENV> β€” config environments whose resources should be removed

🌈 Examples 🌈

Preview what removing the ssh environment's resources would do:

mise bootstrap unapply ssh --dry-run

Remove them after a confirmation prompt:

mise bootstrap unapply ssh

Remove the resources of two environments without a prompt:

mise bootstrap unapply ssh gpg --yes

🐚 MISE BOOTSTRAP USER 🐚

Manage your login shell from [bootstrap.user] β€” glow-up for your terminal era ✨

Run it as the user whose shell should change. The new shell applies to future logins, not to the shell running this command (no take-backs mid-session, sorry bestie πŸ™ˆ).

Usage: mise bootstrap user [OPTIONS] <COMMAND>

✨ Options ✨

  • -h, --help β€” print help

🌟 MISE BOOTSTRAP USER APPLY 🌟

Set your login shell from [bootstrap.user] β€” new shell, who dis πŸ’…

Usage: mise bootstrap user apply [OPTIONS]

✨ Options ✨

  • -n, --dry-run β€” show what would change without changing anything
  • -y, --yes β€” skip the confirmation prompt
  • -h, --help β€” print help

πŸ” MISE BOOTSTRAP USER STATUS πŸ”

Show whether your login shell matches [bootstrap.user] β€” the ultimate "do I even go here" check 🫢

Usage: mise bootstrap user status [OPTIONS]

✨ Options ✨

  • -J, --json β€” output in JSON format
  • --missing β€” exit with status 1 if your login shell differs from the config
  • -h, --help β€” print help

πŸŽ€ MISE CACHE πŸŽ€

Manage the mise cache β€” the closet where mise keeps stuff it can always re-buy πŸ›οΈ

The cache holds data mise can fetch or rebuild again, such as version lists and release metadata. With no subcommand, it prints the cache directory, like mise cache path. See https://mise.jdx.dev/cache-behavior.html.

Usage: mise cache [OPTIONS] [COMMAND]

✨ Options ✨

  • -h, --help β€” print help

🧼 MISE CACHE CLEAR 🧼

Delete cached data β€” spring cleaning arc, we love to see it 🌸

With no arguments, it deletes the whole cache directory, the cached environment, and every task's cached artifacts. With TOOL arguments, it deletes only the cached data of those tools, such as their version lists. With --task, it deletes only that task's cached artifacts.

🫢 Good news: installed tools are not removed; mise downloads or rebuilds what it needs again.
Usage: mise cache clear [OPTIONS] [<TOOL>] ...

✨ Options ✨

  • --outdate β€” mark all cache files as old πŸ‘΅
  • --task <TASK> β€” [experimental] clear task artifact cache entries for a task name or pattern
  • -h, --help β€” print help

🫢 Arguments 🫢

  • <TOOL> β€” only clear the cache of these tools, such as node

🌈 Examples 🌈

Clear the whole cache:

mise cache clear

Refresh node's version list:

mise cache clear node

[experimental] Forget the build task's cached artifacts:

mise cache clear --task build

πŸ“ MISE CACHE PATH πŸ“

Print the cache directory path β€” where the magic lives, iykyk ✨

Usage: mise cache path [OPTIONS]

✨ Options ✨

  • -h, --help β€” print help

🧽 MISE CACHE PRUNE 🧽

Remove cache files that have not been accessed recently β€” if you haven't texted it back in a while, it's gone πŸ’€

Removes cache files not accessed within the cache_prune_age setting. Set it to 0s to keep cache files indefinitely (hoarder mode, valid 🫢). mise also prunes the cache now and then on its own.

Usage: mise cache prune [OPTIONS] [<TOOL>] ...

✨ Options ✨

  • -v, --verbose β€” show pruned files
  • --dry-run β€” show what would be pruned without deleting anything πŸ‘€
  • -h, --help β€” print help

🫢 Arguments 🫢

  • <TOOL> β€” only prune the cache of these tools, such as node

🌈 Examples 🌈

List what would be removed:

mise cache prune --dry-run

πŸ”¬ MISE CACHE TASK πŸ”¬

[experimental] Inspect artifact cache entries for a task β€” forensic girlie hours πŸ”βœ¨

Lists the artifact cache entries of the tasks matching TASK with their key, size, run time, last access, and outputs, and marks the entry that matches the task's current inputs. Remove entries with mise cache clear --task TASK. See https://mise.jdx.dev/tasks/caching.html#enable-artifact-caching.

Usage: mise cache task [OPTIONS] <TASK>

✨ Options ✨

  • -J, --json β€” output in JSON format
  • -h, --help β€” print help

🫢 Arguments 🫢

  • <TASK> β€” task name or pattern to inspect

🌈 Examples 🌈

List the build task's cache entries:

mise cache task build

✨ MISE COMPLETION ✨

Generate shell completions, bestie πŸ’–

It prints a completion script for SHELL, or β€” with --install β€” writes it wherever that shell actually loads completions from. The script literally asks mise for candidates as you type, so it also completes your project's task names and tool versions. Slay. See https://mise.jdx.dev/shell-setup.html#autocompletion.

Usage: mise completion [OPTIONS] [<SHELL>]

πŸŽ€ Options πŸŽ€

  • -s, --shell <SHELL> β€” shell type to generate completions for
  • --include-bash-completion-lib β€” no longer has any effect; kept so older setup scripts keep working (legacy vibes only, it does nothing now)
  • --usage β€” also no longer has any effect; kept so older setup scripts keep working
  • --install β€” install the script where this shell looks for it, instead of printing it

Important deets: it writes only the script file, never a shell startup file or PowerShell profile. If your shell needs a one-time setup line, such as zsh's fpath+= or PowerShell's dot-source, mise prints it for you to add. 🫢

  • --force β€” replace a file at the target path that mise did not write
  • --tool <TOOL> β€” generate completions for a tool installed with the packslip: backend

TOOL is the tool or one of its executables; with --install, pass the executable's name. The script matches the version active in the current directory and comes from the most verifiable source its packslip offers: a file the vendor shipped, a script derived from its CLI spec, or a command of the tool's own. With --install, mise writes a small stub that asks mise for the script each time the shell completes the tool, so it follows version changes without being rewritten. Iconic behavior honestly πŸ‘‘

  • -h, --help β€” print help

🌸 Arguments 🌸

  • <SHELL> β€” shell type to generate completions for (required)

πŸ¦‹ Examples πŸ¦‹

Install completions for zsh; bash, fish, and powershell work the same way:

mise completion zsh --install

Print the script to inspect it or save it somewhere else:

mise completion zsh

Install completions for hk, a tool installed with the packslip backend:

mise completion zsh --tool hk --install

πŸ’… MISE CONFIG πŸ’…

Manage config files, periodt.

With no subcommand, it lists the config files mise loads, from lowest to highest precedence, like mise config ls; the flags below apply to that listing. Lowkey the most useful no-args command ever.

Usage: mise config [OPTIONS] [COMMAND]

✨ Options ✨

  • --truncate β€” truncate long terminal output to fit the available width Default: true
  • -J, --json β€” output in JSON format
  • --no-header β€” do not print the table header
  • --tracked-configs β€” list every config file mise has loaded, in any project

mise remembers the config files it loads so mise prune keeps the versions they use. Fr fr, it's keeping receipts 🧾

  • -h, --help β€” print help

🧚 MISE CONFIG EXPLAIN 🧚

Describe each key in a mise TOML file β€” it's giving personal tour guide for your config πŸŽ€

Lists every key the file sets, with its line and what it does, from the same schema editors use to check a config. A key mise does not read is marked, with the known key it most likely meant, and so is a deprecated one. Reads the highest-precedence loaded TOML file by default; select another with --file, --global, or --system.

Usage: mise config explain [OPTIONS] [<KEY>]

🌈 Options 🌈

  • -f, --file, --path <FILE> β€” config file to read, or a directory whose config file to read

Defaults to the highest-precedence loaded TOML file other than the global override files.

  • -g, --global β€” read the global config file
  • --system β€” read the system config file
  • --override β€” read the global override file, config.override.toml
  • -J, --json β€” print the keys as JSON
  • -h, --help β€” print help

πŸ“ Arguments πŸ“

  • <KEY> β€” dotted key path to describe, with the keys under it; omit for the whole file

Quote a key with a dot in its name as TOML does, inside shell quotes: 'tasks."build.sh"'. Unquoted, tasks.build.sh still finds the task build.sh when there is no key build in the way. Iykyk πŸ’«

πŸ’œ Examples πŸ’œ

Describe the keys of the project config:

mise config explain ~/src/app/mise.toml
   1  tools                  dev tools to use
   2  tools.node             a version of the tool, or a table with
its version and options
   4  settings               mise settings
   5  settings.experimantal  not a key mise reads; did you mean
experimental?

Describe only the keys under [tasks]:

mise config explain tasks

🌸 MISE CONFIG GET 🌸

Print a value from one mise TOML file β€” one little peek, no cap πŸ”

Reads the highest-precedence loaded TOML file by default. Select another with --file, --global, or --system. Heads up: this reads stored values, not the merged or template-expanded environment; use mise env for the resolved environment. Two totally different vibes, don't mix them up πŸ’…

Usage: mise config get [OPTIONS] [<KEY>]

✨ Options ✨

  • -f, --file, --path <FILE> β€” config file to read, or a directory whose config file to read

For a directory, mise reads the TOML config file already there, such as .mise.toml, or mise.toml when there is none. Defaults to the highest-precedence loaded TOML file other than the global override files.

  • -g, --global β€” read the global config file
  • --system β€” read the system config file
  • --override β€” read the global override file, config.override.toml
  • -h, --help β€” print help

πŸŽ€ Arguments πŸŽ€

  • <KEY> β€” dotted key path to print, such as tools.python; omit to print the whole file

Quote a key with a dot in its name as TOML does, inside shell quotes: 'tasks."build.sh"'. Unquoted, tasks.build.sh still finds the task build.sh when there is no key build in the way.

πŸ¦‹ Examples πŸ¦‹

Print the python request:

mise config get tools.python
3.13

Print the whole file:

mise config get

πŸ‘‘ MISE CONFIG LS πŸ‘‘

List config files currently in use, from lowest to highest precedence. Later files override earlier ones β€” classic hierarchy moment ✨

Global override files (config.override.toml) rank above all project config and are labeled override. They're the main character of precedence, honestly πŸ’€

Usage: mise config ls [OPTIONS]

🌈 Options 🌈

  • --truncate β€” truncate long terminal output to fit the available width Default: true
  • -J, --json β€” output in JSON format
  • --no-header β€” do not print the table header
  • --tracked-configs β€” list every config file mise has loaded, in any project

mise remembers the config files it loads so mise prune keeps the versions they use. Receipts = kept 🧾

  • -h, --help β€” print help

πŸ“ Examples πŸ“

List the loaded config files and the tools each one requests:

mise config ls
Path                        Tools
~/.config/mise/config.toml  node, python
~/work/api/mise.toml        node, terraform

πŸ”₯ MISE CONFIG SET πŸ”₯

Set a value in one mise TOML file. Write it, don't fight it πŸ’…

Edits the highest-precedence loaded TOML file by default, which may be an environment-specific override. Use --file to select an existing project file, or --global/--system to edit or create those config files.

Ok so this one edits config without installing tools. Use mise use to install and select a version together. For environment variables and settings, mise set and mise settings set are shorter, but they choose their file differently: mise set writes the nearest mise.toml, and mise settings set writes the global config unless you pass --local. Different commands, different file-picking energy, don't @ me 😭

Known settings use their declared type; boolean settings accept true, false, yes, no, 1, and 0. For other keys, true and false become booleans and every other value is stored as a string. Use --type bool to store yes, no, 1 or 0 as a boolean, --type string to store true or false as text, and --type integer for a number. Type safety queen πŸŽ€

Usage: mise config set [OPTIONS] <KEY> [<VALUE>]

✨ Options ✨

  • -f, --file, --path <FILE> β€” config file to edit, or a directory whose config file to edit

For a directory, mise edits the TOML config file already there, such as .mise.toml, or mise.toml when there is none. Defaults to the highest-precedence loaded TOML file other than the global override files.

  • -g, --global β€” edit the global config file
  • --override β€” edit the global override file, config.override.toml
  • --system β€” edit the system config file
  • --append β€” append the value to a list without duplicating an existing entry
  • --remove β€” remove the value from an existing list
  • -t, --type <TYPE> β€” TOML type to store the value as; inferred from the value by default Default: infer
  • -h, --help β€” print help

πŸ¦‹ Arguments πŸ¦‹

  • <KEY> β€” dotted key path to set, such as tools.python

Quote a key with a dot in its name as TOML does, inside shell quotes: 'tasks."build.sh"'. Unquoted, tasks.build.sh still finds the task build.sh when there is no key build in the way.

  • <VALUE> β€” the value to set the key to (optional if provided as KEY=VALUE)

πŸ’œ Examples πŸ’œ

Request python 3.13:

mise config set tools.python 3.13

Set an environment variable:

mise config set env.NODE_ENV production

Settings get their declared type, here an integer:

mise config set settings.jobs 4

List settings take comma-separated values:

mise config set settings.disable_tools node,rust

Add a PATH entry unless it is already there:

mise config set --append env._.path ~/.local/bin

Remove that PATH entry:

mise config set --remove env._.path ~/.local/bin

Edit the global config:

mise config set -g settings.experimental true

🫢 MISE DEACTIVATE 🫢

Print the script to disable mise in the current shell session. The breakup script, but make it reversible πŸ’”βœ¨

In a shell where mise is activated, run mise deactivate: the activation function evaluates the script for you. Calling the executable directly (command mise deactivate) only prints the script, so evaluate it yourself as in the examples below. New shells still activate mise; remove the line from your shell startup file to stop that.

Usage: mise deactivate [OPTIONS]

⭐ Options ⭐

  • -h, --help β€” print help

🌸 Examples 🌸

Turn mise off in an activated shell:

mise deactivate

Bash or Zsh, calling the executable rather than the activation function:

eval "$(command mise deactivate)"

Fish, calling the executable rather than the activation function:

command mise deactivate | source

πŸ’… MISE DAEMONS πŸ’…

okay so this is [experimental] and it's literally how you manage project daemons with pitchfork 🫢 You declare long-running processes in [daemons] β€” either as commands or as service presets like postgres and redis β€” and mise runs them under pitchfork with the project's tools and environment. Requires experimental = true, bestie.

With no subcommand, it lists the project's daemons like mise daemons ls ✨

See https://mise.jdx.dev/daemons.html

Usage:

mise daemons [OPTIONS] [COMMAND]

Options:

  • --json β€” Output in JSON format, including ports, URLs, and data directories πŸ’…
  • -h, --help β€” Print help

Examples:

Start the default group, or every project daemon:

mise daemons start

Show the last 50 lines of api's output:

mise daemons logs api -n 50

Stop every registered project daemon:

mise daemons stop

🫢 MISE DAEMONS PROVIDERS 🫢

[experimental] Manage shared servers from global [daemon_providers] 🌸

A shared server is one PostgreSQL, CockroachDB, or NATS server declared in your global config, with a separate database or account for each checkout that uses it. Not supported on Windows. See https://mise.jdx.dev/daemons/sharing.html#shared-server-providers

Usage:

mise daemons providers [OPTIONS] [COMMAND]

Options:

  • -h, --help β€” Print help

Examples:

List shared servers:

mise daemons providers ls

Start the shared server named local-postgres:

mise daemons providers start local-postgres

πŸ¦‹ MISE DAEMONS PROVIDERS LS πŸ¦‹

[experimental] List shared servers.

Usage:

mise daemons providers ls [OPTIONS]

Options:

  • --json β€” Output in JSON format
  • -h, --help β€” Print help

πŸŽ€ MISE DAEMONS PROVIDERS START πŸŽ€

[experimental] Start shared servers.

Usage:

mise daemons providers start [OPTIONS] [<NAMES>] ...

Options:

  • -h, --help β€” Print help

🌈 MISE DAEMONS PROVIDERS STOP 🌈

[experimental] Stop shared servers (data is kept).

Usage:

mise daemons providers stop [OPTIONS] [<NAMES>] ...

Options:

  • -h, --help β€” Print help

⭐ MISE DAEMONS PROVIDERS RESTART ⭐

[experimental] Restart shared servers with their current configuration.

Usage:

mise daemons providers restart [OPTIONS] [<NAMES>] ...

Options:

  • -h, --help β€” Print help

πŸ”₯ MISE DAEMONS START πŸ”₯

[experimental] Start project daemons and the daemons they depend on 🫢

It installs missing tools and registers the project's daemons with pitchfork, then starts the selected daemons and waits until they are ready. With no names, it starts the default group from [daemon_groups] when the project declares one; otherwise it starts every project daemon.

Select daemons by name (api or a qualified ID such as shop/api), by group with --group NAME, or all of them with --all. --all covers every daemon in this project, including those the default group leaves out; unlike pitchfork's own --all, it never reaches other projects, and it cannot be combined with names or --group. Other flags pass through to pitchfork start ✨

Usage:

mise daemons start [OPTIONS] [<ARGS>] ...

Options:

  • -h, --help β€” Print help

Arguments:

  • <ARGS> β€” Daemon names (short, such as api, or qualified, such as shop/api), --group NAME, and flags passed to pitchfork

Examples:

Start the default group, or every daemon:

mise daemons start

Start api and the daemons it depends on:

mise daemons start api

Start a group declared in [daemon_groups]:

mise daemons start --group backend

🧚 MISE DAEMONS REGISTER 🧚

[experimental] Register project daemons for on-demand startup πŸ’–

It installs missing tools, validates daemon definitions and dependencies, and registers the generated configuration with pitchfork without starting anything. Covers every project daemon, including imported dependencies and daemons outside the default group. Daemons that are already running keep running, no cap.

A running pitchfork supervisor with its proxy enabled can then start a registered HTTP daemon when a request reaches its hostname. See https://mise.jdx.dev/daemons/worktrees.html#register-for-on-demand-startup

Usage:

mise daemons register [OPTIONS]

Options:

  • -h, --help β€” Print help

Examples:

Register every project daemon:

mise daemons register

πŸ“ MISE DAEMONS STOP πŸ“

[experimental] Stop project daemons.

With no names, it stops every daemon the project has registered, including daemons a removed group started. Data is kept. Select daemons as mise daemons start does: by name, with --group NAME, or with --all. Other flags pass through to pitchfork stop 🫢

Usage:

mise daemons stop [OPTIONS] [<ARGS>] ...

Options:

  • -h, --help β€” Print help

Arguments:

  • <ARGS> β€” Daemon names (short, such as api, or qualified, such as shop/api), --group NAME, and flags passed to pitchfork

Examples:

Stop one daemon:

mise daemons stop postgres

πŸ’œ MISE DAEMONS RESTART πŸ’œ

[experimental] Restart project daemons.

It installs missing tools first and selects daemons as mise daemons start does: with no names, the default group when the project declares one; otherwise every project daemon. A changed daemon declaration takes effect on restart. Other flags pass through to pitchfork restart πŸ”₯

Usage:

mise daemons restart [OPTIONS] [<ARGS>] ...

Options:

  • -h, --help β€” Print help

Arguments:

  • <ARGS> β€” Daemon names (short, such as api, or qualified, such as shop/api), --group NAME, and flags passed to pitchfork

Examples:

Restart api with its current declaration:

mise daemons restart api

🌸 MISE DAEMONS LS 🌸

[experimental] List project daemons.

It shows each daemon's ID, status, and source without starting a supervisor or registering configuration ✨

Usage:

mise daemons ls [OPTIONS]

Options:

  • --json β€” Output in JSON format, including ports, URLs, and data directories
  • -h, --help β€” Print help

Examples:

Include ports, URLs, and data directories:

mise daemons ls --json

πŸ¦‹ MISE DAEMONS URLS πŸ¦‹

[experimental] Show each daemon's URL and port.

It lists every project daemon with its proxy hostname URL, the port it binds, its proxy mode, and its status. A daemon's hostname does not change when its port does, so an HTTP service can be addressed by URL while concurrent checkouts keep separate ports. A daemon with no port, or with proxy = false, gets no hostname and is listed without a URL. Each project's table is followed by its project page URL and, in a linked Git worktree, its stack page URL.

See https://mise.jdx.dev/daemons/worktrees.html#stable-urls-per-worktree

Usage:

mise daemons urls [OPTIONS]

Options:

  • --json β€” Output in JSON format, including ports, URLs, and data directories
  • -h, --help β€” Print help

Examples:

Show the URLs for this checkout:

mise daemons urls

πŸŽ€ MISE DAEMONS LOGS πŸŽ€

[experimental] Show the output of project daemons.

Requires a running pitchfork supervisor. With no names, it shows every daemon the project has registered. Flags such as -n, --since, and --grep pass through to pitchfork logs πŸ’…

Usage:

mise daemons logs [OPTIONS] [<ARGS>] ...

Options:

  • -h, --help β€” Print help

Arguments:

  • <ARGS> β€” Daemon names (short, such as api, or qualified, such as shop/api), --group NAME, and flags passed to pitchfork

Examples:

Show the last 50 lines of api's output:

mise daemons logs api -n 50

Show the last five minutes of output:

mise daemons logs --since 5min

⭐ MISE DAEMONS STATUS ⭐

[experimental] Show the status of project daemons.

It prints pitchfork's status for each selected daemon. With no names, it covers every daemon the project has registered 🫢

Usage:

mise daemons status [OPTIONS] [<ARGS>] ...

Options:

  • -h, --help β€” Print help

Arguments:

  • <ARGS> β€” Daemon names (short, such as api, or qualified, such as shop/api), --group NAME, and flags passed to pitchfork

Examples:

Show the status of api:

mise daemons status api

🌈 MISE DAEMONS TUI 🌈

[experimental] Open the pitchfork dashboard.

Requires a running pitchfork supervisor. Takes pitchfork tui flags, not daemon names πŸ‘‘

Usage:

mise daemons tui [OPTIONS] [<ARGS>] ...

Options:

  • -h, --help β€” Print help

Arguments:

  • <ARGS> β€” Flags passed to pitchfork tui

🧹 MISE DAEMONS PRUNE 🧹

[experimental] Remove daemon state left by deleted projects.

It scans $MISE_STATE_DIR/daemons/ for state that belongs to deleted projects, including removed Git worktrees. For each one, it stops its daemons, unregisters its configuration, and deletes its state and data. Existing projects are not touched.

Use --dry-run to preview the paths and sizes.

Removal cannot be undone and asks for confirmation. Pass the global --yes flag to prune without a prompt; entries that may belong to an unmounted volume or a deleted symlink are then skipped and need a separate interactive confirmation.

pitchfork must be available. State is kept when mise cannot confirm that the daemons have stopped or cannot unregister their configuration 😭

Usage:

mise daemons prune [OPTIONS]

Options:

  • -n, --dry-run β€” Show what would be removed without deleting anything
  • -h, --help β€” Print help

Examples:

Preview what would be removed:

mise daemons prune --dry-run

Review the list and confirm removal:

mise daemons prune

πŸ’– MISE DOTFILES πŸ’–

Deploy, track, and sync dotfiles πŸŽ€

A [dotfiles] entry deploys a file (from a source with symlink, symlink-each, copy, or template, or from inline content), removes one (mode = "absent"), sets an existing path's permissions, edits part of a file, or tracks a live file where it is (mode = "track"). mise saves tracked files to a local Git history that you can browse and roll back, and syncs it with other machines through an origin repository. mise dot is a shorter alias, iykyk.

Deploy files with add, apply, diff, status, and unapply. Track and restore files with track, save, history, rollback, and undo. Sync them with origin, sync, and pull ✨

See https://mise.jdx.dev/dotfiles.html and https://mise.jdx.dev/dotfiles/history.html

Usage:

mise dotfiles [OPTIONS] <COMMAND>

Options:

  • --local β€” Work on this machine's local-only history (mode = "track-local"), which is never shared
  • -h, --help β€” Print help

Examples:

Start managing ~/.zshrc from your dotfiles directory:

mise dot add ~/.zshrc

Deploy every [dotfiles] entry:

mise dot apply

Show the state of your dotfiles and their history:

mise dot status

Save the history of a directory in place:

mise dot track ~/.config/nvim

List saved checkpoints:

mise dot history

✨ MISE DOTFILES ADD ✨

Start deploying a file, or copy its edits back to the source πŸ‘‘

So here's the vibe: if your target isn't managed yet, mise saves its contents as a source under dotfiles.root (or wherever you point it with --source), adds a [dotfiles] entry, and then applies it β€” unless you hit it with --no-apply. If the target is already managed, no drama, it just updates the source from the live file. And --dry-run gives you the sneak peek: it previews the source and config changes without writing a single thing πŸ’…

One little plot twist: a target that lives inside the tree of a dotfile group gets captured into that group's source instead, and it does not get a new [dotfiles] entry. Which group? The deepest group whose target contains it β€” or the one you name with --group. iykyk πŸ¦‹

Usage: mise dotfiles add [OPTIONS] [<TARGET>] ...

πŸŽ€ Options πŸŽ€

  • --changed β€” update the sources of every changed file that's managed in copy mode ✨
  • -f, --force β€” overwrite existing sources without prompting (no "are you sure" energy, we're just doing it) πŸ’€
  • -g, --global β€” write to the global config (this is the default, bestie)

New entries go to the write_targets.dotfiles file when that setting is set πŸ‘€

  • -l, --local β€” write to the project config instead of the global config 🏠
  • -m, --mode <MODE> β€” the mode for a target that isn't managed yet: symlink, symlink-each, copy, or template (default: whatever the dotfiles.default_mode setting says) 🌸

And if the target is already managed? It keeps its mode. Periodt.

  • -n, --dry-run β€” print the config and source changes without writing anything πŸ™ˆ
  • --no-apply β€” add the entry but don't apply it
  • -p, --path <PATH> β€” write to this config file or directory
  • -s, --source <PATH> β€” source path to use for a single target

A relative path starts from the current directory. The entry records it relative to the config file's directory when it lies inside it, and as an absolute path otherwise. Fr fr, it depends on where it lands πŸ“

  • -y, --yes β€” skip the confirmation prompt ⚑
  • --prompt-secrets β€” prompt for [bootstrap.secrets] values that templates need and the environment does not set πŸ”
  • --group <NAME> β€” capture into the tree of this dotfile group 🧚
  • -h, --help β€” print help

🌈 Arguments 🌈

  • <TARGET> β€” targets to add or update

πŸ’– Examples πŸ’–

Start managing ~/.zshrc from your dotfiles directory:

mise dot add ~/.zshrc

Copy the file into place instead of symlinking it:

mise dot add --mode copy ~/.config/starship.toml

Choose where the source is stored:

mise dot add --source dotfiles/gitconfig ~/.gitconfig

Capture the file into a dotfile group's tree:

mise dot add --group home ~/.config/starship.toml

Copy edits of every changed copy-mode file back to its source:

mise dot add --changed

πŸ¦‹ MISE DOTFILES APPLY πŸ¦‹

Link, copy, and render [dotfiles] entries into place ✨

apply does the actual deploying: it applies the whole-file entries and the edits that aren't in their desired state. Whole-file entries can symlink, copy, render templates, write inline content, set permissions, or remove targets declared mode = "absent". Edit entries, meanwhile, manage a marker-delimited block, a single line, or merged keys in a file that mise doesn't otherwise own πŸŽ€

Here's the iconic part: entries that deploy mise's own configuration get applied first, and then the configuration is read again β€” so a rule that the new file adds applies in that same run. Chef's kiss πŸ‘‘

Also important, ngl: apply works from the files on this machine. It never fetches or pulls. To bring in changes from other machines, you run mise dot sync, then mise dot pull, then mise dot apply β€” in that order, bestie πŸ”

The pre-dotfiles and post-dotfiles bootstrap hooks run before and after the apply (and with --dry-run they're printed, not run 🌸), and the matching [history.reload] commands run for the targets it wrote.

And with --prune, it also removes files that dotfile groups deployed but no active entry deploys now: files of a group that's no longer selected or declared, plus files a group stopped deploying because of a new exclude or a deleted source. Cleanup szn 🧹

Usage: mise dotfiles apply [OPTIONS] [<TARGET>] ...

πŸŽ€ Options πŸŽ€

  • -f, --force β€” overwrite existing files that conflict with whole-file dotfile entries πŸ’₯
  • -n, --dry-run β€” print the actions that would run without writing anything πŸ™ˆ
  • -y, --yes β€” skip the confirmation prompt
  • --prune β€” also remove files that dotfile groups deployed but no active entry deploys now
  • --prompt-secrets β€” prompt for [bootstrap.secrets] values that templates need and the environment does not set πŸ”
  • -h, --help β€” print help

🌈 Arguments 🌈

  • <TARGET> β€” only apply these targets

πŸ’– Examples πŸ’–

Deploy every entry that's out of date:

mise dot apply

Print what would change:

mise dot apply --dry-run

Also remove files left by dotfile groups:

mise dot apply --prune

Overwrite conflicting files without prompting:

mise dot apply --force --yes

🫢 MISE DOTFILES CAPTURE 🫢

Run a command and save tracked files before and after it πŸ“Έ

This one's lowkey underrated. capture runs your command with your terminal and environment, and it saves a checkpoint before and after it β€” even when the command fails or changes nothing β€” so mise dot undo can reverse whatever it did to your tracked files. Edits you make while it's running are part of the same operation, all one vibe πŸ’…

Real talk though: packages, services, and other system changes are not recorded and cannot be undone. Only your tracked files. And if saving fails, mise warns you and still exits with the command's status. ⚠️
Usage: mise dotfiles capture [OPTIONS] <COMMAND> ...

πŸŽ€ Options πŸŽ€

  • --label <LABEL> β€” describe this operation in history 🏷️
  • -h, --help β€” print help

🌈 Arguments 🌈

  • <COMMAND> β€” command and arguments to run, after --

πŸ’– Examples πŸ’–

Record what an upgrade changes:

mise dot capture -- brew upgrade

Label the operation in history:

mise dot capture --label "theme switch" -- ./switch-theme.sh

πŸ’€ MISE DOTFILES CONFLICTS πŸ’€

Compare both sides of a sync conflict πŸ‘€

When sync goes sideways, this is your referee. It prints a unified diff from this machine's saved version to the version fetched from the origin. --difftool opens the comparison in Git's configured diff tool β€” and when diff.tool is unset, Git falls back to merge.tool. Good to know, fr fr πŸ¦‹

Neither side gets changed by this command. It's purely a look, don't touch situation. Resolve things with mise dot pull --take-remote or --keep-local. πŸ‘‘
Usage: mise dotfiles conflicts [OPTIONS] [<PATH>] ...

πŸŽ€ Options πŸŽ€

  • --difftool β€” open the comparison in Git's configured diff or merge tool πŸ› οΈ
  • --tool <TOOL> β€” use this Git diff tool instead of the configured default
  • -h, --help β€” print help

🌈 Arguments 🌈

  • <PATH> β€” only inspect these conflicted paths

πŸ’– Examples πŸ’–

Show every conflict:

mise dot conflicts

Show one conflicted file:

mise dot conflicts ~/.zshrc

Open the comparison in Git's diff tool:

mise dot conflicts --difftool ~/.zshrc

Use a specific diff tool:

mise dot conflicts --difftool --tool meld ~/.zshrc

🌸 MISE DOTFILES DIFF 🌸

Show what mise dot apply would change ✨

It prints a unified diff for every whole-file entry and edit that mise dot apply would change. Spoiler alert: templates get rendered first, so trusted template functions may run πŸ‘€ β€” that's a real caveat, not a vibe.

And a lil note: tracked entries have nothing to apply. To see their unsaved changes, use mise dot history diff instead πŸŽ€

Usage: mise dotfiles diff [OPTIONS] [<TARGET>] ...

πŸŽ€ Options πŸŽ€

  • --prompt-secrets β€” prompt for [bootstrap.secrets] values that templates need and the environment does not set πŸ”
  • -h, --help β€” print help

🌈 Arguments 🌈

  • <TARGET> β€” only show these targets

πŸ’– Examples πŸ’–

Show every pending change:

mise dot diff

Show the change for one target:

mise dot diff ~/.zshrc

⭐ MISE DOTFILES EDIT ⭐

Open a dotfile's source in your editor ✍️

It opens the file that defines TARGET in $VISUAL or $EDITOR. Which file, you ask? Depends on the entry, bestie:

  • the source, for symlink, copy, and template entries
  • the file itself, for tracked and permissions-only entries
  • the declaring config, for inline content, absent entries, and edits without a source file

And a fnox entry is edited with fnox edit --file, which stores the change in fnox 🧚

Now, if the target is unmanaged, it first gets added to the global [dotfiles] β€” exactly like mise dot add --no-apply would add it β€” after a prompt that --yes skips. Without a terminal, an unmanaged target needs --yes. No terminal, no prompt, no guessing. πŸ’…

And with --apply, it applies the target after the editor exits. Slay.

Usage: mise dotfiles edit [OPTIONS] <TARGET>

πŸŽ€ Options πŸŽ€

  • --apply β€” apply this target after the editor exits πŸš€
  • -m, --mode <MODE> β€” mode to use if the target is not managed yet: symlink, symlink-each, copy, or template (default: the dotfiles.default_mode setting)
  • -s, --source <PATH> β€” source path to use if the target is not yet managed
  • -y, --yes β€” skip the confirmation prompt when adding an unmanaged target
  • --group <NAME> β€” dotfile group whose tree holds the target, when several groups deploy into its directory
  • --prompt-secrets β€” prompt for [bootstrap.secrets] values that templates need and the environment does not set πŸ”
  • -h, --help β€” print help

🌈 Arguments 🌈

  • <TARGET> β€” target to edit

πŸ’– Examples πŸ’–

Edit the source of ~/.zshrc:

mise dot edit ~/.zshrc

Edit the source, then deploy it:

mise dot edit --apply ~/.config/starship.toml

πŸŽ€ MISE DOTFILES EXCLUDE πŸŽ€

Never save paths matching a glob 🚫

This adds a glob to [history] exclude in the global config, and the rule applies to every tracked path. Quote the glob so your shell doesn't expand it β€” for real, quote it πŸ™ˆ

Use exclusions for logs, caches, databases, and session state. For files you want to save only on demand, track them with mise dot track --no-autosave instead. And to limit what one tracked directory saves, edit the exclude or include list of its [dotfiles] entry. Different tool, different job πŸ’…

Usage: mise dotfiles exclude [OPTIONS] <GLOB>

πŸŽ€ Options πŸŽ€

  • -h, --help β€” print help

🌈 Arguments 🌈

  • <GLOB> β€” a glob such as ~/.config/hypr/plugins/**

πŸ’– Examples πŸ’–

Never save Codex session logs:

mise dot exclude '~/.codex/sessions/**'

MISE DOTFILES HISTORY

Okay bestie, listen β€” every [dotfiles] entry you've got with mode = "track" gets a checkpoint, which is just a saved version of the whole thing. A lil time capsule, if you will. πŸ“Έ

What triggers one? mise dot save, the watcher, and literally every command that changes tracked files (like mise bootstrap, mise dot apply, rollback, pull, and undo) β€” yeah, all of them record a checkpoint. And heads up: checkpoints hold file contents only, not packages or services. Periodt. Files deployed in other modes are saved only if you also track them, so if you want them in the history you gotta opt in, iykyk.

With no subcommand, it just lists checkpoints newest first. Main character behaviour honestly. πŸ’…

See https://mise.jdx.dev/dotfiles/history.html πŸ¦‹

Usage: mise dotfiles history [OPTIONS] [COMMAND]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format, for the data girlies πŸ“Š
  • -n, --limit <LIMIT> β€” show at most this many checkpoints (0 for all). Default: 20
  • --path <PATH> β€” only checkpoints where this path (or something under it) changed
  • --trigger <TRIGGER> β€” only checkpoints with this trigger, such as edit, save, agent, bootstrap, apply, rollback, or undo
  • --label <LABEL> β€” only checkpoints with this label, like little sticky notes for your saves πŸŽ€
  • --pending β€” only checkpoints recorded by operations that did not finish (the unfinished-girlboss filter πŸ’€)
  • -h, --help β€” print help

Quick trigger lore, since it's lowkey confusing:

bootstrap covers mise bootstrap, its packages commands, and mise dot add, apply, edit, and unapply. apply covers incoming changes written by mise dot pull or the watcher. ✨

🌸 EXAMPLES 🌸

List recent checkpoints:

mise dot history

List checkpoints that changed one file:

mise dot history --path ~/.config/hypr/bindings.lua

List the last five checkpoints from mise bootstrap or mise dot apply:

mise dot history --trigger bootstrap -n 5

Show the newest checkpoint:

mise dot history show latest

Show unsaved changes:

mise dot history diff

MISE DOTFILES HISTORY DESCRIBE

Giving a checkpoint a lil name tag so future-you knows what was going on. 🏷️ Set the description of a checkpoint.

Usage: mise dotfiles history describe [OPTIONS] <REF> <TEXT>

✨ OPTIONS ✨

  • -h, --help β€” print help

Arguments

  • <REF> β€” numeric checkpoint ID, latest, latest~N, or commit:<sha>
  • <TEXT> β€” the new description

🌸 EXAMPLES 🌸

Describe the newest checkpoint:

mise dot history describe latest "before the theme change"

MISE DOTFILES HISTORY DIFF

The comparison station. πŸ’… Compare checkpoints, or compare your files against one.

With no arguments: shows unsaved changes β€” the files on disk against the latest checkpoint. With one reference: shows what that checkpoint changed since the one before it. With two: compares them, head to head, no notes. πŸ”₯

Usage: mise dotfiles history diff [OPTIONS] [<A>] [<B>]

✨ OPTIONS ✨

  • --operation β€” compare an operation with the checkpoint it saved before it ran
  • -p, --patch β€” print the full patch instead of a per-file summary
  • --path <PATH> β€” restrict to one path (a file or a directory)
  • --exit-code β€” exit 1 when the two sides differ
  • -h, --help β€” print help

More on --operation, because it's got rules: with no reference, it uses the newest operation, ignoring later saves. With one reference, it uses that operation. And it fails if the operation's earlier checkpoint is unavailable β€” it will not go compare some unrelated save instead. Respect the boundaries fr fr. 🫢

Arguments

  • <A> β€” numeric checkpoint ID, latest, latest~N, or commit:<sha>
  • <B> β€” compare A with this checkpoint instead of its predecessor

🌸 EXAMPLES 🌸

Show unsaved changes:

mise dot history diff

Show what checkpoint 12 changed:

mise dot history diff 12

Print the full patch between two checkpoints:

mise dot history diff 11 12 --patch

Show what the newest operation changed:

mise dot history diff --operation

MISE DOTFILES HISTORY LS

Same energy as the bare history β€” list checkpoints, newest first. πŸ‘‘

Usage: mise dotfiles history ls [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format
  • -n, --limit <LIMIT> β€” show at most this many checkpoints (0 for all). Default: 20
  • --path <PATH> β€” only checkpoints where this path (or something under it) changed
  • --trigger <TRIGGER> β€” only checkpoints with this trigger, such as edit, save, agent, bootstrap, apply, rollback, or undo
  • --label <LABEL> β€” only checkpoints with this label
  • --pending β€” only checkpoints recorded by operations that did not finish
  • -h, --help β€” print help

Trigger recap, one more time for the people in the back πŸ“£: bootstrap covers mise bootstrap, its packages commands, and mise dot add, apply, edit, and unapply. apply covers incoming changes written by mise dot pull or the watcher.

🌸 EXAMPLES 🌸

List every checkpoint:

mise dot history ls -n 0

List operations that did not finish:

mise dot history ls --pending

MISE DOTFILES HISTORY PURGE

⚠️ Okay this one is the serious one. Read it twice. ⚠️

Erase a path's saved versions from history. 🧹 This rewrites the history without the path β€” the use case is a file you tracked by mistake that holds a secret. And ngl, untrack, rollback, and undo do not help here: they only add checkpoints. They leave the old versions readable. 😭

Checkpoints that changed only this path are removed. The others stay, with their descriptions, dates, and IDs, minus the path. Clean surgery, basically.

Without --yes, the command lists what would change and asks first. Always let it ask, bestie. πŸ™ˆ

mise never rewrites history that is on the origin: if a saved version of the path was ever published, the command refuses. Straight up. Rotate the secret, then see https://mise.jdx.dev/dotfiles/encryption.html#remove-plaintext-from-history πŸ’œ

Also, this does not stop tracking the path. If the file is still tracked, the next save records its current contents again β€” so run mise dot untrack first (or encrypt it). And stop the watcher service while this runs.

Usage: mise dotfiles history purge [OPTIONS] <PATH> ...

✨ OPTIONS ✨

  • -n, --dry-run β€” show what would change without changing anything (my beloved, the safe option 🫢)
  • -y, --yes β€” rewrite without prompting
  • --backup β€” keep the replaced history in the repository under refs/mise/purge-backup/
  • --keep-objects β€” leave the replaced objects on disk instead of deleting them
  • -h, --help β€” print help
πŸ’€ Real talk on --backup: the backup still holds the content you are erasing. Yeah. Delete it with git update-ref -d once you are sure.

Arguments

  • <PATH> β€” files or directories to erase from history

🌸 EXAMPLES 🌸

List the checkpoints that hold the file:

mise dot history purge ~/.aws/credentials --dry-run

Erase every saved version of the file:

mise dot history purge ~/.aws/credentials --yes

MISE DOTFILES HISTORY SHOW

The full tour of a single checkpoint: its trigger, changes, and operation journal. πŸ”

It prints the checkpoint's trigger, description, time, and machine, the files that changed since the previous checkpoint, and the tracked entries it covers. And for a checkpoint that an operation recorded? It also prints the operation's journal of the files it wrote. Receipts. 🧾

Usage: mise dotfiles history show [OPTIONS] [<REF>]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format
  • --files β€” list every file in the snapshot
  • --path <PATH> β€” resolve latest~N among the checkpoints where this path changed
  • -h, --help β€” print help

Arguments

  • <REF> β€” numeric checkpoint ID, latest (the default), latest~N, or commit:<sha>

🌸 EXAMPLES 🌸

Show the newest checkpoint:

mise dot history show

List every file in an older checkpoint:

mise dot history show latest~2 --files

MISE DOTFILES INCLUDE

Un-exclude something. 🩹 Stop excluding paths matching a glob.

It removes a glob that mise dot exclude added to [history] exclude in the global config. Pass the pattern exactly as you excluded it β€” no glow-ups, no edits, character for character. Other matching exclusion rules still apply, so don't assume one removal clears everything.

Heads up though: this command does not edit a tracked directory's include list. That list lives in its [dotfiles] entry β€” go change it there. ✨

Usage: mise dotfiles include [OPTIONS] <GLOB>

✨ OPTIONS ✨

  • -h, --help β€” print help

Arguments

  • <GLOB> β€” the glob as written by mise dot exclude

🌸 EXAMPLES 🌸

Save Codex session logs again:

mise dot include '~/.codex/sessions/**'

MISE DOTFILES NOTIFY

Send a test desktop notification. πŸ”” So cute, so useful.

It checks that history.notify can actually reach you. On macOS the first notification asks for permission, so run this once to get prompted now instead of at the first sync conflict (thank me later 😌).

It fails with the reason when this build or machine cannot show notifications. The reasons, officially: a macOS build that is not mise's signed release (such as Homebrew's), a missing notify-send on Linux, denied permission, or history.notify = false. πŸ’€

And fr, mise notifies you only when a sync conflict pauses syncing. Other problems β€” like a watcher that cannot save β€” appear in mise doctor and mise dot status. Different department, bestie.

Usage: mise dotfiles notify [OPTIONS]

✨ OPTIONS ✨

  • -h, --help β€” print help

🌸 EXAMPLES 🌸

Send a test notification:

mise dot notify

MISE DOTFILES ORIGIN

Show, connect, or disconnect the origin repository. 🌈 The origin is a Git repository that shares the history of your tracked files with your other machines β€” like a group chat but for dotfiles.

With no subcommand, it prints the connected URL, its branch, the config file that declares it, and the sync mode (the history.sync setting). And --remove disconnects β€” but local checkpoints and fetched history stay, no data lost, we don't do that here. 🫢

See https://mise.jdx.dev/dotfiles/sync.html πŸ¦‹

Usage: mise dotfiles origin [OPTIONS] [COMMAND]

✨ OPTIONS ✨

  • --remove β€” disconnect the origin by removing [history.origin]; local checkpoints and fetched history stay
  • -h, --help β€” print help

🌸 EXAMPLES 🌸

Show the connected repository:

mise dot origin

Connect a repository:

mise dot origin set git@github.com:you/dotfiles.git

Disconnect the repository:

mise dot origin --remove

πŸŽ€ MISE DOTFILES ORIGIN SET β€” connect an origin repo πŸŽ€

Okay bestie, this is the moment you link your dotfiles history to an origin repository. Iconic.

Use a private repository: every saved checkpoint gets shared, including the ones you saved before you connected (yes, retroactively, the whole glow-up). mise shows you the sync mode and the tracked files before you confirm, then runs the first sync. She will never replace a repository that has unrelated history, and she flat-out refuses to push older plaintext versions of files you now encrypt. No cap, that's a safety thing.

The connection gets written to [history.origin] in config.local.toml next to your global config, so it stays on this machine. Local girly, machine-specific. πŸ’…

Heads up: the origin holds tracked-file history, not a checkout of your global config. So connect a repository of its own, or a separate branch (--branch) of the one you adopt as global config with mise bootstrap --adopt.

Usage:

mise dotfiles origin set [OPTIONS] <URL>

✨ Options ✨

  • --branch <BRANCH> β€” the branch to sync (default: the repository's default branch). Reconnecting a repository this machine already follows keeps that connection's branch. A repository with no branches gets main, which the first push creates. πŸ¦‹
  • --sync <MODE> β€” how to sync with the repository: sync, fetch-only, or manual. sync pushes saved checkpoints and applies incoming changes automatically. fetch-only fetches automatically and never pushes. manual makes no automatic network calls: mise dot sync pushes and fetches, and mise dot pull applies, only when you run them; local history is still saved automatically. When omitted, mise prompts; with --yes, it uses the history.sync setting.
  • -y, --yes β€” skip the confirmation prompt. Main character energy, no questions asked.
  • -h, --help β€” print help.

🌸 Arguments 🌸

  • <URL> β€” the repository URL (any Git URL; use a private repository).

πŸ’– Examples πŸ’–

Connect and choose a sync mode at the prompt:

mise dot origin set https://github.com/you/dotfiles.git

Connect without automatic network activity:

mise dot origin set git@github.com:you/dotfiles.git --sync manual

🫢 MISE DOTFILES PATHS β€” list tracked paths & how they're saved 🫢

This one's the receipts of your setup. It shows each tracked entry with the config file that declares it, whether it saves automatically, and how many files it covers. Entries mise can't save get listed as invalid, omitted, or incomplete, so you can literally see what's not protected. Vibe check on your own dotfiles, basically. ✨

Usage:

mise dotfiles paths [OPTIONS]

✨ Options ✨

  • -J, --json β€” output in JSON format. For the data girlies.
  • --preview <PATH> β€” list the files that tracking this path would save, without tracking it. A little sneak peek, no commitment. πŸ™ˆ
  • --noisy β€” list the paths the watcher found changing constantly and saves less often.
  • -h, --help β€” print help.

πŸ’– Examples πŸ’–

List tracked paths:

mise dot paths

List the files tracking ~/.codex would save:

mise dot paths --preview ~/.codex

List files the watcher saves less often:

mise dot paths --noisy

πŸ¦‹ MISE DOTFILES PULL β€” write fetched changes from other machines to tracked files πŸ¦‹

Okay so pull writes the changes that the last mise dot sync fetched from your other machines. (mise dot apply deploys your own [dotfiles] entries; pull writes what other machines pushed. Two different jobs, don't mix them up bestie. πŸ’…)

pull restores tracked paths, including tracked symlinks, but never deploys copy, symlink, or template entries: when a tracked file is the source of one, pull updates the source, and mise dot apply then writes the target your application reads. mise saves a checkpoint first, so mise dot undo reverses the whole pull, and runs the matching [history.reload] commands after writing. Clean, reversible, gorgeous.

A pull applies every incoming change together, including config files and the files they reference; it does not take paths. Nothing is written if an incoming config file doesn't parse, a file has unsaved local edits, your own checkout has staged Git changes, or a file changed on both sides. 🫠

A file that changed on both sides is a conflict: compare the two versions with mise dot conflicts, then resolve it with --take-remote or --keep-local, or resolve every conflict with --take-remote-all or --keep-local-all. While any conflict remains, pushing and applying stop for all tracked files; local history and fetching continue. So it's not a total lockup, just a responsible pause.

In sync mode the watcher pulls on its own when there are no conflicts. When incoming config declares more tracked files, their versions from the origin are written in the same pull. Efficient. Slay.

Usage:

mise dotfiles pull [OPTIONS] [<PATH>] ...

✨ Options ✨

  • -n, --dry-run β€” show the plan without changing anything. Look but don't touch. πŸ‘€
  • -y, --yes β€” accepted for compatibility; pull skips the apply confirmation.
  • --take-remote <PATH> β€” resolve a conflict with the origin's version.
  • --keep-local <PATH> β€” resolve a conflict by keeping this machine's version; the next sync pushes it.
  • --take-remote-all β€” resolve every remaining conflict with the origin's version. Paths named by --keep-local keep this machine's version; every other conflict takes the origin's. Use it on a newly connected machine, where each existing file that differs is a separate conflict. 😭 (ask me how I know)
  • --keep-local-all β€” resolve every remaining conflict by keeping this machine's version. Paths named by --take-remote take the origin's version; every other conflict keeps this machine's. Each kept path must already be saved.
  • -h, --help β€” print help.

🌸 Arguments 🌸

  • <PATH> β€” not supported; a pull always applies every incoming change. Sorry babe, that's the rule. πŸ’€

πŸ’– Examples πŸ’–

Show what would be written:

mise dot pull --dry-run

Resolve a conflict with the origin's version:

mise dot pull --take-remote ~/.zshrc

Resolve a conflict by keeping this machine's version:

mise dot pull --keep-local ~/.zshrc

Take the origin's version of every conflict except one:

mise dot pull --take-remote-all --keep-local ~/.zshrc

🧚 MISE DOTFILES RECOVER β€” rescue an interrupted dotfile operation 🧚

Crash? Ctrl+C? We've all been there, no judgment. This finishes recovering from an operation that was interrupted. With no argument, it recovers every interrupted operation. ✨

mise restores files from the operation's recovery copies unless you've edited them since. When it can't tell which version is safe, it lists the files: check them, then rerun with --keep-current to keep what's on disk and discard the operation's recovery copies. When several operations were interrupted, --keep-current needs the ID of one. And FYI β€” Git history is not changed. 🫢

Usage:

mise dotfiles recover [OPTIONS] [<OPERATION>]

✨ Options ✨

  • --keep-current β€” keep the files on disk instead of restoring the recovery copies.
  • -y, --yes β€” discard the operation's recovery copies without prompting.
  • -h, --help β€” print help.

🌸 Arguments 🌸

  • <OPERATION> β€” the operation's checkpoint ID (see mise dot history --pending) or a unique prefix of its UUID.

πŸ’– Examples πŸ’–

Recover every interrupted operation:

mise dot recover

Keep the files on disk for operation 42:

mise dot recover 42 --keep-current --yes

⭐ MISE DOTFILES ROLLBACK β€” return files to the version a checkpoint holds ⭐

Time travel but make it cozy. πŸ•°οΈ Without --to, each path returns to its most recent saved version that differs from what's on disk; other checkpoints don't affect the choice. With --to REF, the named checkpoint is the source, and --all restores everything it covers. mise saves the current state in a checkpoint first, so mise dot undo can reverse the rollback. Reversible, always. πŸ‘‘

Usage:

mise dotfiles rollback [OPTIONS] [<PATH>] ...

✨ Options ✨

  • --to <REF> β€” the checkpoint to roll back to: numeric ID, latest, latest~N, or commit:<sha>.
  • --all β€” with --to, restore everything the checkpoint covers.
  • -n, --dry-run β€” show the plan without changing anything.
  • -y, --yes β€” apply without prompting.
  • --force β€” replace a path whose type changed (file, symlink, directory).
  • -h, --help β€” print help.

🌸 Arguments 🌸

  • <PATH> β€” paths to roll back (files or directories).

πŸ’– Examples πŸ’–

Restore the latest saved version that differs from the file:

mise dot rollback ~/.config/hypr/bindings.lua

Restore ~/.zshrc as checkpoint 42 holds it:

mise dot rollback ~/.zshrc --to 42

Preview restoring every file from three checkpoints ago:

mise dot rollback --to latest~3 --all --dry-run

πŸ”₯ MISE DOTFILES SAVE β€” save a checkpoint of the tracked files right now πŸ”₯

Snapshot time, bestie. πŸ“Έ Exits non-zero when history cannot save or a named path is not tracked. With no changes since the latest checkpoint, nothing is saved unless you pass --description, --label, --task, or a --trigger other than save. So if you want an empty-ish checkpoint, you gotta ask for it.

--best-effort turns a failure to write the checkpoint, such as missing Git, into a warning for update scripts that run under set -e. A disabled history or an untracked path still fails, though β€” those are real problems, not vibes. πŸ’€

A save re-encrypts the files it captures to the current [history.encryption] recipients. --re-encrypt also re-encrypts the encrypted files it does not capture: files with autosave = false that it does not name, and variants for other platforms. It re-encrypts their saved versions and saves no unsaved edit. Run it after changing recipients so a machine added to the list can read every file. 🫢 This machine must be able to unlock each one; otherwise nothing is saved and the error lists each file it cannot unlock.

Usage:

mise dotfiles save [OPTIONS] [<PATH>] ...

✨ Options ✨

  • -d, --description <TEXT> β€” a description for the checkpoint.
  • --trigger <TRIGGER> β€” record the checkpoint as a save, agent, or update checkpoint. Default: save.
  • --task <ID> β€” the ID of the task an agent is working on, recorded with the checkpoint.
  • --label <LABEL> β€” a label to find the checkpoint by later. Little breadcrumb, love that. πŸ“
  • --best-effort β€” warn instead of failing when the checkpoint cannot be written.
  • --re-encrypt β€” re-encrypt every saved encrypted file to the current recipients.
  • -h, --help β€” print help.

🌸 Arguments 🌸

  • <PATH> β€” paths to save; every one must be tracked.

πŸ’– Examples πŸ’–

Save every tracked file that changed:

mise dot save

Save one file with a description:

mise dot save ~/.zshrc -d "before the theme change"

Warn instead of failing in a script:

mise dot save --best-effort

Re-encrypt every encrypted file after changing recipients:

mise dot save --re-encrypt

πŸ’… MISE DOTFILES STATUS πŸ’…

Okay bestie, this one shows you the state of your dotfiles and their history β€” like a vibe check for your whole setup ✨

It lists the [dotfiles] entries that need attention and just counts the rest; --verbose lists every single entry. Each one has a state: applied, missing, differs, source missing, tracked, would remove for an absent entry whose target is still hanging around, or absent for a removal that's already done. And if a tracked entry's variants all select other machines β€” say, one for an inactive profile β€” it says not on this machine. Periodt.

Then it shows the history state in sections: Tracking, Repository, Conflicts, Automatic capture, and Bootstrap, and ends with the next steps 🫢

Files that a dotfile group deployed but no active entry deploys anymore get listed as orphaned: either the group was deselected or removed, or a new exclude or a deleted source dropped them. mise dot apply --prune removes them, no cap.

Heads up: template entries get rendered to compare their output, so trusted template functions may run. Know what you're trusting πŸ™ˆ

With --json it prints files, edits, and history, with each entry's origin and a state of applied, missing, differs, source_missing, or tracked. Orphaned files show up in a separate orphaned array with the state orphaned, or orphaned_changed when the file was modified after it got deployed. Every state is documented at https://mise.jdx.dev/dotfiles/reference.html#status-states πŸ¦‹

Usage: mise dotfiles status [OPTIONS] [<TARGET>] ...

✨ OPTIONS ✨

  • --truncate β€” truncate long terminal output so it fits the available width. Default: true.
  • -J, --json β€” output in JSON format, for the data girlies πŸ’œ
  • --missing β€” exit with code 1 if any dotfile is not in its desired state (missing, source missing, or differs). Perfect for CI.
  • -v, --verbose β€” list every entry, including the ones already applied or tracked.
  • --prompt-secrets β€” prompt for [bootstrap.secrets] values that templates need and the environment does not set πŸ”
  • -h, --help β€” print help.
Real talk: by default the table lists only entries that need attention or have omitted files, plus a one-line summary of the rest. Naming targets lists them regardless πŸ’…

Arguments:

  • <TARGET> β€” only show these targets.

🌸 Examples 🌸

Show what needs attention:

mise dot status

List every entry:

mise dot status --verbose

Show one target:

mise dot status ~/.zshrc

Print the state as JSON:

mise dot status --json

Exit 1 if anything is out of date, for scripts and CI:

mise dot status --missing

πŸ”„ MISE DOTFILES SYNC πŸ”„

Push saved checkpoints and fetch incoming changes β€” it's giving synchronization ✨

It fetches the origin branch and pushes your local history to it. If the push gets rejected, mise fetches again and reconciles the two histories without rewriting either β€” iconic, honestly. Incoming changes and conflicts get recorded for mise dot pull; this command never changes your files. With --fetch-only, or in fetch-only mode, nothing is pushed.

The watcher does this on its own in sync and fetch-only mode (the history.sync setting). More at https://mise.jdx.dev/dotfiles/sync.html πŸ¦‹

Usage: mise dotfiles sync [OPTIONS]

✨ OPTIONS ✨

  • --fetch-only β€” fetch without pushing. Lowkey the safest vibe.
  • --allow-plaintext-history β€” allow pushing older unencrypted versions of files that are now encrypted, and versions that look like they contain secrets. Be careful with this one bestie 😭
  • --best-effort β€” warn instead of failing when the origin is unreachable.
  • -h, --help β€” print help.

🌸 Examples 🌸

Push and fetch now:

mise dot sync

Fetch without pushing:

mise dot sync --fetch-only

πŸ‘‘ MISE DOTFILES TRACK πŸ‘‘

Track a file or directory in place β€” main character energy, no moving required πŸ’…

It adds a [dotfiles] entry with mode = "track" to your global config: the file stays exactly where it is, nothing is copied or linked, and mise saves a checkpoint of it right away. While the watcher service runs, later edits are saved automatically; without it, mise dot save saves them. Use --dry-run to see what a large directory would add before you track it β€” future you says thank you πŸ™

--os and --profile declare a variant: machines that match the platform or config environment keep their own version of the file, so a Mac and a Linux machine can have totally different contents at the same path. --machine gives every machine its own version instead, for files such as a monitor layout that should never be applied on another machine. Slay.

See https://mise.jdx.dev/dotfiles/history.html 🌈

Usage: mise dotfiles track [OPTIONS] <PATH> ...

✨ OPTIONS ✨

  • --os <OS> β€” declare a variant for this platform (macos, linux, linux/arm64, …).
  • --profile <PROFILE> β€” declare a variant for this config environment (MISE_ENV or -E).
  • --local β€” keep this file's history on this machine only; it is never shared 🏠
  • --machine β€” keep a separate stream on every machine, never applied on another.
  • --no-autosave β€” save only on mise dot save <path>, never automatically.
  • --encrypt β€” encrypt contents before saving them to history (requires [history.encryption] recipients) πŸ”
  • --allow-plaintext β€” save an explicitly tracked credential-named file in plaintext. Yes, on purpose.
  • -y, --yes β€” accepted for compatibility; track no longer asks to confirm the paths.
  • -n, --dry-run β€” show what each path expands to (files, size, what is left out) without tracking it.
  • -h, --help β€” print help.

Arguments:

  • <PATH> β€” paths to track (absolute or starting with ~/).

🌸 Examples 🌸

Track a file and a directory:

mise dot track ~/.zshrc ~/.config/hypr

Show what tracking a directory would save:

mise dot track --dry-run ~/.codex

Keep a separate version for macOS machines:

mise dot track ~/.zshrc --os macos

Keep a separate version on every machine:

mise dot track ~/.config/hypr/monitors.lua --machine

Keep the file's history on this machine only:

mise dot track ~/.config/app/state.json --local

Encrypt the file before saving it:

mise dot track ~/.config/app/credentials --encrypt

Save the file only when you run mise dot save:

mise dot track ~/.config/app/state.json --no-autosave

🧹 MISE DOTFILES UNAPPLY 🧹

Remove files that mise dot apply deployed β€” the break-up command πŸ’”

It removes the targets of whole-file entries and the blocks and lines that edit entries added, but only what mise can identify as its own. Modified copies, modified templates, and plain-line edits need --force. Merged keys, absent entries, and permissions-only targets are left alone. Sources and config entries are kept, so run this before you delete a declaration β€” while mise can still identify its targets. Timing matters, bestie ⏰

With --group, it removes only that dotfile group's files, using what mise recorded when it applied them, so it works even after the group is deselected or deleted from the config. Iconic.

Usage: mise dotfiles unapply [OPTIONS] [<TARGET>] ...

✨ OPTIONS ✨

  • -f, --force β€” remove modified or otherwise ambiguous managed files and lines.
  • -n, --dry-run β€” print the actions that would run without writing anything.
  • -y, --yes β€” skip the confirmation prompt.
  • --group <NAME> β€” only unapply the files of this dotfile group, even one that is no longer selected or declared.
  • --prompt-secrets β€” prompt for [bootstrap.secrets] values that templates need and the environment does not set πŸ”
  • -h, --help β€” print help.

Arguments:

  • <TARGET> β€” only unapply these targets.

🌸 Examples 🌸

Remove every target mise can identify:

mise dot unapply

Remove one target:

mise dot unapply ~/.zshrc

Remove one dotfile group's files:

mise dot unapply --group work

Preview what would be removed:

mise dot unapply --dry-run

Also remove modified targets, without prompting:

mise dot unapply --force --yes

βͺ MISE DOTFILES UNDO βͺ

Reverse the tracked-file changes from an operation β€” the ultimate take-backsies 🫢

It restores exactly the paths that an operation changed from the checkpoint it saved first, and leaves everything else as it is now. Without a reference, it reverses the newest operation that has not been undone.

Works for operations that changed tracked files: mise bootstrap, mise dot add, apply, edit, unapply, capture, rollback, pull (including changes the watcher applied), and undo itself. Package installations, service state, and untracked files are not reversed β€” so don't expect this to uninstall anything, bestie πŸ’€

Usage: mise dotfiles undo [OPTIONS] [<REF>]

✨ OPTIONS ✨

  • -n, --dry-run β€” show the plan without changing anything.
  • -y, --yes β€” apply without prompting.
  • -h, --help β€” print help.

Arguments:

  • <REF> β€” the operation's checkpoint: numeric ID, latest, latest~N, or commit:<sha>.

🌸 Examples 🌸

Reverse the newest operation:

mise dot undo

Show what would be restored:

mise dot undo --dry-run

Reverse the operation recorded as checkpoint 42:

mise dot undo 42

🚫 MISE DOTFILES UNTRACK 🚫

Stop tracking a file or directory β€” we're closing that chapter ✨

It removes the path's mode = "track" entry from your global config. When a project or system config declares the entry, mise turns it off on this machine in config.local.toml next to your global config instead.

A path inside a tracked directory has no entry of its own: mise adds a rule for it to [history] exclude in the global config, and mise dot include <path> removes that rule. The file itself and its existing checkpoints are not changed β€” so nothing gets deleted, we're just done watching it πŸ’…

Usage: mise dotfiles untrack [OPTIONS] <PATH> ...

✨ OPTIONS ✨

  • -h, --help β€” print help.

Arguments:

  • <PATH> β€” paths to stop tracking.

🌸 Examples 🌸

Stop saving ~/.zshrc:

mise dot untrack ~/.zshrc

Exclude one directory inside a tracked directory:

mise dot untrack ~/.config/hypr/plugins

πŸ¦‹ MISE DOTFILES WATCH πŸ¦‹

Save tracked files as they change β€” bestie, it literally watches your back πŸ’…

So this runs in the foreground (main character energy, no backgrounding) and saves a checkpoint once a changed file has been quiet for history.watch.debounce. And like β€” a file that keeps changing does not delay the others, and it's still saved every history.watch.max_interval. No cap, the watcher also rescans every tracked path at startup, every history.watch.reconcile, and whenever the configuration changes. Oh and heads up: entries tracked with --no-autosave are not watched πŸ™ˆ

With an origin connected, the watcher also syncs according to the history.sync setting. In sync mode it pushes within history.sync_interval of a save, fetches every history.fetch_interval, and applies incoming changes when there are no conflicts. In fetch-only mode it only fetches; in manual mode it does not use the network. A failed sync is retried with backoff while saving continues. --once runs one rescan and one sync, then exits. ✨

The built-in history-watch service runs this for you 🫢:

[bootstrap.services.mise-history]
builtin = "history-watch"

Exits 0 when history is disabled or another watcher is already running, and 1 when Git is unusable, the store cannot be opened, or no watch can be installed. A failed save is retried with backoff and never drops the pending changes, and a save that would overlap another history operation is deferred. With --once, nothing is retried: a save that fails or is deferred, or a sync that fails, exits 1.

⚠️ Lowkey important: --once means zero retries. One shot, one sync, and if it flops you get exit 1. Periodt.

Usage: mise dotfiles watch [OPTIONS]

✨ OPTIONS ✨

  • --once β€” Rescan and sync once, then exit (for timers and cron)
  • -J, --json β€” Print one JSON object per line instead of log lines
  • -h, --help β€” Print help

🌸 EXAMPLES 🌸

Watch and save until stopped:

mise dot watch

Rescan and sync once, for a timer:

mise dot watch --once

Print JSON lines instead of log lines:

mise dot watch --json

🩺 MISE DOCTOR 🩺

Check your mise setup for problems β€” the vibe check your config has been dreading πŸ’€

Prints mise's version, whether shell activation and shims are set up, its directories, the config files, tools, and environment in use, and its settings, then lists any problems and warnings with a suggested fix. Exits with status 1 when it finds a problem. Include this output when you report a bug. πŸ›

Usage: mise doctor [OPTIONS] [COMMAND]

✨ OPTIONS ✨

  • -J, --json β€” Output in JSON format
  • -h, --help β€” Print help

🌸 EXAMPLES 🌸

Check the setup and list problems:

mise doctor

Print the report as JSON:

mise doctor --json

πŸ›€οΈ MISE DOCTOR PATH πŸ›€οΈ

Print the directories mise adds to PATH β€” the receipts for where your tools live πŸŽ€

Lists tool bin directories and _.path entries from [env]. --full prints the whole PATH mise would set. mise bin-paths lists tool bin directories only. (iykyk the difference πŸ‘‘)

Usage: mise doctor path [OPTIONS]

✨ OPTIONS ✨

  • -f, --full β€” Print every PATH entry, including those mise does not provide
  • -h, --help β€” Print help

🌸 EXAMPLES 🌸

Print the directories mise adds to PATH:

mise doctor path
/home/user/.local/share/mise/installs/node/24.11.0/bin
/home/user/.local/share/mise/installs/python/3.13.1/bin

Print the whole PATH mise would set:

mise doctor path --full

πŸ” MISE DOCTOR PROJECT πŸ”

Run the project's diagnostic checks β€” custom vibe checks, but for your repo πŸ’–

Checks are declared in [doctor.checks.<name>] tables in mise.toml. Each command runs with the project's installed tools and environment. Checks should inspect state; mise does not sandbox them or run their suggested remedies. Exits with status 1 when a check fails. See https://mise.jdx.dev/configuration/project-diagnostics.html.

😭 Fr fr read that again: mise doesn't sandbox these checks and won't auto-run whatever fix they suggest. You're on your own for the remedies, bestie.

Usage: mise doctor project [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” Output the complete report as JSON
  • -h, --help β€” Print help

🌸 EXAMPLES 🌸

Run every check and report pass or fail:

mise doctor project

Print the report as JSON:

mise doctor project --json

🐚 MISE EN 🐚

Start a subshell with mise's tools and environment β€” a little mise bubble you can pop whenever 🌈

This is an alternative to mise activate for starting a mise session explicitly. The new shell has the tools and environment variables from the config loaded. Unlike an activated shell, changing directories does not update the environment. Type exit to leave it. 🫢

Usage: mise en [OPTIONS] [<DIR>]

✨ OPTIONS ✨

  • -s, --shell <SHELL> β€” Shell to start; defaults to $SHELL
  • -h, --help β€” Print help

🧚 ARGUMENTS 🧚

  • <DIR> β€” Directory to start the shell in. Default: .

🌸 EXAMPLES 🌸

Start a shell with the project's tools and environment:

mise en

Start the shell in another project:

mise en ~/work/api

Skip loading .bashrc:

mise en -s "bash --norc"

Skip loading .zshrc:

mise en -s "zsh -f"

🌿 MISE ENV 🌿

Print the environment for the current configuration β€” one big dump of your env, no prompt hooks attached πŸ’œ

Evaluate the shell output to load tools and variables once, without installing prompt hooks. Changing directories afterward does not recompute this environment. Use mise exec -- command to apply it to one child process instead. 🎯

🚨 SECURITY MOMENT: JSON, dotenv, and shell output contain actual variable values, including secrets. And --redacted selects variables marked for redaction; it does not mask their values. So like… be careful where you paste that output, bestie 😭

Tools you pass as TOOL@VERSION arguments are installed first if they are missing; missing tools from the config are reported, not installed. (Subtle but iconic distinction πŸ‘‘)

Usage: mise env [OPTIONS] [<TOOL@VERSION>] ...

✨ OPTIONS ✨

  • -D, --dotenv β€” Output in dotenv format
  • -J, --json β€” Output in JSON format
  • -s, --shell <SHELL> β€” Shell type to generate environment variables for
  • --json-extended β€” Output in JSON format with additional information (source, tool)
  • --redacted β€” Only include variables marked for redaction; their values are printed unmasked
  • --values β€” Only show values of environment variables
  • --paths β€” Print the PATH entries mise manages, in PATH order, one per line
  • -h, --help β€” Print help

🧚 ARGUMENTS 🧚

  • <TOOL@VERSION> β€” Tools to include in addition to those in the config, such as node@24

🌸 EXAMPLES 🌸

Load the environment once into the current bash session:

eval "$(mise env -s bash)"

Same, for zsh:

eval "$(mise env -s zsh)"

Same, for fish:

mise env -s fish | source

Same, for xonsh:

execx($(mise env -s xonsh))

Print the variables as JSON:

mise env --json

List the PATH entries mise manages, such as tool bin directories:

mise env --paths

Write a dotenv file; it contains secret values:

mise env --dotenv > .env
⚠️ That last one writes real secrets into .env. Do not commit it, do not post it, do not send it to the group chat πŸ’€

⚑ MISE EXEC ⚑

Run a command with mise's tools and environment β€” the script-and-CI icon, honestly πŸ”₯

Loads the tools and [env] from your config into one child process without changing the current shell. Use it in scripts and CI, or to run a tool that is not in the config. πŸ› οΈ

TOOL@VERSION arguments add tools or override the configured version of that tool only: with node = "24" in mise.toml, mise exec python@3.13 -- python -V still has node 24 on PATH. The way that's so precise πŸ’…

Put the command after --, or pass a shell command string with -c. Missing tools are installed first unless the exec_auto_install or auto_install setting is off; when you name tools, only those are installed. The --allow-* and --deny-* flags sandbox the command; see https://mise.jdx.dev/sandboxing.html.

Usage: mise exec [OPTIONS] [<TOOL@VERSION>] ... [<COMMAND>] ...

✨ OPTIONS ✨

  • -c, --command <COMMAND> β€” Command string to run through a shell (supports pipes and redirection)
  • -j, --jobs <JOBS> β€” How many tools to install in parallel; defaults to the jobs setting. Values below 1 are treated as 1. Environment: MISE_JOBS
  • --allow-env <VAR> β€” Pass only VAR through from the environment (implies --deny-env). Supports wildcards, such as --allow-env='MYAPP_*'.
  • --allow-net <HOST> β€” Allow network access only to HOST (not supported on any platform). Per-host filtering does not work: Linux and macOS exit with an error, and Windows runs the command without network restrictions. See https://mise.jdx.dev/sandboxing.html#access-to-particular-hosts
  • --allow-read <PATH> β€” Allow reads from PATH (implies --deny-read for everything else)
  • --allow-write <PATH> β€” Allow writes to PATH (implies --deny-write for everything else)
  • --deny-all β€” Block reads, writes, network, and env vars
  • --deny-env β€” Block env var inheritance except PATH, HOME, USER, SHELL, TERM, COLORTERM, LANG. On Windows it also keeps the variables programs need to start, such as SystemRoot and TEMP.
  • --deny-net β€” Block all network access
  • --deny-read β€” Block filesystem reads (system libs and tool dirs still accessible)
  • --deny-write β€” Block filesystem writes except temporary and device paths (/tmp, /dev)
  • --fresh-env β€” Bypass the environment cache and recompute the environment
  • --no-deps β€” Skip automatic dependency preparation
  • --raw β€” Connect install commands directly to the terminal; implies --jobs=1
  • --secrets <SECRET> β€” [experimental] Give the command these secrets (comma-separated); by default it gets none
  • --secrets-all β€” [experimental] Give the command every secret the project can inject, except file secrets
  • -h, --help β€” Print help
πŸ’€ Real talk on --allow-net: per-host filtering just does not work. Linux and macOS exit with an error, and Windows runs the command with the network unrestricted. That's not a vibe, that's a footgun β€” plan accordingly.

🧚 ARGUMENTS 🧚

  • <TOOL@VERSION> β€” Tools to add or override, such as node@24 python@3.13
  • <COMMAND> β€” Executable and arguments to run directly, after --

🌸 EXAMPLES 🌸

Run app.js with node 24:

mise exec node@24 -- node ./app.js

Run a shell command string:

mise x node@24 python@3.13 -c "node -v && python -V"

Run in another project's directory:

mise x -C ~/work/api -- npm test

Run without network access:

mise x --deny-net -- npm run build

[experimental] Pass one secret from the project's secrets source:

mise x --secrets GH_TOKEN -- gh release list

🌸 MISE FMT 🌸

Format mise TOML configuration β€” yes bestie, we're doing formatting now πŸ’…

Okay so this is the glow-up pass for your config files, and it's lowkey iconic. It formats the config files in the current directory in place 🫢. Pass --all and it formats every config file mise loads. Use --check in CI to fail when a file is not formatted (vibe check: failed πŸ’€), or --stdin to format a document from stdin to stdout without touching anything.

Formatting normalizes whitespace and writes TOML 1.1 syntax, including multiline inline tables ✨.

Top-level entries written as plain, dotted, or inline-table keys go in a standard order, and the order is exactly this:

min_version, env_file, env_path, _, env, vars, hooks, watch_files, tools, other keys, tasks, task_config, redactions, alias, plugins, settings

But <cyan>[table]</cyan> sections, and the keys inside any table, keep the order they were written in. No cap, they stay put πŸ‘‘

Lists whose order has no effect get sorted πŸŽ€:

  • task sources and outputs
  • task_config.global_inputs and input_groups
  • redactions

File pattern lists put @group: references first, then globs, then literal paths. And a list with a ! exclusion or a comment is left exactly as written β€” respect the author's choices fr fr πŸ™ˆ

Usage: mise fmt [OPTIONS]

✨ OPTIONS ✨

  • -a, --all β€” format every config file mise loads, not only the ones in the current directory 🌈
  • -c, --check β€” check whether the configs are formatted without rewriting them; exits 1 if any are not 😭
  • -s, --stdin β€” format TOML from stdin and print it to stdout, without touching any file πŸ¦‹
  • -h, --help β€” print help πŸ’–

πŸ“ EXAMPLES πŸ“

Format the config files in the current directory:

mise fmt

Exit 1 if any config file needs formatting:

mise fmt --check

Print a formatted copy without changing the file:

mise fmt --stdin < mise.toml

🧚 MISE GENERATE 🧚

Generate project files such as CI workflows, git hooks, and scripts ✨ β€” it's giving scaffolding, it's giving main character energy for your repo πŸ‘‘

Usage: mise generate [OPTIONS] <COMMAND>

OPTIONS

  • -h, --help β€” print help πŸ’…

πŸŽ€ MISE GENERATE CONFIG πŸŽ€

Generate a mise.toml file.

Same as mise edit, which has the details β€” go peek at that one for the full tea 🍡. It opens the interactive editor, or, without an interactive terminal (or with --yes), writes a commented starter template. If PATH already exists it stops with an error rather than replace the file 😀 β€” pass --force to replace it.

Usage: mise generate config [OPTIONS] [<PATH>]

OPTIONS

  • -g, --global β€” generate the global config file (~/.config/mise/config.toml) 🌍
  • -n, --dry-run β€” print the result instead of writing it to the file πŸ‘€
  • -f, --force β€” replace an existing file with the starter template when not opening the editor πŸ’₯
  • -t, --tool-versions <FILE> β€” copy the tools from this .tool-versions file into the config, without opening the editor 🫢
  • -h, --help β€” print help

ARGUMENTS

  • <PATH> β€” config file to edit or create; defaults to mise.toml

🌸 EXAMPLES 🌸

Edit mise.toml in the current directory:

mise generate config

Print the result instead of writing it:

mise generate config -n

πŸ¦‹ MISE GENERATE DEVCONTAINER πŸ¦‹

Generate a devcontainer configuration that installs mise and the project's tools 🐳✨

Prints JSON by default. --write saves .devcontainer/devcontainer.json in the repository root (or the current directory outside a git repository), replacing an existing file. Review the image, mounts, and setup commands before opening it β€” like, actually look at it bestie, don't just raw-dog it πŸ™ˆ

Usage: mise generate devcontainer [OPTIONS]

OPTIONS

  • -i, --image <IMAGE> β€” base image; defaults to mcr.microsoft.com/devcontainers/base:ubuntu
  • -m, --mount-mise-data β€” keep installed tools in a mise-data-volume Docker volume so they survive rebuilds πŸ’Ύ Mounts the volume at /mnt/mise-data, sets MISE_DATA_DIR to it, and adds its shims directory to PATH.
  • -n, --name <NAME> β€” container name; defaults to mise
  • -w, --write β€” write to .devcontainer/devcontainer.json instead of printing πŸ“
  • -h, --help β€” print help

πŸ“ EXAMPLES πŸ“

Print the configuration:

mise generate devcontainer

Keep installed tools in a volume and save .devcontainer/devcontainer.json:

mise generate devcontainer --mount-mise-data --write

πŸ’œ MISE GENERATE GIT-PRE-COMMIT πŸ’œ

Generate a git hook that runs a mise task πŸͺ

The hook runs mise run <TASK> (default pre-commit) with the staged file names in the STAGED environment variable. It prints the hook unless you pass --write, which saves it in the repository's hooks directory and makes it executable ✨

For hooks that git gives a message file (commit-msg, prepare-commit-msg, applypatch-msg, sendemail-validate), the task gets that file as an argument. Other hook arguments β€” such as a pre-push hook's remote name and URL β€” are not passed on 🫠

For a full git hook manager, see hk: https://hk.jdx.dev

Usage: mise generate git-pre-commit [OPTIONS] [<MISE_ARG>] ...

OPTIONS

  • -t, --task <TASK> β€” the task to run when the hook is triggered Default: pre-commit
  • -w, --write β€” write the hook to the hooks directory and make it executable πŸ’₯ The hooks directory is .git/hooks, or core.hooksPath when it is set. An existing hook of the same name is moved to <HOOK>.old.
  • --hook <HOOK> β€” which git hook to write, such as pre-push Default: pre-commit
  • -h, --help β€” print help

ARGUMENTS

  • <MISE_ARG> β€” mise flags to embed in the generated hook, given after -- These are inserted between mise and run, so the hook carries the same context you would pass on the command line. Useful when the config is not at the repository root, since git runs hooks from the top level: -- -C subdir makes the hook find it 🧭

🌈 EXAMPLES 🌈

Install the hook; each commit then runs mise run pre-commit:

mise generate git-pre-commit --write --task=pre-commit

Use the config in subdir, since git runs hooks from the repository root:

mise generate git-pre-commit --write -- -C subdir

⭐ MISE GENERATE GITHUB-ACTION ⭐

Generate a GitHub Actions workflow that runs a mise task πŸ€–

The workflow runs the task named by --task on pull requests, tags, manual dispatch, and pushes to the current branch. It prints YAML unless you pass --write, which saves .github/workflows/<NAME>.yml in the repository root and replaces an existing file. Define the task and review the triggers before committing the workflow β€” pls don't commit blind, bestie 😭

Usage: mise generate github-action [OPTIONS]

OPTIONS

  • -t, --task <TASK> β€” the task to run when the workflow is triggered Default: ci
  • -w, --write β€” write the workflow to .github/workflows/<NAME>.yml instead of printing it πŸ“
  • --name <NAME> β€” name of the workflow and its file Default: ci
  • -h, --help β€” print help

πŸŽ€ EXAMPLES πŸŽ€

Print a workflow that runs the ci task:

mise generate github-action

Save it as .github/workflows/ci.yml:

mise generate github-action --write

Save a workflow that runs the lint task as .github/workflows/lint.yml:

mise generate github-action --task lint --name lint --write

πŸ’– MISE GENERATE INSTALL-SCRIPT πŸ’–

Generate a script that downloads and runs a pinned mise πŸ”’

Commit the script, for example as bin/mise, so contributors and CI can run ./bin/mise install without installing mise first. On first run it downloads the pinned mise version into the mise data directory, or into the project with --localize, then runs it with the arguments it was given 🫢

mise generate bootstrap is a deprecated alias for this command and will be removed in mise 2027.9.0. Like, it's on the clock bestie πŸ’€
Usage: mise generate install-script [OPTIONS]

OPTIONS

  • -l, --localize β€” keep mise data and cache in a project-local directory (.mise by default) 🏠 Use --localized-dir to choose its location. This isolates mise state; it is not an OS sandbox for commands the generated script runs ⚠️
  • -V, --version <VERSION> β€” mise version to pin; defaults to the release mise self-update would install πŸ“Œ
  • -w, --write <PATH> β€” write the script to PATH (./bin/mise when no path is given) and make it executable, instead of printing it ✨
  • --localized-dir <DIR> β€” directory for mise data when using --localize, relative to the project Default: .mise
  • --windows β€” also write a Windows launcher, <PATH>.cmd πŸͺŸ Windows cannot run the bash script. Generate the launcher on any OS and commit it for contributors on Windows. Requires --write.
  • -h, --help β€” print help

🌸 EXAMPLES 🌸

Write ./bin/mise; on first run it downloads the pinned mise, then runs it:

mise generate install-script --write ./bin/mise

Keep mise and its tools in .mise inside the project:

mise generate install-script --localize --write ./bin/mise

Also write bin/mise.cmd for contributors on Windows:

mise generate install-script --write ./bin/mise --windows

🧚 MISE GENERATE TASK-DOCS 🧚

Generate Markdown documentation for project tasks πŸ“šβœ¨

Documents the tasks defined for the current directory. Prints to stdout by default. Use --output to write a file, --inject to replace a marked section, or --multi for one file per task β€” pick your fighter πŸ’…

Usage: mise generate task-docs [OPTIONS]

OPTIONS

  • -i, --inject β€” replace the marked section of the --output file 🎯 Replaces everything between <!-- mise-tasks --> and <!-- /mise-tasks --> in the --output file, so you can rerun it to update the docs. The file must already contain both markers; mise reports an error and leaves the file unchanged if either is missing 😀
  • -I, --index β€” write only an index of tasks, intended for use with --multi πŸ—‚οΈ
  • -m, --multi β€” render each task as a separate document; requires --output to be a directory πŸ“
  • -o, --output <PATH> β€” write the generated docs to a file or directory
  • -r, --root <ROOT> β€” has no effect; tasks always come from the current directory 🫠
  • -s, --style <STYLE> β€” has no effect; both styles produce the same output Default: simple
  • -h, --help β€” print help

πŸ“ EXAMPLES πŸ“

Print the task documentation:

mise generate task-docs

Write the task documentation to TASKS.md:

mise generate task-docs --output TASKS.md

Update the marked section of README.md:

mise generate task-docs --inject --output README.md

πŸŽ€ MISE GENERATE TASK-STUBS πŸŽ€

Okay so this one generates scripts that run mise tasks, and it's honestly such a serve. πŸ’…

It writes one executable stub per task into a directory β€” like bin/test for the test task β€” and that stub runs the task with mise. Pair them with mise generate install-script so your contributors can run tasks without installing mise. Iconic. When a task has subtasks, the parent's stub gets written to <parent>/_default.

Hidden tasks and global tasks are skipped, and here's why: the stubs get committed to the project, and global tasks come from each user's own config. So they just don't belong there, no cap. 🫢

Usage:

mise generate task-stubs [OPTIONS]

✨ Options ✨

  • -d, --dir <DIR> β€” Directory to create task stubs inside of. Default: bin
  • -m, --mise-bin <PATH> β€” the mise executable that the stubs run; defaults to mise from PATH

Use --mise-bin ./bin/mise with a script from mise generate install-script. On Windows a path runs as written, so that script needs its .cmd launcher sitting right beside it β€” generate it with mise generate install-script --write ./bin/mise --windows. The default, mise, is a bare name that resolves from PATH and needs nothing extra. πŸͺŸ

Default: mise

  • --windows-launcher <KIND> β€” what to write beside each stub so Windows can launch it

cmd writes <task>.cmd. Heads up though: cmd.exe re-parses the whole line before %* expands, so an argument containing & ^ | " %VAR% does not reach the task intact when the launcher is called from PowerShell. 😭

exe writes a native <task>.exe instead, which receives its arguments unchanged from every shell. It's a copy of the mise-shim.exe that ships with the Windows build, so it can only be generated on Windows, and it adds ~220KB per task to a directory that is normally committed. Weigh that one carefully bestie.

Default: cmd

  • -h, --help β€” Print help

🌸 Examples 🌸

Write a stub for each task into ./bin:

mise generate task-stubs

Make the stubs run the mise that mise generate install-script wrote:

mise generate task-stubs --mise-bin ./bin/mise

πŸ¦‹ MISE GENERATE TOOL-STUB πŸ¦‹

Generate or update a tool stub. Lowkey one of the coolest little features ngl. ⭐

A tool stub is an executable file that names a tool and where to get it β€” running it installs the tool if needed and then runs it. Full docs live at https://mise.jdx.dev/dev-tools/tool-stubs.html.

Pass --url or --platform-url to create or extend a stub. mise downloads each artifact to record its checksum, size, and binary path β€” unless you pass --skip-download. On an existing stub, new platforms get added and URLs you pass again get replaced. --fetch fills in missing checksums and sizes, and --lock records lock data for an existing stub, including one that uses a registry tool. Chef's kiss. πŸ‘‘

Usage:

mise generate tool-stub [OPTIONS] <OUTPUT>

✨ Options ✨

  • -b, --bin <BIN> β€” Binary path within the extracted archive

If you don't specify it and the archive is downloaded, mise detects the most likely binary for you. 🧚

  • --bootstrap β€” Make the stub install mise when it's missing

The stub becomes a bash script that:

  1. Uses mise from PATH, or ~/.local/bin/mise
  2. Otherwise installs mise to ~/.local/bin with the embedded installer
  3. Runs the tool stub with mise
  • --bootstrap-version <BOOTSTRAP_VERSION> β€” mise version the --bootstrap script installs; defaults to the latest release

Pin a version such as 2026.10.0 to keep the installer reproducible.

  • --checksum-algorithm <ALGORITHM> β€” Checksum algorithm for downloaded artifacts

Not available with --lock or --skip-download, which do not compute checksums. 🚫

Default: blake3

  • --fetch β€” Fetch checksums and sizes for an existing tool stub file

Reads an existing stub file and fills in missing checksum and size fields by downloading the files. URLs must already be present in the stub.

  • --http <HTTP> β€” Has no effect; kept so existing scripts that pass it keep working. (A little legacy moment, we respect it. πŸ™ˆ) Default: http
  • --lock β€” Resolve and record lock data (exact version, platform URLs and checksums) for an existing stub

The data goes into the mise.lock of the nearest project config above the stub, and the stub keeps its version request. It is an error when no project config is found. πŸ’€

  • --platform-bin <PLATFORM_BIN> β€” Binary path inside the archive for one platform, such as linux-x64:bin/tool; repeatable
  • --platform-url <PLATFORM_URL> β€” Download URL for one platform, as PLATFORM:URL or a bare URL; repeatable

With a bare URL, mise detects the platform from the file name, such as --platform-url https://nodejs.org/dist/v24.11.0/node-v24.11.0-darwin-arm64.tar.gz. When the output file already exists, new platforms are added to its platforms table, and a platform you pass again gets the new URL.

  • --skip-download β€” Do not download artifacts, so checksums, sizes, and the detected binary path are left out
  • -u, --url <URL> β€” URL to download the tool from
  • --version <VERSION> β€” Version of the tool. Default: latest
  • -h, --help β€” Print help

🌈 Arguments 🌈

  • <OUTPUT> β€” Output file path for the tool stub

πŸ“ Examples πŸ“

Download and inspect a real archive to detect its binary and checksum:

mise generate tool-stub ./bin/node --platform-url https://nodejs.org/dist/v24.11.0/node-v24.11.0-darwin-arm64.tar.gz

Add a Linux artifact to the same stub:

mise generate tool-stub ./bin/node --platform-url linux-x64:https://nodejs.org/dist/v24.11.0/node-v24.11.0-linux-x64.tar.gz

Draft a stub without downloading; replace the placeholder URL before running it:

mise generate tool-stub ./bin/my-tool --url https://example.com/my-tool.tar.gz --skip-download

Fill missing checksums and sizes in an existing stub:

mise generate tool-stub ./bin/node --fetch

Resolve and record the version and platform lock data of an existing registry-backed stub:

mise generate tool-stub ./bin/registry-node --lock --version 24

πŸ’€ MISE IMPLODE πŸ’€

Remove the mise CLI and all related data. This is the nuclear option bestie, handle with care. 🚨

It deletes the mise executable and the data (including installed tools), state, and cache directories. It also deletes the system-wide shared directory used by mise install --system (MISE_SYSTEM_DATA_DIR, default /usr/local/share/mise), which other users on the machine may rely on. So like… other people's stuff. Be so serious about that one. 😭

It asks before each removal; --yes skips the prompts. The config directory stays unless you pass --config.

If a package manager such as Homebrew or apt installed mise, uninstall it with that package manager instead. And remove the mise activate line from your shell startup file yourself β€” mise won't do it for you. See https://mise.jdx.dev/installing-mise.html#uninstalling.

Usage:

mise implode [OPTIONS]

✨ Options ✨

  • -n, --dry-run β€” Print what would be removed, without removing anything (please do this first, I'm begging πŸ₯Ί)
  • --config β€” Also remove the config directory
  • -h, --help β€” Print help

🌸 Examples 🌸

List what would be removed:

mise implode --dry-run

πŸ‘‘ MISE EDIT πŸ‘‘

Edit mise.toml interactively. Main character energy only. ✨

Opens a terminal editor for PATH (default: mise.toml in the current directory) where you can add tools from the registry, pick versions, and set environment variables, tasks, and settings. It pre-fills tools it detects from files in the current directory, such as .node-version. So helpful fr fr. πŸ’–

Without an interactive terminal, or with --yes, it writes a commented starter template instead. If PATH already exists it stops with an error rather than replace the file β€” pass --force to replace it. Use --dry-run to print the result without writing it.

Usage:

mise edit [OPTIONS] [<PATH>]

✨ Options ✨

  • -g, --global β€” Edit the global config file (~/.config/mise/config.toml)
  • -n, --dry-run β€” Print the result instead of writing it to the file
  • -f, --force β€” Replace an existing file with the starter template when not opening the editor
  • -t, --tool-versions <FILE> β€” Copy the tools from this .tool-versions file into the config, without opening the editor
  • -h, --help β€” Print help

πŸ¦‹ Arguments πŸ¦‹

  • <PATH> β€” Config file to edit or create; defaults to mise.toml

πŸŽ€ Examples πŸŽ€

Edit mise.toml in the current directory:

mise edit

Edit another config file:

mise edit mise.local.toml

Edit the global config:

mise edit -g

Copy the tools from .tool-versions into mise.toml:

mise edit -t .tool-versions

Print the result instead of writing it:

mise edit -n

Write a commented starter config to a new file without opening the editor:

mise edit -y new.toml

Replace an existing mise.toml with the starter config:

mise edit -y --force

πŸ’– MISE INSTALL

Installs the tools in your config, or specific tool versions ✨

Okay so with no arguments it installs every tool version your config asks for that isn't already installed, bestie. With TOOL@VERSION arguments, it installs those exact versions, and a bare tool name installs whatever version your config requests for it πŸŽ€

Big important thing: installing does not add a tool to your config, so a tool you haven't configured is not on PATH, periodt. Use mise use to install a tool and add it to mise.toml, or mise exec <TOOL>@<VERSION> -- <COMMAND> to run it once πŸ‘‘

Versions install in parallel (peep --jobs) under the mise data directory, which is by default ~/.local/share/mise/installs/<TOOL>/<VERSION> πŸ¦‹

Usage: mise install [OPTIONS] [<TOOL@VERSION>] ...

✨ OPTIONS ✨

  • -f, --force β€” reinstall even if it's already installed. And with no TOOL arguments, it reinstalls every configured tool 😭 (no cap, that's a lot)
  • -j, --jobs <JOBS> β€” how many tools to install in parallel; defaults to the jobs setting. Values below 1 are treated as 1. Environment: MISE_JOBS ⚑
  • -n, --dry-run β€” show what would be installed without installing anything πŸ™ˆ
  • -v, --verbose β€” show installer output. Prints each backend's download, configure, and compile output πŸ”₯
  • --dry-run-code β€” like --dry-run, but exits with status 1 when anything needs installing. Use it in scripts to check whether mise install has work to do πŸ’…
  • --include-task-tools β€” also install tools required by tasks in the current scope. This prepares task tools without running task commands or dependencies. Combine with --monorepo to include tasks from every configured root 🫢
  • --include-lazy β€” also install tools configured with lazy = true. By default, a bare mise install leaves lazy tools to be installed the first time you run one of their commands 😴
  • --minimum-release-age <AGE> β€” only install versions released before a date or at least a duration ago. Takes a date such as 2024-06-01 or a duration such as 90d or 1y. Overrides the minimum_release_age setting and tool option πŸ•°οΈ
  • --monorepo β€” also install tools from every config root in [monorepo].config_roots. Requires monorepo_root = true and an explicit config_roots list in the monorepo root's config. Uses the active MISE_ENV. Environment: MISE_MONOREPO 🌈
  • --raw β€” connect install commands directly to the terminal; implies --jobs=1 πŸ–₯️
  • --shared <DIR> β€” install into DIR instead of the mise data directory. May require elevated permissions, depending on the path πŸ”
  • --system β€” install into the system-wide shared directory. Installs to /usr/local/share/mise/installs (or MISE_SYSTEM_DATA_DIR/installs). On Unix, binary-download backends invoke sudo to publish into protected system directories unless system_packages.sudo is disabled. Run mise as your user, without sudo ⚠️
  • -h, --help β€” print help

πŸŽ€ ARGUMENTS πŸŽ€

  • <TOOL@VERSION> β€” tools to install, such as node@24; defaults to every tool in the config

🌸 EXAMPLES 🌸

Install every tool the config requests:

mise install

Install the node version the config requests:

mise install node

Install the latest node 24.x release:

mise install node@24

Install an exact version:

mise install node@24.11.0

Also install tools marked lazy = true:

mise install --include-lazy

Also install the tools your tasks need:

mise install --include-task-tools

πŸ¦‹ MISE INSTALL-INTO

Install a tool version into a directory outside mise πŸ’«

So this one downloads or builds TOOL@VERSION into PATH for use without mise. Heads up: mise does not track the result, so it won't show up in mise ls πŸ™ˆ

If PATH isn't empty, mise asks before deleting its contents β€” --yes deletes them without asking πŸ’€ (careful, bestie).

Usage: mise install-into [OPTIONS] <TOOL@VERSION> <PATH>

✨ OPTIONS ✨

  • -h, --help β€” print help

πŸŽ€ ARGUMENTS πŸŽ€

  • <TOOL@VERSION> β€” tool and version to install, such as node@24
  • <PATH> β€” directory to install into; its existing contents are deleted 😭

🌸 EXAMPLES 🌸

Install node 24 into ./mynode and run it:

mise install-into node@24 ./mynode && ./mynode/bin/node -v v24.11.0

πŸ‘‘ MISE INSTALLS

[experimental] Inspect and choose identity-layout installations πŸ§ͺ

With install_layout = "identity", each installation lives in its own <label>-<hash> directory, and several installations of one version can exist side by side (different options, platforms, pinned artifacts, or a refreshed copy) β€” iconic, honestly. These commands list them, choose which one mise uses when no lockfile pins one, and move installations made before you turned the layout on into it. With no subcommand, runs mise installs ls. See https://mise.jdx.dev/dev-tools/install-layout.html πŸ”—

Usage: mise installs [OPTIONS] [COMMAND]

✨ OPTIONS ✨

  • -h, --help β€” print help

⭐ MISE INSTALLS LS

List the installations of the identity install layout πŸ“‹

Every installation is listed separately, so variants of one version (made with different options, or pinned to different artifacts by lockfiles) can be told apart. The Status column marks the installation mise uses when no lockfile pins one (selected), installations a lockfile pins (pinned), and installations in a read-only shared installs directory (shared) πŸ’…

Usage: mise installs ls [OPTIONS] [<TOOL>] ...

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format 🧚
  • --no-header β€” do not print the table header
  • -h, --help β€” print help

πŸŽ€ ARGUMENTS πŸŽ€

  • <TOOL> β€” only show the installations of these tools

🌸 EXAMPLES 🌸

List every installation in the identity layout:

mise installs ls

List the installations of node as JSON:

mise installs ls node --json

🧚 MISE INSTALLS MIGRATE

Reinstall legacy installations into the identity install layout 🚚

Installations made before install_layout = "identity" was turned on stay in installs/<tool>/<version> and keep working; mise never moves them on its own, because tools record their own path in shebangs, virtual environments and package-manager files 😀. This reinstalls each one into its own <label>-<hash> directory, then removes the old directory and puts the version link in its place, so a path that pointed into the old directory still resolves 🎯

Each version is reinstalled from its backend, not copied, so the files are written for their new path. Run it while nothing is using the tools: the old directory is moved aside while its replacement installs, and put back if that fails. Versions whose recorded backend is not the one their tool resolves to now are left alone, as are tools that keep the legacy layout (http:, rust, dotnet) πŸ™…β€β™€οΈ

A version that can't be reinstalled (its release was withdrawn or is signed by someone else now, or the network is unavailable) is not an error: its directory is moved as it is into the identity layout, behind the same version link. Only a version that can't be moved either keeps its old directory, reported as kept in the legacy layout. The command ends with a count of what was migrated, relocated, kept and failed, and fails only when a migration itself broke πŸ’€

Usage: mise installs migrate [OPTIONS] [<TOOL@VERSION>] ...

✨ OPTIONS ✨

  • -n, --dry-run β€” show what would move without changing anything πŸ™ˆ
  • -h, --help β€” print help

πŸŽ€ ARGUMENTS πŸŽ€

  • <TOOL@VERSION> β€” only migrate these tools, or these versions of them. Defaults to every legacy installation

🌸 EXAMPLES 🌸

List the legacy installations that would move:

mise installs migrate --dry-run

Move every installed node and one python version:

mise installs migrate node python@3.12.1

πŸ’… MISE INSTALLS SELECT

Choose which installation mise uses when no lockfile pins one πŸ‘‘

Several installations can match the same request, such as a refreshed copy next to one a lockfile pinned, or installations made for different lockfiles. For a request with no lockfile entry, mise uses the installation selected for that tool, version, platform, and options. If none is selected and several match, mise stops and tells you to run this command 😭

The selection is shared by every project on this machine that makes the same request without a lockfile. Projects whose lockfile pins an artifact keep the installation of that artifact. The version link (installs/<tool>/<version>) is pointed at the selected installation πŸŽ€

Usage: mise installs select [OPTIONS] <INSTALLATION>

✨ OPTIONS ✨

  • -h, --help β€” print help

πŸŽ€ ARGUMENTS πŸŽ€

  • <INSTALLATION> β€” the installation to select: its directory name, or its path

🌸 EXAMPLES 🌸

Find jq's installations:

mise installs ls jq

Use this one for requests with no lockfile entry:

mise installs select jq-hm3qa4vb

🌈 MISE LATEST

Print the latest version that matches a version request ⭐

mise latest node prints the latest release, and mise latest node@22 the latest 22.x release. Each backend decides what "latest" means, for example whether prereleases count and how channels and refs resolve. Nothing is installed and no config changes β€” it's giving purely informational, bestie πŸ¦‹

Usage: mise latest [OPTIONS] <TOOL@VERSION> [<ASDF_VERSION>]

✨ OPTIONS ✨

  • -i, --installed β€” print the latest installed version instead of the latest available one πŸ’–
  • --minimum-release-age <AGE> β€” only consider versions released before a date or at least a duration ago. Takes a date such as 2024-06-01 or a duration such as 90d or 1y. Overrides the minimum_release_age setting and tool option πŸ•°οΈ
  • -h, --help β€” print help

πŸŽ€ ARGUMENTS πŸŽ€

  • <TOOL@VERSION> β€” tool, optionally with a version prefix, such as node or node@22
  • <ASDF_VERSION> β€” the version prefix to use when querying the latest version, same as the first argument after the @, used for asdf compatibility 🫢

🌸 EXAMPLES 🌸

Print the latest node release:

mise latest node

Print the latest node 22.x release:

mise latest node@22

Print the latest installed node 22.x version:

mise latest node@22 --installed

Skip releases from the last 30 days:

mise latest node --minimum-release-age 30d

Okay bestie, this one's literally just a symlink moment β€” it lets you slide a tool version into mise so mise knows it exists.

Use it to register an install you compiled by hand or built with some other tool. mise uses the version exactly as written, like node@24.11.0 or a name of your own invention like node@brew. But heads up: latest, aliases, and channels are rejected β€” no cap, they will not be accepted. πŸ’…

Usage: mise link [OPTIONS] <TOOL@VERSION> <PATH>

✨ Options ✨

  • -f, --force β€” replace an existing installation of this version, slay
  • -h, --help β€” print help

🫢 Arguments 🫢

  • <TOOL@VERSION> β€” the tool and version you're making a symlink for
  • <PATH> β€” the directory of the existing installation, like ~/.nvm/versions/node/v24.11.0

πŸ¦‹ Examples πŸ¦‹

Link a node that node-build built into ~/.nodes/24.11.0:

mise link node@24.11.0 ~/.nodes/24.11.0

Register Homebrew's node as node@brew; then run mise use node@brew:

mise link node@brew "$(brew --prefix node)"

πŸ”’ MISE LOCK

Create or refresh lockfile versions, checksums, and download URLs. Iconic behavior honestly. ✨

It operates on the current config root, including tools declared by tasks. Existing matching locked versions are preserved unless --bump re-resolves their requests. Important vibe check: this command does not install tools β€” --dry-run just previews changes. πŸ‘‘

mise lock TOOL@VERSION locks that exact version. And when the version falls outside the configured request β€” like tiny@3.0.1 while tiny = "2" β€” mise also updates the request in mise.toml to match. It's giving "I fixed it for you." πŸ’–

Usage: mise lock [OPTIONS] [<TOOL>] ...

✨ Options ✨

  • -g, --global β€” lock only the global and system config lockfiles. These are ~/.config/mise/mise.lock and the system config's lockfile. By default, only the current project's config root is locked.
  • -j, --jobs <JOBS> β€” how many jobs to run in parallel; defaults to the jobs setting. Values below 1 are treated as 1. Environment: MISE_JOBS
  • -n, --dry-run β€” show what would change, without writing anything πŸ™ˆ
  • -p, --platform <PLATFORM> β€” platforms to lock, comma-separated, such as linux-x64,macos-arm64. Defaults to the lockfile_platforms setting plus the current platform when that setting is configured, else the platforms already in the lockfile, else a common set for a new lockfile.
  • --bump β€” re-resolve version requests against the latest available versions. By default, mise lock refreshes metadata for the currently locked versions. With this flag, requests such as "latest", "lts", or prefixes such as "24" are re-resolved against the latest matching remote versions, so the lockfile advances without installing anything. --bump never modifies config files: exact versions resolve to themselves and stay unchanged (use mise upgrade --bump to rewrite pins in mise.toml). If the remote versions cannot be fetched, it fails rather than keep the locked version. No silent fallback energy. πŸ’€
  • --json β€” output version changes as JSON. Prints an array of objects describing lockfile version changes: name, backend, lockfile, old_versions, new_versions. Version lists keep config/lockfile order; they are not sorted. Only version-level changes are reported: checksum and URL refreshes for unchanged versions produce no entries, so mise lock --json prints [] when no version changed, even though it still updates the lockfile. Suppresses the human-readable output. Combine with --dry-run to detect available updates without writing the lockfile.
  • --local β€” update mise.local.lock, for tools in mise.local.toml, instead of mise.lock
  • --minimum-release-age <AGE> β€” only lock versions released before a date or at least a duration ago. Takes a date such as 2024-06-01 or a duration such as 90d or 1y. Overrides the minimum_release_age setting and tool option. It filters only requests that are not exact, such as "24" or "latest"; exact versions such as "24.11.0" are not filtered. Existing matching lockfile entries are kept; this flag alone does not downgrade them.
  • --upgrade β€” upgrade lockfiles to the latest format. mise keeps an existing lockfile at its format version during normal updates, so collaborators on an older mise can still read it. This flag rewrites it in the newest format, which adds request bindings, dependency-graph sidecars, and packslip repository IDs. It processes every configured tool and cannot be combined with tool arguments. See https://mise.jdx.dev/dev-tools/mise-lock-reference.html#format-versions.
  • --sidecars β€” list native dependency sidecars instead of updating lockfiles. Backends such as npm and pypi keep a tool's locked dependency graph in a sidecar directory next to mise.lock; see https://mise.jdx.dev/dev-tools/mise-lock-reference.html#native-dependency-sidecars. For each existing lockfile in scope, prints the sidecar directory mise keeps its dependency graphs in and every sidecar directory the lockfile references. Nothing is resolved, installed, or written. Paths are relative to the current directory when they are inside it, and absolute otherwise, such as the sidecars of a symlinked lockfile. Combine with --json for machine-readable output, or with --local and --global to choose the lockfiles.
  • -h, --help β€” print help

🫢 Arguments 🫢

  • <TOOL> β€” tools to lock, such as node python; defaults to every configured tool and every tool a task needs. Use tool@version to lock an exact version. If it falls outside the configured request, mise.toml is updated to match.

πŸ¦‹ Examples πŸ¦‹

Create or refresh the project lockfile:

mise lock

Refresh only node and python:

mise lock node python

Lock an exact version; mise.toml keeps a request such as "24":

mise lock node@24.11.0

Lock only the linux-x64 platform:

mise lock --platform linux-x64

Show what would change:

mise lock --dry-run

Re-resolve requests such as "latest" or "24" to the latest matching versions:

mise lock --bump

List available updates as JSON without writing:

mise lock --bump --dry-run --json

Lock versions released before 2024-01-01 for requests that are not exact:

mise lock --minimum-release-age 2024-01-01

Update mise.local.lock:

mise lock --local

Update only the global lockfiles:

mise lock --global

πŸ“‹ MISE LS

List installed and active tool versions. This is the "who's here and who's supposed to be here" command, and honestly it ate. πŸ’–

It lists the tools mise knows about: versions that are installed, and versions requested by a config file (active) whether or not they're installed. Each row shows the tool, the version (marked (missing) when it's not installed, or (lazy) when it's a lazy tool that installs on first use), the config file that requests it, and the request as written. πŸ’…

Usage: mise ls [OPTIONS] [<INSTALLED_TOOL>] ...

✨ Options ✨

  • --truncate β€” truncate long terminal output to fit the available width. Default: true
  • -b, --backend <BACKEND> β€” only show tools from this backend, such as aqua, cargo, core, or go. Registry shorthands count as the backend they resolve to, so jq is listed under aqua. Repeat the flag to show several backends.
  • -c, --current β€” only show versions the loaded config files request
  • -g, --global β€” only show versions the global config requests
  • -i, --installed β€” only show installed versions. Hides requested versions that are not installed.
  • --grouped β€” list tools in a separate section for each backend. Cannot be combined with --json; use --backend to filter JSON output.
  • -J, --json β€” output in JSON format
  • -l, --local β€” deprecated alias for --no-global. Removed in mise 2027.7.0. RIP bestie πŸͺ¦
  • --no-global β€” only show versions that non-global config files request. Includes config files in parent directories and skips the global config, system config, and MISE_<TOOL>_VERSION environment variables. See --project for the nearest project's config alone.
  • --project β€” only show versions the nearest project config requests. The project is the nearest directory, starting at the current one and moving up, that has a mise config file. Every config file in that directory counts, such as mise.toml, mise.local.toml, conf.d fragments, .tool-versions and idiomatic version files. Configs in parent directories and global or system configs do not, nor do MISE_<TOOL>_VERSION environment variables. A version that a later file in that directory overrides is not listed, as with --no-global; mise uninstall --project still removes it.
  • -m, --missing β€” only show requested versions that are not installed
  • -o, --offline β€” don't fetch information such as outdated versions
  • -p, --plugin <PLUGIN>
  • --all-sources β€” show requests from every config file mise has seen, not only loaded ones. mise tracks the config files it loads so mise prune keeps the versions they use.
  • --monorepo β€” also list tools from every config root in [monorepo].config_roots. Requires monorepo_root = true and an explicit config_roots list in the monorepo root's config. Uses the active MISE_ENV. Environment: MISE_MONOREPO
  • --no-header β€” do not print the header row
  • --outdated β€” show whether each version is outdated
  • --prefix <PREFIX> β€” only show versions starting with PREFIX (requires a tool argument)
  • --prunable β€” list only tools that can be pruned with mise prune
  • -h, --help β€” print help

🫢 Arguments 🫢

  • <INSTALLED_TOOL> β€” only show these tools

πŸ¦‹ Examples πŸ¦‹

Show installed versions and the requests from the loaded config files:

mise ls

Show only versions the loaded config files request:

mise ls --current

Find requested versions that are not installed:

mise ls --missing

Machine-readable output: an object keyed by tool name:

mise ls --json

With a tool argument, JSON output is an array of its version records:

mise ls node --json

Include requests from every config file mise has seen:

mise ls --all-sources

Show only tools from the go or cargo backends:

mise ls --backend go --backend cargo

List tools in a separate section for each backend:

mise ls --grouped

🌸 MISE LS-REMOTE 🌸

Bestie, this one's your window-shopping command β€” it lists all the tool versions you could install. ✨

Heads up though: results may be cached, so if you're not seeing what you expect, run mise cache clear TOOL to refresh one tool before you query it again. And fyi, version formats and ordering are backend-specific β€” every backend does its own thing, no cap.

Usage: mise ls-remote [OPTIONS] [<TOOL@VERSION>] [<PREFIX>]

✨ Options ✨

  • --all β€” list available versions for every tool mise currently knows about 🫢
  • --minimum-release-age <AGE> β€” only show versions released before a date or at least a duration ago. Takes a date such as 2024-06-01 or a duration such as 90d or 1y. This overrides the minimum_release_age setting and tool option.
  • -J, --json β€” output in JSON format, with metadata such as created_at when available πŸ’…
  • --no-versions-host β€” fetch versions from the tool's upstream instead of mise's version mirror. Same as use_versions_host = false for this command.
  • --prerelease β€” include prerelease versions. Works for backends that report prerelease metadata or detect prereleases by pattern. Same as MISE_PRERELEASES=1 or the prereleases setting, for this command only.
  • --strict-metadata β€” exit with an error when release metadata cannot be fetched. Without it, backends such as aqua and ruby fall back to a version list without release dates, or an empty one. Requires --json and --no-versions-host.
  • -h, --help β€” print help

πŸ¦‹ Arguments πŸ¦‹

  • <TOOL@VERSION> β€” the tool to get versions for
  • <PREFIX> β€” version prefix to filter by; same as TOOL@PREFIX

πŸŽ€ Examples πŸŽ€

List every node version:

mise ls-remote node

List node 24.x versions:

mise ls-remote node@24

Skip versions released in the last 30 days:

mise ls-remote node --minimum-release-age 30d

Include release dates, as JSON:

mise ls-remote github:cli/cli --json

πŸ’œ MISE LSP πŸ’œ

Run the language server for mise config files over stdin/stdout. Editors start this command and exchange Language Server Protocol messages with it. It's giving "your editor and mise are texting each other" energy πŸ˜­πŸ’–

It serves mise.toml and the other config files mise loads (.mise.toml, mise.<env>.toml, mise.local.toml, mise/config.toml, and the files of a conf.d). It ignores every other file, including files that [task_config] includes lists β€” so you can attach it to the TOML language without it touching Cargo.toml or pyproject.toml. Obsessed, honestly. ✨

Here's the full menu of what it offers:

  • diagnostics β€” TOML syntax errors, unknown keys with a suggestion, values of the wrong type, deprecated keys, task names no task defines (unknown-task), and dependency cycles (task-cycle)
  • completion β€” of keys, including inside inline tables, and of values that have a fixed set
  • hover β€” documentation for keys
  • for tools β€” completion of tool names under [tools] from the registry, and hover with the tool's description and backends
  • quick fixes β€” that replace an unknown key or task name with the suggested one, and rewrite a deprecated key to its replacement when the schema names one
  • formatting β€” as mise fmt does
  • semantic tokens β€” which color task, tool and env var names, env directives, deprecated keys and the {{ }} and {% %} of templates
  • for tasks β€” completion of task names in depends, depends_post, wait_for and run = [{ task = "..." }] (and of templates in extends), hover with the task's description and command, go to definition, find references, and rename together with every reference in the file

Tasks come from the open file, the configs in the directories above it and the TOML files their [task_config] includes name.

If a client runs another TOML server beside this one, it can switch features off with initializationOptions:

{"formatting": false, "hover": false, "completion": false, "definition": false, "references": false, "rename": false, "semanticTokens": false}
🫢 The server only parses a config. It never renders templates or runs anything, so opening an untrusted file is safe. Iconic safety behaviour.

One little compatibility note: a mise that predates this command runs a task named lsp instead β€” so a client that needs to know whether the command exists can check that mise help lsp prints Usage: mise lsp.

Editor config lives at https://mise.jdx.dev/ide-integration.html β€” go look, bestie. πŸ’…

Usage: mise lsp [OPTIONS]

✨ Options ✨

  • -h, --help β€” print help

πŸŽ€ Examples πŸŽ€

Start the server; an editor's LSP configuration runs this command:

mise lsp

πŸ”₯ MISE MCP πŸ”₯

Run the Model Context Protocol server over stdin/stdout. Basically mise gets to talk to your AI coding assistant, and we love that for her. πŸ‘‘

It exposes project tools, tasks, environment, and configuration to an MCP client. The client β€” such as an AI coding assistant β€” starts this command and exchanges messages with it. Start it in the project directory or pass --cd: the resources describe that project.

Resources (JSON):

  • mise://tools β€” active tool versions (?include_inactive=true adds the rest)
  • mise://tasks β€” task definitions, including monorepo subproject tasks
  • mise://env β€” environment variables
  • mise://config β€” loaded config files and the project root
πŸ’€ Environment resources contain real values, including secrets. Read that twice.

Tools:

  • list_commands β€” every mise command and its declared effect
  • run_task β€” run a task with your permissions; it can change files and call external services
  • install_tool β€” install a tool version, as mise install does

run_task and install_tool refuse a project whose config files are not trusted β€” so run mise trust there after reviewing them. Fr fr, review first. πŸ™ˆ

Client configuration and access controls live at https://mise.jdx.dev/mcp.html.

Usage: mise mcp [OPTIONS]

✨ Options ✨

  • -h, --help β€” print help

πŸŽ€ Examples πŸŽ€

Serve a project from another directory, as an MCP client config does:

mise --cd /path/to/project mcp

🧚 MISE OCI 🧚

[experimental] Build, push, and run OCI images of a project's tools. Yes she's experimental, so treat her like a main character still figuring things out. 🌈

The cute part: each tool version becomes its own image layer, so changing one tool version rebuilds that tool's layer instead of the whole image. Efficiency slay. ⭐

⚠️ Requires mise settings experimental=true (or MISE_EXPERIMENTAL=1). Behavior, flags, and output layout may change in future releases. See https://mise.jdx.dev/dev-tools/mise-oci.html
Usage: mise oci [OPTIONS] <COMMAND>

✨ Options ✨

  • -h, --help β€” print help

πŸŽ€ MISE OCI BUILD πŸŽ€

[experimental] Build an OCI image from the current mise.toml.

Each tool version becomes its own content-addressable OCI layer. Bumping a tool version invalidates that tool's layer (a Python bump also invalidates pypi tool layers, which are relocated against it); the other tool layers and the base image layers are reused, while the generated /etc/mise/config.toml layer, image config, and manifest are regenerated. The output directory follows the OCI image-layout spec. ✨

Only tools from project config files are packaged, including a monorepo root's config. The global and system configs and a config directly in your home directory, such as ~/mise.toml, are left out unless you pass --include-global.

🫢 Build on a Linux host with the image's architecture. Tools are packaged as installed on the host, and so is the running mise binary, at /usr/local/bin/mise, unless you pass --no-mise. asdf plugins are not supported β€” use a vfox plugin or any other backend for each tool. vfox plugins are copied into the image next to the tools they install.

Requires mise settings experimental=true (or MISE_EXPERIMENTAL=1).

Usage: mise oci build [OPTIONS]

✨ Options ✨

  • --copy <HOST_PATH:IMAGE_PATH> β€” copy a host file, directory, or symlink into the image (repeatable, HOST:IMAGE)
  • -o, --output <OUTPUT> β€” output directory for the OCI image layout. Default: ./mise-oci
  • --from <FROM> β€” base image reference (overrides [oci].from and the oci.default_from setting)
  • --include-global β€” also package tools from the global and system configs. By default mise oci build packages only project config files, including a monorepo root's config. With this flag it also includes the tools, [oci], [bootstrap.packages], and [dotfiles] of the global and system configs and of a config directly in your home directory, so personal tools from ~/.config/mise/config.toml end up in the image.
  • -t, --tag <TAG> β€” tag to record in the image index (the org.opencontainers.image.ref.name annotation)
  • --mount-point <MOUNT_POINT> β€” where tools install inside the image. Overrides [oci].mount_point and the oci.default_mount_point setting.
  • --no-mise β€” do not embed the currently-running mise binary at /usr/local/bin/mise
  • --no-cache β€” rebuild tool layers without reading or writing the local layer cache
  • --owner <UID[:GID]> β€” UID[:GID] to assign to every tar entry in generated layers. Overrides [oci].user_id and [oci].group_id. Defaults to 0:0. If GID is omitted, it defaults to UID. This affects file ownership only; [oci].user controls the image USER directive.
  • -h, --help β€” print help

πŸ¦‹ Examples πŸ¦‹

Build the project's image into ./mise-oci:

mise oci build

Use another base image and record a tag:

mise oci build --from ubuntu:24.04 --tag myorg/dev:latest -o ./img

Inspect the result:

skopeo inspect oci:./img

Open a shell in it:

mise oci run --image-dir ./img -- /bin/sh

πŸ’… MISE OCI PUSH

[experimental] bestie, this one builds an OCI image and pushes it to a registry. Iconic behavior honestly.

It builds from the project's config, exactly like mise oci build does β€” unless --image-dir names an image layout you built earlier. Then it uploads only the blobs the registry does not already have ✨. And the way mise pushes? With its own registry client, so skopeo, crane, and docker are literally not needed. No cap.

Tool layers whose tool, version, mount point, and file owner match the previously pushed image (or --cache-from) get reused without being rebuilt πŸŽ€ β€” so those tools don't even need to be installed locally. Chef's kiss. If you want every single tool layer rebuilt, pass --no-cache.

Credentials come from the same files docker and podman use, in this order: $REGISTRY_AUTH_FILE, $XDG_RUNTIME_DIR/containers/auth.json, ~/.config/containers/auth.json, then ~/.docker/config.json β€” including inline auths and credential helpers. Just log in with docker login or podman login and you're so set πŸ’–.

Needs mise settings experimental=true (or MISE_EXPERIMENTAL=1) to even run. Periodt.

Usage: mise oci push [OPTIONS] <REF>

✨ Options ✨

  • --cache-from <REF> β€” reuse unchanged tool layers from this image instead of the destination's current tag πŸ¦‹. Has to be in the same repository as the destination. Super useful when every push gets a new tag, like per-commit tags in CI: mise oci push --cache-from ghcr.io/me/dev:latest ghcr.io/me/dev:$SHA. Cannot be combined with --no-cache.
  • --from <FROM> β€” the base image for the build. Overrides [oci].from and the oci.default_from setting πŸ’œ.
  • --image-dir <IMAGE_DIR> β€” push an existing OCI image layout instead of building one. Cannot be combined with --cache-from, --from, --include-global, --mount-point, --no-mise, or --owner 🚫.
  • --include-global β€” also package tools from the global and system configs. See mise oci build --help for the details 🌸.
  • --mount-point <MOUNT_POINT> β€” where tools install inside the image. Overrides [oci].mount_point and the oci.default_mount_point setting πŸŽ€.
  • --no-cache β€” rebuild tool layers without using the remote or local layer cache πŸ”₯.
  • --no-mise β€” don't embed the running mise binary at /usr/local/bin/mise.
  • --owner <UID[:GID]> β€” the UID[:GID] to assign to every tar entry when building. Overrides [oci].user_id and [oci].group_id. Defaults to 0:0. If GID is omitted, it defaults to UID. Heads up: this affects file ownership only β€” [oci].user controls the image USER directive ⭐.
  • --update-index β€” maintain the tag as a multi-arch image index πŸ‘‘. Pushes this build's manifest by digest and points the tag at an OCI image index containing one entry per platform, preserving entries other architectures pushed. Run mise oci push --update-index from one runner per platform to assemble a multi-arch tag.
  • -h, --help β€” print help πŸ’….

🫢 Arguments 🫢

  • <REF> β€” destination registry reference (e.g. ghcr.io/me/devenv:latest).

🌈 Examples 🌈

Build and push to GHCR:

mise oci push ghcr.io/me/devenv:latest

Push an image built earlier:

mise oci build -o ./img mise oci push --image-dir ./img ghcr.io/me/devenv:v1

πŸ¦‹ MISE OCI RUN

[experimental] Builds the project's image and runs a command in it 😭 this is the good one.

It builds the image the way mise oci build does, unless --image-dir names an existing layout, then loads it into podman or docker and runs the command in a container with stdin, stdout, and stderr attached 🫢. podman reads the OCI layout directly; docker receives it through docker load.

Requires mise settings experimental=true (or MISE_EXPERIMENTAL=1) and podman or docker πŸ’€.

Usage: mise oci run [OPTIONS] [<CMD>] ...

✨ Options ✨

  • --engine <ENGINE> β€” container engine to use; auto prefers podman and falls back to docker. Default: auto πŸŽ€.
  • --from <FROM> β€” base image for the build. Overrides [oci].from and the oci.default_from setting πŸ’œ.
  • --image-dir <IMAGE_DIR> β€” use an existing OCI image layout instead of building one. Cannot be combined with --from, --include-global, --mount-point, --no-mise, or --owner 🚫.
  • --include-global β€” also package tools from the global and system configs. See mise oci build --help for details 🌸.
  • --keep β€” keep the loaded image in the engine's storage after the run. By default both the container (--rm) and the loaded image are removed when the command exits, so repeated mise oci run calls don't fill podman or docker storage 🧚. With --keep, the image stays under the tag mise used (mise-oci:run-* for docker, the pulled image ID for podman) ⭐.
  • --mount-point <MOUNT_POINT> β€” where tools install inside the image. Overrides [oci].mount_point and the oci.default_mount_point setting.
  • --no-mise β€” don't embed the running mise binary at /usr/local/bin/mise.
  • --owner <UID[:GID]> β€” the UID[:GID] to assign to every tar entry when building. Overrides [oci].user_id and [oci].group_id. Defaults to 0:0. If GID is omitted, it defaults to UID. Again: file ownership only β€” [oci].user controls the image USER directive πŸ’….
  • --volume <HOST:CONTAINER> β€” bind-mount a host path (repeatable, HOST:CONTAINER[:MODE]). Unlike docker run, there's no -v short form because mise uses -v for --verbose πŸ™ˆ. Use --volume or --mount.
  • -e, --env <KEY=VAL> β€” set environment variable in the container (repeatable, KEY=VAL) πŸ’–.
  • -i, --interactive β€” run interactively (passes -i to the engine).
  • -t, --tty β€” allocate a TTY (passes -t to the engine) 🌈.
  • -w, --workdir <WORKDIR> β€” working directory inside the container.
  • -h, --help β€” print help 😌.

🫢 Arguments 🫢

  • <CMD> β€” command and arguments to run inside the container (after --).

🌈 Examples 🌈

Build the project's image and open bash in it:

mise oci run -it -- bash

Run a one-shot command with an environment variable and a mounted directory:

mise oci run -e DEBUG=1 --volume "$PWD:/work" -w /work -- npm test

Reuse a layout built earlier instead of building again:

mise oci build -o ./img && mise oci run --image-dir ./img -- node -e 'console.log(process.version)'

πŸ”₯ MISE PACKSLIP

Inspect and reset the signers mise has pinned for packslip tools πŸ‘‘

So here's the vibe: mise verifies a tool installed with the packslip: backend against the identity its project name implies, then remembers the signer it accepted β€” the way SSH remembers host keys πŸ’…. A later release from another signer, a weaker signing scheme, a repackager where the vendor signed before, or one that drops build provenance gets refused 🚫. After you confirm the change with the publisher, run mise packslip forget <PROJECT>, and update mise.lock if it records the old signer.

With no subcommand, it lists the pins (same as mise packslip pins) ✨. See https://mise.jdx.dev/dev-tools/backends/packslip.html#pinned-signers

Usage: mise packslip [OPTIONS] [COMMAND]

✨ Options ✨

  • -h, --help β€” print help πŸŽ€.

🧚 MISE PACKSLIP FORGET

Forget a project's pinned signer so the next accepted release sets it πŸ’œ

Do this after the vendor announces a new signing identity or key πŸ”‘. Name the project as in its tool identifier: github.com/owner/repo, owner/repo, or a domain such as tool.example.com, with or without packslip:. This also resets the project's remembered release-list state.

⚠️ Heads up bestie: it does not change mise.lock. If the lockfile records the old signer, delete the tool's entries and run mise lock πŸ’€.
Usage: mise packslip forget [OPTIONS] <PROJECT>

✨ Options ✨

  • -h, --help β€” print help 🌸.

🫢 Arguments 🫢

  • <PROJECT> β€” the project whose pin to drop.

🌈 Examples 🌈

Accept whichever signer the next hk release uses:

mise packslip forget github.com/jdx/hk

⭐ MISE PACKSLIP PINS

List the signer mise has pinned for each packslip project πŸŽ€

Each row is a project and the signer mise pinned the first time it accepted a release: the signing scheme, the signer identity, whether the vendor or a repackager attested it, and whether build provenance links were present βœ…. A later release that doesn't match gets refused. Iykyk.

Usage: mise packslip pins [OPTIONS]

✨ Options ✨

  • -J, --json β€” output in JSON format πŸ¦‹.
  • -h, --help β€” print help 😭.

🌈 Examples 🌈

List every pinned signer:

mise packslip pins
Project            Scheme         Signer                                              Attested by  Provenance
github.com/jdx/hk  sigstore-oidc  https://github.com/jdx/hk/.github/workflows/release.yml  vendor       yes

Include the issuer, pin time, and forge repository ID:

mise packslip pins --json

πŸ’… MISE OUTDATED

okay so this one shows you which tools are outdated β€” like, the version you have installed is older than the newest version your config actually asks for. Bestie, it lists 'em for you. For node = "20", that's the newest 20.x release; pass --bump if you wanna compare against the newest release overall instead. Then run mise upgrade to actually install the newer ones. slay.

Usage:

mise outdated [OPTIONS] [<TOOL@VERSION>] ...

✨ OPTIONS ✨

  • -b, --bump β€” compare against the newest release overall, not just the configured range. So with node = "20" in your config, mise outdated reports the newest 20.x release. With this flag the latest column shows the newest release overall, like 24.1.0, and a bump column shows the request that mise upgrade --bump would write, like 24. πŸŽ€
  • -J, --json β€” output in JSON format, for the data girlies
  • -l β€” deprecated shorthand for --bump (it's giving legacy, but it still works)
  • --inactive β€” also check installed tools that the current config does not request. By default mise outdated checks only tools that come from the current config.
  • --global β€” only check tools defined in the global config. Reports the requests in the global and system config (~/.config/mise/config.toml, /etc/mise/config.toml), even where a project config or a MISE_<TOOL>_VERSION environment variable sets its own version of the tool: basically what mise upgrade --global would install. πŸ‘‘
  • --local β€” deprecated alias for --no-global. Removed in mise 2027.7.0 β€” mark your calendars bestie.
  • --no-global β€” only check tools defined in project config files. Skips tools defined in the global config (~/.config/mise/config.toml) and tools set through MISE_<TOOL>_VERSION environment variables.
  • --monorepo β€” placeholder for future monorepo outdated checks; mise outdated --monorepo is not implemented yet. it's giving coming soon energy, don't come for her πŸ’€
  • --no-header β€” do not print the table header
  • -h, --help β€” print help

πŸ¦‹ ARGUMENTS πŸ¦‹

  • <TOOL@VERSION> β€” tools to check, such as node@20 python@3.10. When omitted it checks every tool in the global and project configs. iykyk.

🌸 EXAMPLES 🌸

Show tools with a newer version inside their configured range:

mise outdated
name    requested  current  latest  source
node    20         20.0.0   20.1.0  ~/src/app/mise.toml
python  3.11       3.11.0   3.11.1  ~/src/app/mise.toml

Compare against the newest release overall and show the request for it:

mise outdated --bump
name  requested  current  bump  latest  source
node  20         20.0.0   24    24.1.0  ~/src/app/mise.toml

Print the same information as JSON:

mise outdated --json
{
  "node": {
    "name": "node",
    "requested": "20",
    "current": "20.0.0",
    "bump": null,
    "latest": "20.1.0",
    "source": {
      "type": "mise.toml",
      "path": "/home/me/src/app/mise.toml"
    }
  }
}

Skip tools that only the global config requests:

mise outdated --no-global

Check the global config's request for claude, even inside a project that sets its own:

mise outdated --global claude --json

πŸ’– MISE PATRONS

this one is literally the sweetest β€” it shows the individuals supporting mise as Patron-tier members 🫢

It fetches the list from https://jdx.dev/patrons.json and caches it for a day; pass --refresh to fetch it now. If the fetch fails, the cached list is used. Terminals that support OSC 8 hyperlinks show each name as a link. fancy ✨

To appear here, become a patron at https://jdx.dev/sponsors.html. bestie. do it for the plot. πŸ’œ

Usage:

mise patrons [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format
  • --refresh β€” fetch the list now instead of using the cached copy
  • -h, --help β€” print help

πŸŽ€ EXAMPLES πŸŽ€

List the patrons:

mise patrons

Fetch the list now and print it as JSON:

mise patrons --refresh -J

🧚 MISE PLUGINS

manage plugins πŸ’…

Plugins add tools, backends, environment directives, or bootstrap package managers to mise. Most tools need no plugin because most registry tools use built-in backends, and mise installs a missing plugin when a configured tool needs it. so like, you're probably fine, ngl.

With no subcommand, it lists installed plugins (same as mise plugins ls; the flags below are passed to it). See https://mise.jdx.dev/plugins.html ✨

Usage:

mise plugins [OPTIONS] [COMMAND]

✨ OPTIONS ✨

  • -a, --all β€” list all available remote plugins (same as mise plugins ls-remote)
  • -c, --core β€” list the core tools built into mise instead of installed plugins
  • -u, --urls β€” show each plugin's Git URL, ref, and commit
  • --refs β€” show each plugin's Git ref and commit, such as main 1234abc
  • --user β€” list installed plugins. This is the default behavior but can be used with --core to show core and user plugins
  • -h, --help β€” print help

🌈 MISE PLUGINS INSTALL

install plugins from a configured source, Git URL, or archive πŸŽ€

Most registry tools use built-in backends and need no plugin. When a tool's backend requires a plugin, mise installs it with the tool. Use this command to install one ahead of time or from a custom source.

Pass a name that the registry or a [plugins] entry knows, a name and a URL, or only a URL. With only a URL, the plugin is named after the repository without an asdf-, mise-, or vfox- prefix. Pass several names to install several plugins. Prefix a name with vfox:, vfox-backend:, package:, or asdf: to choose the plugin type. okay that's actually so versatile of her πŸ‘‘

A Git URL may end in #ref to select a plugin commit, tag, or branch. This selects the plugin code, separately from the tool version mise use installs. two different things bestie, don't mix 'em up.

Usage:

mise plugins install [OPTIONS] [<NEW_PLUGIN>] [<GIT_URL>] [<REST>] ...

✨ OPTIONS ✨

  • -a, --all β€” install every plugin the current config needs that is not installed yet. Only plugins with a registry shorthand or a [plugins] entry can be installed this way.
  • -f, --force β€” reinstall even if the plugin is already installed
  • -j, --jobs <JOBS> β€” number of plugins to install in parallel (default: the jobs setting)
  • -v, --verbose β€” show installation output
  • -h, --help β€” print help

πŸ¦‹ ARGUMENTS πŸ¦‹

  • <NEW_PLUGIN> β€” the plugin to install, or a URL to infer its name from
  • <GIT_URL> β€” where to install from: a Git URL (optionally ending in #ref) or an archive URL

🌸 EXAMPLES 🌸

Install a plugin from a Git repository:

mise plugins install my-tool https://github.com/your-org/mise-my-tool

Pin the plugin to a tag:

mise plugins install my-tool 'https://github.com/your-org/mise-my-tool#v1.2.0'

Name the plugin after its repository (my-tool):

mise plugins install https://github.com/your-org/vfox-my-tool

Use a local plugin repository at a tag you created:

mise plugins install my-tool file:///path/to/mise-my-tool#v1.0.0

Install the plugins that the current config needs:

mise plugins install --all

link a local plugin directory into mise for development 🧚

Edits in the source directory take effect without reinstalling the plugin. literally live-reload energy, we love to see it. Pass a name and a directory, or only a directory to name the plugin after it without an asdf-, mise-, or vfox- prefix. Use the bare name, without a vfox: or package: prefix: mise detects the plugin type from the directory. This does not install a tool version. just fyi πŸ’€

Usage:

mise plugins link [OPTIONS] <NAME> [<DIR>]

✨ OPTIONS ✨

  • -f, --force β€” replace an existing plugin with the same name
  • -h, --help β€” print help

πŸŽ€ ARGUMENTS πŸŽ€

  • <NAME> β€” the plugin name, or the plugin directory when DIR is omitted
  • <DIR> β€” the local path to the plugin, such as ./mise-my-tool

πŸ’œ EXAMPLES πŸ’œ

Link ./mise-my-tool as the plugin my-tool:

mise plugins link my-tool ./mise-my-tool

Infer the name my-tool from the directory:

mise plugins link ./mise-my-tool

List versions through the linked plugin:

mise ls-remote my-tool

⭐ MISE PLUGINS LS

list installed plugins πŸ’…

Use --core to list the core tools built into mise instead, or --core --user for both. --outdated checks each plugin's Git remote for newer plugin code; it does not compare tool versions. Use mise ls for installed tool versions and mise registry for tools you can install. very important distinction, bestie, don't be out here confusing them 😭

Usage:

mise plugins ls [OPTIONS]

✨ OPTIONS ✨

  • -a, --all β€” list all available remote plugins (same as mise plugins ls-remote)
  • -c, --core β€” list the core tools built into mise instead of installed plugins
  • -o, --outdated β€” only show plugins whose Git remote has newer commits
  • -u, --urls β€” show each plugin's Git URL, ref, and commit
  • --refs β€” show each plugin's Git ref and commit, such as main 1234abc
  • --user β€” list installed plugins. This is the default behavior but can be used with --core to show core and user plugins
  • -h, --help β€” print help

🌸 EXAMPLES 🌸

List installed plugins:

mise plugins ls

Show each plugin's Git URL, ref, and commit:

mise plugins ls --urls

List core tools and installed plugins:

mise plugins ls --core --user

List plugins whose Git remote has newer commits:

mise plugins ls --outdated

πŸ¦‹ MISE PLUGINS LS-REMOTE

list registry tools that have an asdf or vfox plugin backend ✨

Each line is a registry shorthand that lists an asdf or vfox plugin among its backends; mise may still install the tool through another backend first. * marks plugins you have installed. Entries from the shorthands_file setting are listed too. Use mise registry to list every registry tool and its backends in order. slay πŸ’…

Usage:

mise plugins ls-remote [OPTIONS]

✨ OPTIONS ✨

  • -u, --urls β€” show the plugin source for each shorthand, e.g. vfox:jdx/vfox-poetry
  • --only-names β€” only show the name of each plugin, without the * marking installed plugins
  • -h, --help β€” print help

πŸŽ€ EXAMPLES πŸŽ€

List registry tools with a plugin backend:

mise plugins ls-remote

πŸ’… MISE PLUGINS UNINSTALL πŸ’…

Okay bestie, this one removes a plugin you already installed. Bye-bye πŸ‘‹

So the tea is: the tool versions you installed stay put unless you pass --purge β€” that's the one that also wipes a tool plugin's installs, downloads, and cache. 🧹

⚠️ Heads up though: --purge does not remove the tools of a backend plugin (<plugin>:<tool>). You gotta uninstall those first with mise uninstall --all <plugin>:<tool>. No cap, that's the rule. πŸ™ˆ

Usage:

mise plugins uninstall [OPTIONS] [<PLUGIN>] ...

Options:

  • -a, --all β€” remove all the plugins. every single one. πŸ”₯
  • -p, --purge β€” also nukes a tool plugin's installs, downloads, and cache
  • -h, --help β€” print help

Arguments:

  • <PLUGIN> β€” the plugins you want to remove

Examples:

Remove the plugin but keep the versions it installed πŸ’–

mise plugins uninstall my-tool

Also delete the versions it installed 😭

mise plugins uninstall --purge my-tool

✨ MISE PLUGINS UPDATE ✨

Updates your installed plugins, periodt.

If you give it no names, it updates every installed plugin. Important vibe check: this updates the plugin code, not the tool versions it manages. 🧠

Also good to know: linked local plugins get skipped entirely, and plugins installed from an archive can't be updated with Git. That's just how it is, bestie. 🫢

Usage:

mise plugins update [OPTIONS] [<PLUGIN>] ...

Options:

  • -j, --jobs <JOBS> β€” how many plugins to update in parallel (default: the jobs setting)
  • -h, --help β€” print help

Arguments:

  • <PLUGIN> β€” plugins to update; append #ref to switch to a branch, tag, or commit πŸ‘‘

Examples:

Update every installed plugin 🌈

mise plugins update

Update just one plugin

mise plugins update my-tool

Switch a plugin over to its main branch, slay

mise plugins update my-tool#main

πŸ¦‹ MISE DEPS πŸ¦‹

[experimental] β€” yes it says experimental, girlies, act accordingly πŸ’€

Manages project dependencies. Like node_modules and friends. And it does this separately from the tools that mise install handles. Two different worlds, both iconic. ✨

So here's the lore: each provider is one package-manager step β€” either a built-in one like npm or uv, or a custom [deps.<name>] command. A provider only runs when its inputs changed or its outputs are missing, and --explain tells you why. πŸ”

With no subcommand, it runs mise deps install. And providers with auto = true also run before mise exec and mise run β€” unless you pass --no-deps. πŸ™…

Usage:

mise deps [OPTIONS] [<PROVIDER>] [COMMAND]

Options:

  • --explain β€” shows why a provider is fresh or stale, then exits non-zero unless it's fresh (requires a PROVIDER argument)
  • -f, --force β€” runs providers even when their outputs are already up to date
  • -n, --dry-run β€” shows which providers would run, without actually running them
  • --list β€” lists configured providers with their status, sources, and outputs
  • --monorepo β€” also runs providers from every config root in [monorepo].config_roots

Requires monorepo_root = true and an explicit config_roots list in the monorepo root's config. Provider names then include their root, like //apps/api:uv. πŸ™οΈ

Environment: MISE_MONOREPO

  • --only <PROVIDER> β€” run only these providers
  • --skip <PROVIDER> β€” skip these providers
  • -h, --help β€” print help

Arguments:

  • <PROVIDER> β€” run only this provider, or explain it with --explain

Examples:

Run every provider that's out of date πŸƒβ€β™€οΈ

mise deps

Show why the npm provider would or wouldn't run

mise deps install npm --explain

Include providers from every monorepo config root

mise deps --monorepo

πŸŽ€ MISE DEPS ADD πŸŽ€

Adds packages to your project's dependencies. Cute, quick, done. πŸ’…

It runs the package manager's own add command, which updates the project's manifest (for npm, package.json) and its lockfile β€” not mise.toml. Big distinction, don't get it twisted. 🧠

If what you actually want is a CLI tool from npm for mise to manage, use mise use npm:<package> instead. Different tool for a different job, iykyk.

Name each package as <ecosystem>:<package>, like npm:react or npm:@types/react@19. See https://mise.jdx.dev/dev-tools/deps.html#adding-and-removing-packages. πŸ”—

Usage:

mise deps add [OPTIONS] <PACKAGES> ...

Options:

  • -D, --dev β€” add it as a development dependency
  • -h, --help β€” print help

Arguments:

  • <PACKAGES> β€” packages to add, like npm:react or npm:@types/react@19

Examples:

Add react to package.json βš›οΈ

mise deps add npm:react

Add vitest as a dev dependency

mise deps add -D npm:vitest

🌸 MISE DEPS INSTALL 🌸

Installs your project dependencies. The main character of the deps commands, honestly. πŸ‘‘

It runs each provider whose inputs changed or whose outputs are missing. Pass PROVIDER to run only that one, --force to run regardless of freshness, or --explain PROVIDER to see why it would or wouldn't run. With --explain, mise runs nothing and exits non-zero unless the provider is fresh. πŸ”βœ¨

Usage:

mise deps install [OPTIONS] [<PROVIDER>]

Options:

  • --explain β€” shows why a provider is fresh or stale, and exits non-zero unless it's fresh (requires a PROVIDER argument)
  • -f, --force β€” runs providers even when their outputs are up to date
  • -n, --dry-run β€” shows which providers would run, without running them
  • --list β€” lists configured providers with their status, sources, and outputs
  • --monorepo β€” also runs providers from every config root in [monorepo].config_roots

Requires monorepo_root = true and an explicit config_roots list in the monorepo root's config. Provider names then include their root, like //apps/api:uv. πŸ™οΈ

Environment: MISE_MONOREPO

  • --only <PROVIDER> β€” run only these providers
  • --skip <PROVIDER> β€” skip these providers
  • -h, --help β€” print help

Arguments:

  • <PROVIDER> β€” run only this provider, or explain it with --explain

Examples:

Run every provider that's out of date πŸƒβ€β™€οΈ

mise deps install

Run every provider, even the fresh ones πŸ’ͺ

mise deps install --force

Show which providers would run

mise deps install --dry-run

🧚 MISE DEPS REMOVE 🧚

Removes packages from your project's dependencies. The reverse arc. πŸ¦‹

Runs the package manager's remove command, which updates the project's manifest and its lockfile β€” not mise.toml, bestie, same deal as add. Name each package as <ecosystem>:<package>, like npm:lodash. πŸ—‘οΈ

Usage:

mise deps remove [OPTIONS] <PACKAGES> ...

Options:

  • -h, --help β€” print help

Arguments:

  • <PACKAGES> β€” packages to remove, like npm:lodash

Examples:

Remove lodash from package.json

mise deps remove npm:lodash

πŸ’€ MISE PRUNE πŸ’€

Deletes tool versions that nothing uses. Spring cleaning but for your installs. 🧹✨

Here's the mechanics, stay with me: mise records each config file it loads (in ~/.local/state/mise/tracked-configs) and each tool stub it runs (in ~/.local/state/mise/tracked-stubs). mise prune deletes installed versions that none of them selects. So a config requesting node = "20" keeps only the 20.x version it resolves to. πŸ“Œ

Versions installed only for mise exec <TOOL>@<VERSION> or through MISE_<TOOL>_VERSION? Deleted. Gone. 😭

But versions that a running process was started from are kept β€” so a long-running program keeps its files. She's considerate like that. 🫢

It also forgets tracked, trusted, and ignored config files that no longer exist. Pass --tools or --configs if you only want one of the two. And you can preview the versions it would delete with mise ls --prunable. πŸ‘€

Usage:

mise prune [OPTIONS] [<INSTALLED_TOOL>] ...

Options:

  • -n, --dry-run β€” show what would change without changing anything
  • --configs β€” only forget tracked, trusted, and ignored config files that no longer exist
  • --dry-run-code β€” like --dry-run, but exits with code 1 if there are tools to prune

Use it in scripts that check whether tools need pruning. πŸ€–

  • --monorepo β€” placeholder for future monorepo pruning; mise prune --monorepo is not implemented yet.
Lowkey don't come for me, it literally says not implemented yet. πŸ™ˆ
  • --tools β€” only delete unused tool versions
  • -h, --help β€” print help

Arguments:

  • <INSTALLED_TOOL> β€” prune only these tools

Examples:

Preview what would be deleted and why πŸ”

mise prune --dry-run mise node@20.0.0 is prunable: node is required
at 20.19.5 by ~/src/app/mise.toml mise node@20.0.0 [dryrun]  remove
~/.local/share/mise/installs/node/20.0.0, ~/.cache/mise/node/20.0.0

Delete unused node versions only 🟒

mise prune --tools node

πŸ‘‘ MISE REGISTRY πŸ‘‘

Lists registry shorthand names and their backends. The directory of nicknames, basically. πŸ“–

The registry maps short names to backends β€” for example, node uses the built-in node backend (core:node). When a tool lists several backends, mise uses the first one that this platform and your settings allow. And an explicit identifier like aqua:jqlang/jq, a [tool_alias] entry, or a MISE_BACKENDS_<TOOL> environment variable overrides that choice. πŸ’…

⚠️ Real talk: this is not a list of every tool mise can install. For a source without a registry shorthand, use an explicit identifier like github:owner/repo.

Usage:

mise registry [OPTIONS] [<NAME>]

Options:

  • -b, --backend <BACKEND> β€” show only tools for this backend
  • --complete β€” print all tools with descriptions for shell completions
  • --hide-aliased β€” hide names that are aliases of another registry tool
  • -J, --json β€” output in JSON format
  • --security β€” include security features for each tool's backends in JSON output

Requires --json. Features are merged across a tool's backends. Each backend is resolved separately, so this slows down a full listing. 🐌

  • -h, --help β€” print help

Arguments:

  • <NAME> β€” show only this tool's backends, in the order mise prefers them

Examples:

List every registry tool and its backends 🌈

mise registry

Show the backends for one tool

mise registry jq aqua:jqlang/jq asdf:mise-plugins/asdf-jq

List the tools that have an aqua backend 🌊

mise registry --backend aqua

Print the registry as JSON

mise registry --json

πŸ“ MISE RESHIM πŸ“

Creates shims for executables provided by installed tools. The glow-up pass. ✨

Run this when an executable was added to an existing installation outside mise β€” for example, after a language package manager installed a CLI globally. It rebuilds your shim directory (~/.local/share/mise/shims by default). And --system rebuilds the system shim directory used by mise install --system. πŸ› οΈ

Shims are created for all installed versions. When invoked, a shim picks the version to run from the current config. --force rebuilds mise-owned shims β€” it does not turn unrelated files into mise-owned shims. Don't try it, bestie, it won't. πŸ’€

See https://mise.jdx.dev/dev-tools/shims.html πŸ”—

Usage:

mise reshim [OPTIONS] [<TOOL>] [<VERSION>]

Options:

  • -f, --force β€” rebuild all mise-owned shims
  • --system β€” rebuild the system shims, for tools installed with mise install --system
  • -h, --help β€” print help

Examples:

Rebuild shims, then run node through its shim 🟒

mise reshim ~/.local/share/mise/shims/node -v v24.11.0

πŸ’… MISE RUN πŸ’…

Run tasks and their dependencies

Okay so bestie, this is the command. Run one task with mise run TASK [ARGS...], or run a whole bunch at once by sticking ::: between them. Lowkey important: put your mise flags before the task name, because everything after it gets yeeted straight to the task itself. And if you give it no task at all? mise runs the default task if there is one, or opens up a task picker in an interactive terminal. ✨

Tasks come from [tasks] in mise.toml and also from task directories like mise-tasks/. Here's the iconic part: a task with sources and outputs gets skipped while its outputs are up to date β€” and --force runs it anyway, no cap. For example:

[tasks.build]
run = "npm run build"
sources = ["src/**/*.ts", "package.json", "package-lock.json"]
outputs = ["dist/**/*.js"]

The experimental artifact cache (that's a task's cache field, iykyk) has its own separate --task-cache controls. πŸŽ€

Wanna create a script task? Run mise tasks add --file hello -- echo hello, then mise run hello. Literally that easy. See https://mise.jdx.dev/tasks/running-tasks.html

Usage: mise run [OPTIONS] [TASK] [ARGS]…

✨ OPTIONS ✨

  • --affected β€” Run matching tasks only in projects affected by Git changes. Counts committed changes between the base and head revisions, plus staged, unstaged, and untracked changes in the working tree when the head revision is the checked-out commit. Requires a monorepo root (monorepo_root = true).
  • --affected-base <REV> β€” Git base revision for --affected. Defaults to MISE_AFFECTED_BASE, CI metadata, or HEAD~1.
  • --affected-committed β€” Count committed changes between the base and head revisions. Alone, it ignores the working tree. Combines with --affected-uncommitted and --affected-untracked. With none of the three, every source counts (the working-tree sources only when the head revision is the checked-out commit). Also set by MISE_AFFECTED_COMMITTED.
  • --affected-explain β€” Explain why --affected selected each project and task. πŸ•΅οΈβ€β™€οΈ
  • --affected-head <REV> β€” Git head revision for --affected. Defaults to MISE_AFFECTED_HEAD, CI metadata, or HEAD.
  • --affected-json β€” Print the affected projects and tasks as JSON without running tasks.
  • --affected-uncommitted β€” Count staged and unstaged changes to tracked files. Combines with the other source flags. Alone, it ignores committed changes. Needs the head revision to be the current checkout. Also set by MISE_AFFECTED_UNCOMMITTED.
  • --affected-untracked β€” Count untracked files that Git does not ignore. Combines with the other source flags. Alone, it ignores committed changes. Needs the head revision to be the current checkout. Also set by MISE_AFFECTED_UNTRACKED.
  • --all β€” Open the task picker with tasks from every project in the monorepo.
  • -c, --continue-on-error β€” Continue running tasks even if one fails. Resilient queen behavior. πŸ‘‘
  • -C, --cd <DIR> β€” Change to this directory before running the tasks.
  • -f, --force β€” Run the tasks even if their outputs are up to date.
  • -j, --jobs <JOBS> β€” Number of tasks to run in parallel (default: the jobs setting). Values below 1 are treated as 1. Environment: MISE_JOBS.
  • -n, --dry-run β€” Print the tasks in the order they would run, without running them. A little peek, no commitment. πŸ™ˆ
  • -o, --output <OUTPUT> β€” How task output is displayed:
    • prefix β€” Print stdout/stderr by line, prefixed with the task's label
    • interleave β€” Print directly to stdout/stderr instead of by line
    • replacing β€” Stdout is replaced each time, stderr is printed as is
    • timed β€” Only show stdout lines if they are displayed for more than 1 second
    • keep-order β€” Print stdout/stderr by line, prefixed with the task's label, but keep the order of the output
    • quiet β€” Deprecated; use --output interleave --quiet
    • silent β€” Do not show any output, including the task's stdout and stderr, except errors

Environment: MISE_TASK_OUTPUT.

  • -q, --quiet β€” Do not show extra output. Environment: MISE_QUIET.
  • -r, --raw β€” Connect the tasks directly to stdin, stdout, and stderr instead of reading their output by line. Redactions are not applied, and tasks run one at a time. Set the raw setting to make this the default.
  • --secrets <SECRET> β€” [experimental] Give the named tasks these secrets (comma-separated); their dependencies and subtasks do not get them. Put this flag before the task name. Not allowed in safe mode.
  • --secrets-all β€” [experimental] Give the named tasks every secret the project can inject; their dependencies and subtasks do not get them. Covers the fnox secrets with env = true or env = "exec", never those with env = false. Put this flag before the task name. Not allowed in safe mode. πŸ”
  • -s, --shell <SHELL> β€” Shell used to run TOML tasks that do not set their own shell. Defaults to sh -o errexit -c on Unix and cmd /c on Windows, from the unix_default_inline_shell_args or windows_default_inline_shell_args setting. A task's shell property takes precedence over this flag.
  • -S, --silent β€” Do not show any output except for errors. Environment: MISE_SILENT.
  • -t, --tool <TOOL@VERSION> β€” Extra tools to use with the tasks, e.g. node@24 python@3.13.
  • --allow-env <VAR> β€” Allow a specific env var through (implies --deny-env for everything else). Supports wildcards, such as --allow-env='MYAPP_*'.
  • --allow-net <HOST> β€” Allow network access only to HOST (not supported on any platform). Per-host filtering does not work: Linux and macOS exit with an error, and Windows runs the task without network restrictions. See https://mise.jdx.dev/sandboxing.html#access-to-particular-hosts
πŸ’€ Heads up bestie, this one is genuinely a no-go on every single platform. Don't be shocked when it errors out.
  • --allow-read <PATH> β€” Allow reads from a specific path (implies --deny-read for everything else).
  • --allow-write <PATH> β€” Allow writes to a specific path (implies --deny-write for everything else).
  • --deny-all β€” Block reads, writes, network, and env vars. Full lockdown mode. 🚫
  • --deny-env β€” Block env var inheritance except PATH, HOME, USER, SHELL, TERM, COLORTERM, and LANG. On Windows it also keeps the variables programs need to start, such as SystemRoot and TEMP.
  • --deny-net β€” Block all network access.
  • --deny-read β€” Block filesystem reads (system libraries and tool directories stay readable).
  • --deny-write β€” Block filesystem writes except temporary and device paths (/tmp, /dev).
  • --fresh-env β€” Bypass the environment cache and recompute the environment.
  • --no-cache β€” Do not use the cache for remote tasks. Environment: MISE_TASK_REMOTE_NO_CACHE.
  • --no-deps β€” Do not run [deps] providers that have auto = true before the tasks.
  • --no-timings β€” Hide the elapsed time printed after each task completes. Set task.timings = false to hide it by default.
  • --skip-deps β€” Run only the named tasks, not the tasks they depend on. Environment: MISE_TASK_SKIP_DEPENDS.
  • --skip-tools β€” Do not install missing tools before running the tasks. Set task.run_auto_install = false to make this the default.
  • --task-cache <TASK_CACHE> β€” [experimental] Set artifact cache access for this run:
    • read-write β€” Read cached results and write new results
    • read-only β€” Read cached results without writing new results
    • write-only β€” Write new results without reading cached results
    • off β€” Disable the artifact cache
    • local-only β€” Read and write only the local cache, skipping any remote cache

Default: read-write. Environment: MISE_TASK_CACHE.

  • --task-cache-explain β€” [experimental] Explain the inputs that produced each task's artifact cache key.
  • --task-cache-explain-json β€” [experimental] Print cache-key input details as JSON Lines without running tasks (requires --dry-run).
  • --task-cache-stats β€” [experimental] Report artifact cache hits, restored bytes, and time saved.
  • --timeout <TIMEOUT> β€” Stop the run if it takes longer than this, e.g. 30s or 5m. Overrides the task.timeout setting. ⏰
  • --timings β€” Show the elapsed time after each task completes. Set task.timings = true to show it by default.

🌈 Examples 🌈

Run the "lint" task, defined in mise.toml or as a script

mise run lint

Run "build" even if its outputs are up to date

mise run --force build

Run "test" connected directly to the terminal, one task at a time

mise run --raw test

Run the "lint", "test", and "check" tasks in parallel

mise run lint ::: test ::: check

Run several tasks, each with its own arguments

mise run cmd1 arg1 arg2 ::: cmd2 arg1 arg2

Run tasks one at a time

mise run -j 1 lint ::: test

Run every task that matches a pattern

mise run 'test:*'

Run a task in a monorepo project

mise run //services/api:build

Give "deploy" the DEPLOY_KEY secret (experimental); its dependencies do not get it

mise run --secrets DEPLOY_KEY deploy

Bestie, this is your tool-hunting era. ✨ It searches for available tools β€” like, it goes through the registry and the tool lists of your installed backend plugins looking for stuff that matches NAME. And when literally nothing matches? It keeps going and searches the aqua registry too. Obsessed with the dedication honestly.

Wanna look in a package registry? Prefix NAME with npm:, cargo:, gem:, or dotnet: and it'll search that one too. Or just yeet --all at it and search every source, no cap.

Matching is fuzzy by default (vibe check, not exact). Use --match-type equal or --match-type contains when you want it strict.

Usage: mise search [OPTIONS] [<NAME>]

✨ OPTIONS ✨

  • -a, --all β€” search every single source: the registry, aqua, installed backend plugins, and the npm, cargo, gem, and dotnet package registries 🫢
  • -i, --interactive β€” show an interactive search menu, very choose-your-own-adventure
  • -m, --match-type <MATCH_TYPE> β€” match type: equal, contains, or fuzzy. Default: fuzzy
  • --no-header β€” don't print the table header (minimalist queen)
  • --complete β€” print all tools with descriptions, for shell completions
  • --complete-ids β€” print only tool identifiers, for shell completions
  • -h, --help β€” print help

Arguments:

  • <NAME> β€” the tool to search for

πŸŽ€ EXAMPLES πŸŽ€

Fuzzy-search the registry for jq:

mise search jq
Tool   Description
jq     Command-line JSON processor. https://github.com/jqlang/jq
jqp    A TUI playground to experiment with jq. https://github.com/noahgorstein/jqp
jiq    jid on jq - interactive JSON query tool using jq expressions. https://github.com/fiatjaf/jiq
gojq   Pure Go implementation of jq. https://github.com/itchyny/gojq

Look up one npm package by its exact name:

mise search --match-type equal npm:typescript-language-server
Tool                            Description
npm:typescript-language-server  Language Server Protocol (LSP) implementation for TypeScript using tsserver

Pick a tool from a filterable list:

mise search --interactive

πŸ” MISE SECRETS

[experimental] β€” this one inspects the project's secrets source, iykyk. πŸ•΅οΈβ€β™€οΈ

With no subcommand it just lists secret names (same as mise secrets ls; the flags below get passed along to it). More deets at https://mise.jdx.dev/environments/secrets/fnox.html

Usage: mise secrets [OPTIONS] [COMMAND]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format
  • --no-header β€” don't print the table header
  • -h, --help β€” print help

πŸ“‹ MISE SECRETS LS

[experimental] β€” lists secret names from the project's secrets source. πŸ’… Names and metadata only, never values β€” we respect privacy in this house.

The source is declared in the project's mise.toml with [secrets.fnox]. A line describing the source goes to stderr and the table goes to stdout (so you can pipe the table, iconic).

Columns, bestie:

  • ENV: the key's env setting in the source: true, exec, false, or - if unset
  • FILE: whether the value is handed over as a file
  • SCOPES: where mise can grant the key: run (tasks) and exec (mise exec)
  • TASKS: the tasks that request the key

A SCOPES value of - means the key cannot be granted, periodt. And a file secret can be granted to tasks only, because mise exec can't clean up the file after it hands the process over. 🫠

Usage: mise secrets ls [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format
  • --no-header β€” don't print the table header
  • --complete β€” render completions: the injectable key names, one per line
  • -h, --help β€” print help

πŸŽ€ EXAMPLES πŸŽ€

List the secret names and how each can be granted:

mise secrets ls
KEY                ENV    FILE  SCOPES     TASKS     DESCRIPTION
AWS_ACCESS_KEY_ID  -      no    run, exec            (lease aws)
DATABASE_URL       true   no    run, exec  deploy    app database
GCP_SA_JSON        exec   yes   run                  service account
SIGNING_KEY        false  no    -          release   signing key

πŸ”„ MISE SELF-UPDATE

Update mise itself β€” glow-up time for your binary. ✨

It installs the newest stable release (or VERSION) from GitHub Releases and verifies its signature before replacing the running binary. Safety first, always. πŸ”₯

Without VERSION, releases younger than the minimum release age get skipped: the self_update.minimum_release_age setting, then minimum_release_age, else 24h. Installed plugins get updated too unless you pass --no-plugins. And if you set self_update.auto, it updates automatically β€” main character automation energy.

Heads up bestie: if a package manager like Homebrew or apt installed mise, update it with that package manager instead: https://mise.jdx.dev/installing-mise.html#updating β€” and packagers can disable this command entirely: https://mise.jdx.dev/packaging.html
Usage: mise self-update [OPTIONS] [<VERSION>]

✨ OPTIONS ✨

  • --minimum-release-age <MINIMUM_RELEASE_AGE> β€” minimum release age for this update, such as 7d. Defaults to the self_update.minimum_release_age setting, then the minimum_release_age setting, else 24h
  • -f, --force β€” update even if already up to date. Also updates when the package that installed mise has disabled self-update
  • -y, --yes β€” skip confirmation prompt (no "are you sure" jumpscare)
  • --no-plugins β€” do not update installed plugins
  • -h, --help β€” print help

Arguments:

  • <VERSION> β€” update to a specific version, skipping the minimum release age

πŸŽ€ EXAMPLES πŸŽ€

Update to the newest eligible release:

mise self-update

Install a specific release:

mise self-update 2026.10.4

Update without prompting or touching plugins:

mise self-update -y --no-plugins

🌸 MISE SET

Set, show, or list environment variables in mise.toml β€” the multitasker of the family. 🫢

So mise set KEY=VALUE writes to the lowest-precedence TOML file in the nearest config directory (mise.toml rather than mise.local.toml), and it'll create mise.toml in the current directory if there isn't one. Run it in your home directory and it writes to the global config instead. mise set KEY prints one value, and plain mise set lists every variable with its source file. Need to write somewhere else? Use --global, --file, or -E <env>. See https://mise.jdx.dev/configuration.html#target-file-for-write-operations

Usage: mise set [OPTIONS] [<ENV_VAR>] ...

✨ OPTIONS ✨

  • -E, --env <ENV> β€” write to mise.<ENV>.toml in the current directory, or to .mise.<ENV>.toml if that one exists
  • -g, --global β€” set the environment variable in the global config file
  • --override β€” set the environment variable in the global override file, config.override.toml. This override file outranks all project config. With --env, it writes config.<ENV>.override.toml instead. See https://mise.jdx.dev/configuration.html#override-file
  • --age-encrypt β€” [experimental] encrypt the value with age before storing πŸ”
  • --age-key-file <PATH> β€” [experimental] age identity file whose public keys to encrypt to. Without --age-recipient, --age-ssh-recipient, or --age-key-file, mise encrypts to the identities in the age.key_file setting (or ~/.config/mise/age.txt if it exists) and to ~/.ssh/id_ed25519 and ~/.ssh/id_rsa when they exist
  • --age-recipient <RECIPIENT> β€” [experimental] age recipient (x25519 public key) for encryption. Can be used multiple times. Requires --age-encrypt
  • --age-ssh-recipient <PATH_OR_PUBKEY> β€” [experimental] SSH recipient (public key or path) for age encryption. Can be used multiple times. Requires --age-encrypt
  • --complete β€” render completions
  • --file, --path <FILE> β€” the TOML file to update. Can be a file or a directory; for a directory, mise uses the config file already in it, or creates one named by MISE_DEFAULT_CONFIG_FILENAME (default mise.toml): https://mise.jdx.dev/configuration/settings.html#default_config_filename β€” to move the global config file, set MISE_GLOBAL_CONFIG_FILE: https://mise.jdx.dev/configuration/settings.html#global_config_file
  • --no-redact β€” show raw values instead of redacting secrets (careful, bestie πŸ‘€)
  • --prompt β€” prompt for environment variable values (input is masked only with --age-encrypt)
  • --remove, --rm, --unset <ENV_KEY> β€” remove the environment variable from the config file. Can be used multiple times
  • --stdin β€” read the value from stdin, for multiline input. Pass a single key without a value; the value is read from stdin until EOF
  • -h, --help β€” print help

Arguments:

  • <ENV_VAR> β€” environment variables to set, such as NODE_ENV=production

πŸŽ€ EXAMPLES πŸŽ€

Set NODE_ENV in mise.toml:

mise set NODE_ENV=production

Show one variable's value:

mise set NODE_ENV
production

List variables, their values, and their source files:

mise set

Write the variable to mise.staging.toml:

mise set -E staging NODE_ENV=staging

Prompt for the value; input is visible unless you add --age-encrypt:

mise set --prompt PASSWORD

Read a multiline value from stdin:

cat private.key | mise set --stdin MY_KEY

Prompt with hidden input and store the value encrypted with age (experimental):

mise set --age-encrypt --prompt API_KEY

βš™οΈ MISE SETTINGS

Manage settings β€” the control room of mise, lowkey. πŸŽ›οΈ

With no arguments, it lists the settings set in config files (same as mise settings ls). With SETTING, it prints that setting's effective value. With SETTING=VALUE or SETTING VALUE, it writes it to the global config (~/.config/mise/config.toml), or to the nearest project config if you pass --local. Every setting is described at https://mise.jdx.dev/configuration/settings.html πŸ’–

Usage: mise settings [OPTIONS] [<SETTING>] [<VALUE>] [COMMAND]

✨ OPTIONS ✨

  • -a, --all β€” list all settings
  • -J, --json β€” output in JSON format
  • -l, --local β€” use only the nearest project config. Reads only its explicit settings, or writes to it instead of the global config
  • -T, --toml β€” output in TOML format
  • --complete β€” print all settings with descriptions, for shell completions
  • --json-extended β€” output in JSON format with sources
  • -h, --help β€” print help

Arguments:

  • <SETTING> β€” only show this setting, or the settings under this prefix such as python
  • <VALUE> β€” the value to set

πŸŽ€ EXAMPLES πŸŽ€

List settings set in config files:

mise settings

Show the effective value of one setting:

mise settings jobs

Set jobs in the global config:

mise settings jobs=4

Set a setting in the project config:

mise settings --local node.mirror_url https://npmmirror.com/mirrors/node/

πŸ’– MISE SETTINGS ADD πŸ’–

Append a value to an array setting, bestie β€” like adding one more sticker to your already-iconic water bottle πŸŽ€

It adds the value to an array setting such as disable_hints, and it keeps the existing entries (no erasing your past self, we love growth ✨). Writes ~/.config/mise/config.toml, or the nearest project config if you pass --local.

Usage: mise settings add [OPTIONS] <SETTING> [<VALUE>]

🌸 OPTIONS 🌸

  • -l, --local β€” Write to the nearest project config instead of the global config.

And what even is the nearest project config? It's the lowest-precedence TOML file in the nearest directory that has one, or ./mise.toml. That's the whole vibe check, no cap.

  • --override β€” Write to the global override file, config.override.toml.

This file outranks all project config, so this setting wins over the same setting in a project's mise.toml. Main character energy, honestly πŸ‘‘

  • -h, --help β€” Print help.

πŸ’œ ARGUMENTS πŸ’œ

  • <SETTING> β€” The array setting to append to. Obviously.
  • <VALUE> β€” The value to append (or you can pass SETTING=VALUE instead, we're flexible like that 🫢).

πŸ¦‹ EXAMPLES πŸ¦‹

Stop showing the python_multi hint:

mise settings add disable_hints python_multi

✨ MISE SETTINGS GET ✨

Show the effective value of a setting β€” like, the actual truth after everyone's had their say πŸ’…

It includes defaults, config files, and environment overrides, so you get the full picture. But if you pass --local, it reads only the explicit settings in the nearest project config β€” and a setting that is not set there is an error. Also, an optional setting with no default that is not set anywhere (think python.compile) is reported as not set and exits with an error too. So dramatic 😭

If you want to inspect just one file, use mise config get settings.KEY --file path/to/mise.toml.

Usage: mise settings get [OPTIONS] <SETTING>

πŸŽ€ OPTIONS πŸŽ€

  • -l, --local β€” Read only the explicit settings in the nearest project config.
  • -h, --help β€” Print help.

πŸ“ ARGUMENTS πŸ“

  • <SETTING> β€” The setting to show.

🌈 EXAMPLES 🌈

Show the effective number of parallel jobs:

mise settings get jobs

Show the value set in the project config:

mise settings get --local experimental

🧚 MISE SETTINGS LS 🧚

List configured settings and their sources β€” the receipts, the provenance, the where did this even come from ✨

By default it lists the settings set in loaded TOML config files. --all also includes the effective value of every other setting. --local lists only the nearest project config, and --json-extended adds source information to the JSON output. If you just want one effective value, that's mise settings get SETTING.

Usage: mise settings ls [OPTIONS] [<SETTING>]

πŸ’– OPTIONS πŸ’–

  • -a, --all β€” List all settings.
  • -J, --json β€” Output in JSON format.
  • -l, --local β€” Use only the nearest project config.

Reads only its explicit settings β€” or writes to it instead of the global config.

  • -T, --toml β€” Output in TOML format.
  • --complete β€” Print all settings with descriptions for shell completions.
  • --json-extended β€” Output in JSON format with sources. Love me some sources πŸ’…
  • -h, --help β€” Print help.

πŸ¦‹ ARGUMENTS πŸ¦‹

  • <SETTING> β€” Only show this setting, or the settings under this prefix such as python. Filtering queen πŸ‘‘

🌸 EXAMPLES 🌸

List settings set in config files:

mise settings ls

Include settings left at their defaults:

mise settings ls --all

Show the python settings as JSON with their sources:

mise settings ls python --json-extended

πŸ‘‘ MISE SETTINGS SET πŸ‘‘

Set a setting. Yes, just set it. Iconic, decisive, periodt πŸ’…

It writes ~/.config/mise/config.toml, or the nearest project config with --local.

⚠️ Okay so this is the important bit: settings that mise reads before loading config files cannot be set here. Set global_config_file and similar through their environment variables, and ceiling_paths and similar in a miserc.toml file or their environment variables. Also, --local refuses settings that only the global config can set, such as yes. That's just the rules, bestie 🫢

See https://mise.jdx.dev/configuration/settings.html

Usage: mise settings set [OPTIONS] <SETTING> [<VALUE>]

πŸ’œ OPTIONS πŸ’œ

  • -l, --local β€” Write to the nearest project config instead of the global config.

Reminder: the nearest project config is the lowest-precedence TOML file in the nearest directory that has one, or ./mise.toml.

  • --override β€” Write to the global override file, config.override.toml.

The override file outranks all project config, so the setting wins over the same setting in a project's mise.toml. It's giving "final say" energy πŸ”₯

  • -h, --help β€” Print help.

πŸŽ€ ARGUMENTS πŸŽ€

  • <SETTING> β€” The setting to set.
  • <VALUE> β€” The value to set (or pass SETTING=VALUE, you know the drill).

🌈 EXAMPLES 🌈

Run up to 4 jobs in parallel:

mise settings set jobs 4

Enable experimental features in the project config:

mise settings set --local experimental=true

πŸ’€ MISE SETTINGS UNSET πŸ’€

Remove a setting from the global or project config. It's called closure, bestie ✨

It edits ~/.config/mise/config.toml, or the nearest project config with --local. After that, the setting falls back to its default or to a value from another config file. Bye bye, you will not be missed (jk you might come back) 😭

Usage: mise settings unset [OPTIONS] <KEY>

πŸ“ OPTIONS πŸ“

  • -l, --local β€” Write to the nearest project config instead of the global config.

The nearest project config is the lowest-precedence TOML file in the nearest directory that has one, or ./mise.toml.

  • --override β€” Write to the global override file, config.override.toml.

The override file outranks all project config, so the setting wins over the same setting in a project's mise.toml.

  • -h, --help β€” Print help.

πŸ¦‹ ARGUMENTS πŸ¦‹

  • <KEY> β€” The setting to remove.

🌸 EXAMPLES 🌸

Remove jobs from the global config:

mise settings unset jobs

🐚 MISE SHELL 🐚

Set a tool version for the current shell session β€” temporary, dramatic, effective πŸ’…

It installs the version if needed, then sets MISE_<TOOL>_VERSION (like MISE_NODE_VERSION) to the resolved version in the current shell. That overrides config files until you close the shell or run mise shell --unset <TOOL> β€” or mise shell --unset --all to remove every version set this way.

✨ Requires mise activate: the shell function it defines is what actually applies the variable that this command prints. No activation, no magic 🫢
Usage: mise shell [OPTIONS] [<TOOL@VERSION>] ...

πŸŽ€ OPTIONS πŸŽ€

  • -j, --jobs <JOBS> β€” Number of jobs to run in parallel (default: the jobs setting).

Environment: MISE_JOBS

  • -u, --unset β€” Remove a version set earlier with mise shell.
  • --all β€” With --unset, remove every MISE_<TOOL>_VERSION in this shell.

Heads up: this includes any you exported yourself, not only those set by mise shell. So, like, be aware 😳

  • --raw β€” Connect the install commands' stdin, stdout, and stderr to the terminal.

Implies --jobs=1.

  • -h, --help β€” Print help.

πŸ’– ARGUMENTS πŸ’–

  • <TOOL@VERSION> β€” Tools to set, such as node@20.

🌈 EXAMPLES 🌈

Use node 20 in this shell:

mise shell node@20 node -v v20.19.5

Go back to the version the config requests:

mise shell --unset node

Drop every version set with mise shell or MISE_<TOOL>_VERSION:

mise shell --unset --all

πŸ”₯ MISE SSH πŸ”₯

Open an SSH session, optionally borrowing read-only GitHub access. Yeah, you read that right β€” borrowing. Like a really responsible friend lending you their notes πŸ““βœ¨

Without relay flags, it runs OpenSSH to DESTINATION and passes -i, -p, and -o through. With --github-relay-read-only, Git and mise on the remote host can clone, fetch, and download releases from the GitHub repositories you allow, using this machine's GitHub credentials, until the session ends.

πŸ’€ The token is not copied to the host, and pushes and API writes are refused. No funny business, bestie.

--github-relay-read-only needs exactly one of --github-relay-repo (repeated for each repository) or --github-relay-all-repos.

😭 Also real talk: a compromised host can read what you allow while the session lasts. Keep that in mind, it's not a vibe to ignore.

See https://mise.jdx.dev/bootstrap/github-relay.html

Usage: mise ssh [OPTIONS] [<DESTINATION>] [<COMMAND>] ...

πŸ’œ OPTIONS πŸ’œ

  • -i, --identity-file <IDENTITY_FILE> β€” SSH identity file.
  • -p, --port <PORT> β€” SSH port.
  • -o, --ssh-option <SSH_OPTION> β€” OpenSSH option; repeat for multiple options.
  • --github-relay-read-only β€” Borrow read-only GitHub access for this session only.
  • --github-relay-repo <OWNER/REPO> β€” GitHub repository the host may read; repeat for more repositories.
  • --github-relay-all-repos β€” Allow reads of every repository your local GitHub credentials can access.
  • --github-relay-log-requests β€” Log sanitized relay requests on local stderr.
  • --github-relay-no-log-requests β€” Turn off request logging even if the github_relay.log_requests setting is on.
  • --github-relay-log-format <FORMAT> β€” Relay log and summary format: text or jsonl (default: the github_relay.log_format setting).
  • --github-relay-max-duration <DURATION> β€” End borrowed access after a duration such as 1h; 0s lasts the whole session.
  • --relay-session <RELAY_SESSION> β€” Internal session adapter.
  • --repository-bundle <REPOSITORY_BUNDLE> β€” (yes, it's a flag, we don't gatekeep)
  • --repository-origin <REPOSITORY_ORIGIN> β€” (another one, slay)
  • --repository-revision <REPOSITORY_REVISION> β€” (keeping the list complete, you're welcome πŸ’…)
  • --repository-update β€” (flag, present, accounted for)
  • --repository-require-branch β€” The bundled branch was requested with ?ref=.
  • --repository-yes β€” (it exists, bestie)
  • --repository-dry-run β€” Preview the transferred repository's installation without writing it. Very demure, very mindful πŸŽ€
  • --repository-preview-directory <REPOSITORY_PREVIEW_DIRECTORY> β€” (listed, noted, respected)
  • --global-config-directory β€” (also a flag, also here)
  • -h, --help β€” Print help.

πŸ¦‹ ARGUMENTS πŸ¦‹

  • <DESTINATION> β€” OpenSSH destination or SSH config alias (required).
  • <COMMAND> β€” Command to execute after --; omit for an interactive shell.

🌸 EXAMPLES 🌸

Let devbox clone one private repository:

mise ssh devbox --github-relay-read-only --github-relay-repo you/setup -- git clone https://github.com/you/setup.git

Open a shell that can read every repository your credentials can read:

mise ssh devbox --github-relay-read-only --github-relay-all-repos

Run a command over plain SSH with an identity file, port, and option:

mise ssh devbox -i ~/.ssh/devbox -p 2222 -o ServerAliveInterval=30 -- uname -a

🧚 MISE SHELL-ALIAS 🧚

Manage shell aliases β€” tiny shortcuts that make you feel powerful ✨

Shell aliases are defined under [shell_alias] in mise.toml. In a shell where mise is activated, mise sets them when you enter the directory and removes them when you leave. Like they were never there. Spooky. Iconic. πŸ’…

With no subcommand, it lists them (same as mise shell-alias ls).

See https://mise.jdx.dev/shell-aliases.html

Usage: mise shell-alias [OPTIONS] [COMMAND]

πŸ“ OPTIONS πŸ“

  • --no-header β€” Do not print the table header.
  • -h, --help β€” Print help.

πŸŽ€ MISE SHELL-ALIAS GET πŸŽ€

Show the command for a shell alias β€” the actual thing it runs, no mystery πŸ•΅οΈβ€β™€οΈ

Usage: mise shell-alias get [OPTIONS] <shell_alias>

πŸ’– OPTIONS πŸ’–

  • -h, --help β€” Print help.

🌈 ARGUMENTS 🌈

  • <shell_alias> β€” The alias to show.

πŸ¦‹ EXAMPLES πŸ¦‹

Print the command that ll runs:

mise shell-alias get ll ls -la

πŸ’… MISE SHELL-ALIAS LS

List shell aliases β€” like, all of them, bestie ✨

So this one lists the shell aliases that are configured for the current directory β€” specifically, the [shell_alias] entries of every single config file mise loads here. Every one. Not just the top one. Okayyy πŸ‘‘

Usage:

mise shell-alias ls [OPTIONS]

Options

  • --no-header β€” don't print the table header. just the goods πŸŽ€
  • -h, --help β€” print help

Examples

List the aliases set in this directory:

mise shell-alias ls
alias    command
ll       ls -la
gs       git status

πŸ¦‹ MISE SHELL-ALIAS SET

Set a shell alias in the global config β€” global, babes, global πŸ’…

This writes to the global config (~/.config/mise/config.toml by default). Wanna share an alias with a project instead? Then drop it under [shell_alias] in the project's mise.toml β€” that's the move 🫢

Usage:

mise shell-alias set [OPTIONS] <shell_alias> [<COMMAND>]

Options

  • -h, --help β€” print help

Arguments

  • <shell_alias> β€” the alias name, literally the nickname
  • <COMMAND> β€” the command to run (or pass ALIAS=COMMAND like a shortcut, iykyk)

Examples

Define ll in every directory:

mise shell-alias set ll "ls -la"

Use the ALIAS=COMMAND form:

mise shell-alias set gs="git status"

🧚 MISE SHELL-ALIAS UNSET

Remove a shell alias from the global config β€” breaking up is hard, but it's for the best 😭

Edits the global config (~/.config/mise/config.toml by default). Heads up though: an alias defined in a project's mise.toml has to be removed there. This one only touches global, no cap πŸ’€

Usage:

mise shell-alias unset [OPTIONS] <shell_alias>

Options

  • -h, --help β€” print help

Arguments

  • <shell_alias> β€” the alias to remove πŸ—‘οΈ

Examples

Remove ll from the global config:

mise shell-alias unset ll

🌈 MISE SKILLS

List and link the agent skills that active tools ship β€” okay this is genuinely iconic 🧠✨

A tool installed with the packslip: backend may declare an agent skill: a directory holding SKILL.md and whatever it references, in the Agent Skills format. And mise knows exactly which version of each tool is active here, so it can hand an agent the skill for exactly that version. Main character energy, honestly πŸ‘‘

With no subcommand, it lists the skills (same as mise skills ls). See https://mise.jdx.dev/dev-tools/packslip-resources.html#skills

Usage:

mise skills [OPTIONS] [COMMAND]

Options

  • -h, --help β€” print help

⭐ MISE SKILLS LS

List the skills the active tools declare β€” a lil roster of talent πŸŽ€

Each line is a skill of a tool that's installed and active in the current directory, with the version it belongs to and the directory holding its SKILL.md.

Usage:

mise skills ls [OPTIONS]

Options

  • -J, --json β€” output in JSON format (for the machine besties πŸ€–)
  • -h, --help β€” print help

Examples

List the skills of the active tools:

mise skills ls
Skill         Tool                        Version  Path
hk-configure  packslip:github.com/jdx/hk  2.5.0    ~/.local/share/mise/installs/packslip-github-com-jdx-hk/2.5.0/skills/hk-configure
hk-debug      packslip:github.com/jdx/hk  2.5.0    ~/.local/share/mise/installs/packslip-github-com-jdx-hk/2.5.0/skills/hk-debug

πŸŽ€ MISE SKILLS SYNC

Link the active tools' skills where an agent looks for them β€” matchmaker era πŸ’–

It writes one symlink per skill into DIR, named after the skill and pointing at the directory of the version that's active here. DIR defaults to the skills.dir setting, .claude/skills, under the project root β€” which is the directory of the nearest mise config. Run it again after mise use changes a version and the links follow along like the loyal besties they are 🫢 Or set skills.auto_sync and miss you will do that automatically after every install and mise use. Slay.

And here's the vibe check: mise replaces only the links it made β€” the ones pointing into its installs directory β€” and removes them only with --prune or the skills.prune setting. A real directory, or a link of your own at a skill's name, gets left alone and reported. Not me messing with your stuff πŸ™ˆ

Usage:

mise skills sync [OPTIONS]

Options

  • --dir <DIR> β€” the directory to link skills into
  • -g, --global β€” link into the skills.dir directory under your home directory instead of the project's. With the default skills.dir, that's ~/.claude/skills 🏠
  • --prune β€” remove links mise made for skills that are no longer active
  • -h, --help β€” print help

Examples

Link skills into the project's skills.dir (default .claude/skills):

mise skills sync

Link into .agents/skills and remove links for skills that are no longer active:

mise skills sync --dir .agents/skills --prune

πŸ‘‘ MISE SPONSORS

Show the companies sponsoring mise and the jdx.dev open source tools β€” support the icons, fr fr πŸ’œ

Usage:

mise sponsors [OPTIONS]

Options

  • -h, --help β€” print help

πŸ”₯ MISE SYNC

Use tool versions installed by other version managers β€” no reinstall needed, we're sharing 😌

This links node versions from nvm, nodenv, or Homebrew, python versions from pyenv or uv, and ruby versions from Homebrew into mise β€” so mise use can select them without reinstalling. Reusing instead of redownloading? That's eco-friendly queen behavior 🌸

Usage:

mise sync [OPTIONS] <COMMAND>

Options

  • -h, --help β€” print help

πŸ’€ MISE SYNC NODE

Symlink node versions installed by nvm, nodenv, or Homebrew into mise β€” node bestie adoption program 🧚

Use this to make versions installed by another version manager available to mise. Important: it does not overwrite managed installs, runtime aliases, or links from other providers. Respectful king πŸ‘‘ Pass one or more of --brew, --nodenv, and --nvm.

Usage:

mise sync node [OPTIONS]

Options

  • --brew β€” get tool versions from Homebrew
  • --nodenv β€” get tool versions from nodenv
  • --nvm β€” get tool versions from nvm
  • -h, --help β€” print help

Examples

Use the node that Homebrew installed:

brew install node@24
mise sync node --brew
mise use -g node@24

🐍 MISE SYNC PYTHON

Symlink python versions installed by pyenv or uv into mise β€” snek diplomacy πŸ“

Use this to make versions installed by another version manager available to mise. Same boundary rules as above: it does not overwrite managed installs, runtime aliases, or links from other providers. With --uv, it also links mise's python versions into uv β€” reciprocal, we love a two-way street πŸ’– Pass --pyenv, --uv, or both; with neither, nothing is linked. Yeah, nothing. Zero. Zilch πŸ’€

Usage:

mise sync python [OPTIONS]

Options

  • --pyenv β€” get tool versions from pyenv
  • --uv β€” link uv's python versions into mise and mise's python versions into uv (both directions, mutuals 🫢)
  • -h, --help β€” print help

Examples

Use a python that pyenv installed:

pyenv install 3.13.0
mise sync python --pyenv
mise use -g python@3.13.0

Share python versions with uv in both directions:

uv python install 3.13.0
mise install python@3.12.0
mise sync python --uv
mise exec python@3.13.0 -- python -V
uv run -p 3.12.0 -- python -V

πŸ’Ž MISE SYNC RUBY

Symlink ruby versions installed by Homebrew into mise β€” ruby girlies rise πŸ’

Use this to make versions installed by another version manager available to mise. Again: it does not overwrite managed installs, runtime aliases, or links from other providers. Homebrew is the only source here, so --brew is required β€” no flag, no linkage, periodt. Also, mise links each ruby@X.Y directory under Homebrew's opt directory, not opt/ruby. Specifics matter, bestie 🌟

Usage:

mise sync ruby [OPTIONS]

Options

  • --brew β€” get tool versions from Homebrew
  • -h, --help β€” print help

Examples

Link the Homebrew ruby@3.4, then list it with the other installed versions:

brew install ruby@3.4
mise sync ruby --brew
mise ls ruby --installed

🌟 MISE TASKS

Manage tasks β€” the whole task department, under one roof πŸ’…

With no subcommand, it lists tasks like mise tasks ls and accepts the same flags. With a task name, it shows that task like mise tasks info. And to actually run a task? That's mise run. Different door, same house πŸšͺ

Usage:

mise tasks [OPTIONS] [<TASK>] [COMMAND]

Options

  • -g, --global β€” only show global tasks
  • -J, --json β€” output in JSON format
  • -l, --local β€” deprecated alias for --no-global. Removed in mise 2027.7.0. ⚠️ like, it's on the way out, don't get attached
  • --no-global β€” only show non-global tasks
  • -x, --extended β€” show all columns (all the tea β˜•)
  • -a, --all β€” include tasks from every project in the monorepo, not only the current directory's hierarchy
  • --complete β€” display tasks for usage completion
  • --hidden β€” show hidden tasks πŸ™ˆ
  • --name-only β€” print only task names, one per line (for fzf and similar tools)
  • --no-header β€” do not print the table header
  • --sort <COLUMN> β€” column to sort by (default: name)
  • --sort-order <SORT_ORDER> β€” sort direction (default: asc)
  • --usage β€” (the manpage doesn't say what this does, so I'm not gonna make it up πŸ’€)
  • -h, --help β€” print help

Arguments

  • <TASK> β€” task to show, exactly as mise tasks info does

Examples

List tasks:

mise tasks

Show the build task:

mise tasks build

Include hidden tasks, sorted by source:

mise tasks --hidden --sort source

πŸ’… MISE TASKS ADD πŸ’…

Okay so bestie, this one adds a task β€” and it's giving "let me write the config for you" energy ✨

It writes a [tasks.<name>] table to the nearest project config file, or to the file that --env, --global or --path picks, and it trusts that file's config root so mise actually loads it. Wanna know how the file gets chosen? The lore lives here: https://mise.jdx.dev/configuration.html#target-file-for-write-operations 🫢

Oh and in safe mode (MISE_SAFE=1) it just writes without trusting anything. Chill like that.

Pass --force to replace a task that already has that name in the file. Replacing one without it is deprecated, so heads up: mise still replaces the task, starts warning from 2027.5.0, and straight-up refuses from 2028.5.0 😭 Adding exactly the same task again changes nothing (iconic, zero drama). But if you only wanna change some fields of an existing task, use mise tasks set instead, mwah πŸ’‹

With --file, it creates an executable script in the project's task directory (for example mise-tasks/) instead, and does not touch any config file. Different assignment entirely.

Usage: mise tasks add [OPTIONS] <TASK> [<RUN>] ...

✨ OPTIONS ✨

  • -f, --file β€” create a file task instead of a TOML task
  • -F, --force β€” replace a task that already has this name in the file
  • -n, --dry-run β€” show what would be written without writing it (peek, don't commit, we love a look-but-don't-touch moment πŸ™ˆ)
  • -J, --json β€” print what was written as JSON
  • -e, --env <ENV> β€” use mise.<ENV>.toml in the current directory, or .mise.<ENV>.toml if that exists

--env local uses mise.local.toml, which is for tasks you keep to yourself πŸ‘€ Not the same as the global -E, which only chooses which config files are loaded. Do not confuse them, I'm begging.

  • -g, --global β€” use the global config file
  • -p, --path <PATH> β€” use this config file, or the config file in this directory
  • -a, --alias <ALIAS> β€” other names for the task (yes, a task can have aliases, main character behavior ✨)
  • -d, --depends <TASK> β€” tasks to run before this one
  • -D, --dir <DIR> β€” run the task in a specific directory
  • -H, --hide β€” hide the task from mise tasks and completions
  • -q, --quiet β€” do not print the command before running
  • -r, --raw β€” connect the task directly to the terminal's stdin, stdout, and stderr
  • -s, --sources <GLOB> β€” glob patterns of files this task uses as input
  • -w, --wait-for <TASK> β€” wait for these tasks to finish if they are also being run
  • --confirm <MESSAGE> β€” ask this question before the task runs, and run it only if the answer is yes
  • --depends-post <TASK> β€” tasks to run after this one
  • --description <DESCRIPTION> β€” description of the task
  • --env-var <KEY=VALUE> β€” set an environment variable for the task; repeat for several

Written to the task's env table. --env chooses the config file instead. Two whole different things, okay? 🫠

  • --outputs <GLOB> β€” glob patterns of files this task creates, used to skip it when they are up to date
  • --run-windows <COMMAND> β€” command to run on Windows (TOML tasks only; ignored with --file)
  • --shell <SHELL> β€” run the task in a specific shell
  • --silent β€” do not print the command or its output
  • --tools <TOOL@VERSION> β€” tool the task needs, such as node@24 or npm:prettier@3; repeat for several

Written to the task's tools table. Without a version, writes latest.

🌸 Arguments 🌸

  • <TASK> β€” name of the task to add
  • <RUN> β€” command to run, given after --

πŸŽ€ Examples πŸŽ€

Add a TOML task that is skipped while its outputs are up to date:

mise tasks add build --description "Build the app" --sources 'src/**/*.ts' --outputs 'dist/**' -- npm run build

Add a personal task to mise.local.toml:

mise tasks add --env local lint --tools node@24 -- npx eslint .

Create an executable lint script in the task directory:

mise tasks add --file lint -- eslint .

Add a task that runs after lint and test:

mise tasks add ci --depends lint --depends test -- echo done

Print the task that would be written, as JSON, without writing it:

mise tasks add --json --dry-run deploy --confirm "Deploy to production?" -- ./deploy.sh

🌈 MISE TASKS DEPS 🌈

Show the dependency tree of tasks β€” the family tree but make it build steps 🧚

So the tree is built from declared dependencies: depends, depends_post, and wait_for. That's it, that's the graph.

Task references inside a run or run_windows array ({ task = "..." } or { tasks = [...] }) are execution steps, not graph edges, so they do not appear here. Ngl that's the whole tea β˜• Those nested tasks still run though, including their own depends. The vibe: they're in the building, they're just not on the org chart.

Usage: mise tasks deps [OPTIONS] [<TASKS>] ...

✨ OPTIONS ✨

  • --compact β€” collapse repeated dependencies after their first occurrence
  • --dot β€” display dependencies in DOT format
  • --hidden β€” show hidden tasks
  • -h, --help β€” print help

🌸 Arguments 🌸

  • <TASKS> β€” tasks to show (default: all tasks)

πŸŽ€ Examples πŸŽ€

Show dependencies for all tasks:

mise tasks deps

Show dependencies for the "lint", "test" and "check" tasks:

mise tasks deps lint test check

Show dependencies in DOT format:

mise tasks deps --dot

Collapse repeated dependencies:

mise tasks deps --compact

πŸ¦‹ MISE TASKS EDIT πŸ¦‹

Open a task in your editor β€” literally the "take me to the source" button πŸ’…

It opens the file that defines the task in $VISUAL or $EDITOR: the script for a file task, or the config file for a TOML task. Simple, clean, no crumbs.

But if no task has that name? mise creates an executable bash script for it in the project's task directory (for example mise-tasks/) and opens that. Yes, it just manifests a task for you. Main character energy honestly πŸ‘‘

--path prints the file's path instead of opening it β€” and a missing task is still created. Yep, even in path mode. Iconic.

Usage: mise tasks edit [OPTIONS] <TASK>

✨ OPTIONS ✨

  • -p, --path β€” print the task's file path instead of opening it
  • -h, --help β€” print help

🌸 Arguments 🌸

  • <TASK> β€” task to edit

πŸŽ€ Examples πŸŽ€

Edit the build task:

mise tasks edit build

Print the build task's file path:

mise tasks edit --path build

πŸ“ MISE TASKS GRAPH πŸ“

Show the monorepo project graph β€” the whole friend group map 🫢

It lists the projects mise infers from Cargo, uv, Go, Gradle, and Node.js workspace manifests, with each project's ID, root directory, dependencies, and metadata. So basically the receipts for every project in your monorepo.

Fun fact: mise run --affected uses this graph to decide which projects a change touches. Slay.

See https://mise.jdx.dev/tasks/workspace-graph.html

Usage: mise tasks graph [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output the project graph as JSON
  • --explain β€” show which provider and workspace file each project, dependency, and task field came from
  • --no-header β€” do not print table headers
  • -h, --help β€” print help

πŸŽ€ Examples πŸŽ€

List projects and their dependencies:

mise tasks graph

Print the project graph as JSON:

mise tasks graph --json

Show which workspace file each project, dependency, and task came from:

mise tasks graph --explain

πŸ’œ MISE TASKS INFO πŸ’œ

Show a task's definition β€” the full dossier, no gatekeeping πŸ”₯

It prints the task's description, source file, dependencies, sources, outputs, run commands, environment, and usage spec. That's a lot of fields and yes, every one of them matters.

--json prints the full definition. Structured, pretty, machine-readable, obsessed.

Usage: mise tasks info [OPTIONS] <TASK>

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format
  • -h, --help β€” print help

🌸 Arguments 🌸

  • <TASK> β€” name of the task to get information about

πŸŽ€ Examples πŸŽ€

Show the test task and the file that defines it:

mise tasks info test

Get the full structured task definition:

mise tasks info test --json

πŸŽ€ MISE TASKS LS πŸŽ€

List available tasks β€” the lineup, the roster, the whole cast 🌟

It lists tasks from [tasks] in your config files and from task directories such as mise-tasks/, .mise-tasks/, and .mise/tasks/, including global tasks in ~/.config/mise/tasks/. Tasks from parent directories and the global config are included too; and a project task overrides a global task with the same name (project wins, sorry global bestie).

In a monorepo, --all also lists tasks from sibling projects. Whole extended family, invited.

See https://mise.jdx.dev/tasks/task-discovery.html

Usage: mise tasks ls [OPTIONS]

✨ OPTIONS ✨

  • -g, --global β€” only show global tasks
  • -J, --json β€” output in JSON format
  • -l, --local β€” deprecated alias for --no-global

Removed in mise 2027.7.0. Rip, she's leaving. πŸ’€

  • --no-global β€” only show non-global tasks
  • -x, --extended β€” show all columns
  • -a, --all β€” include tasks from every project in the monorepo, not only the current directory's hierarchy
  • --complete β€” display tasks for usage completion
  • --hidden β€” show hidden tasks
  • --name-only β€” print only task names, one per line (for fzf and similar tools)
  • --no-header β€” do not print the table header
  • --sort <COLUMN> β€” column to sort by (default: name)
  • --sort-order <SORT_ORDER> β€” sort direction (default: asc)
  • --usage β€” okay the manpage literally gives this one no description at all, no cap, it's just listed with zero notes πŸ’€ (not me adding detail that isn't there πŸ™ˆ)
  • -h, --help β€” print help

πŸŽ€ Examples πŸŽ€

List tasks:

mise tasks ls

Include hidden tasks:

mise tasks ls --hidden

List tasks from every monorepo project:

mise tasks ls --all

Pick a task name interactively:

mise tasks ls --name-only | fzf

πŸ¦‹ MISE TASKS RM πŸ¦‹

Remove tasks β€” the un-invite πŸ’…

It removes a TOML task's [tasks.<name>] table from the config file that defines it, and deletes a file task's script. So the config row and the script file both get cleaned up, whichever applies.

Without --env, --global or --path, mise uses the one file that defines each task and fails when several do 😭 β€” and --path can also name a file task's script.

It asks before removing anything unless --yes (MISE_YES=1) is set, and it fails without a terminal to ask on. No interactive confirmation possible = no deletion, periodt.

Heads up bestie: other tasks that depend on a removed task are left exactly as they are. Nothing gets cleaned up for you. mise tasks validate reports them. So go run that after. 🫢
Usage: mise tasks rm [OPTIONS] <TASKS> ...

✨ OPTIONS ✨

  • -n, --dry-run β€” show what would be removed without removing it
  • -J, --json β€” print what was removed as JSON
  • -e, --env <ENV> β€” use mise.<ENV>.toml in the current directory, or .mise.<ENV>.toml if that exists

--env local uses mise.local.toml, which is for tasks you keep to yourself πŸ‘€ Not the same as the global -E, which only chooses which config files are loaded. (Yes this note appears twice in this page, we stay consistent.)

  • -g, --global β€” use the global config file
  • -p, --path <PATH> β€” use this config file, or the config file in this directory
  • -h, --help β€” print help

🌸 Arguments 🌸

  • <TASKS> β€” tasks to remove

πŸŽ€ Examples πŸŽ€

Remove the build task:

mise tasks rm build

Remove two tasks from mise.local.toml without asking:

mise tasks rm --env local --yes lint fmt

Show which file defines build without changing it:

mise tasks rm --dry-run --json build

πŸŽ€ MISE TASKS SET πŸŽ€

Okay so bestie, you already have a TOML task and you just want to tweak it, not rewrite the whole thing? Say less. This command changes fields of an existing TOML task.

It updates only the fields you actually give it, and leaves the rest of the task β€” and the rest of the file β€” exactly as they are. Periodt. πŸ’…

Now the deets, because the rules here are a lil specific:

  • A list field like --depends replaces the whole list. Not merges, not appends β€” replaces.
  • --env-var and --tools are the exceptions: they add or replace single entries of the task's env and tools tables.
  • --unset removes a field, and that's also how a flag such as hide goes back to false. Sneaky but correct. 🫢
  • A command given after -- replaces the task's run.

Without --env, --global or --path, it edits the one config file that defines the task, and fails when several do (no cap, it just refuses to guess). Like mise tasks add, it trusts the file's config root so mise loads it, except in safe mode (MISE_SAFE=1).

⚠️ File tasks are scripts: use mise tasks edit for them. Don't come at tasks set with a script, it's not that girl.

Usage:

mise tasks set [OPTIONS] <TASK> [<RUN>] ...

✨ OPTIONS ✨

  • -n, --dry-run β€” show what would be written without actually writing it. Preview era. πŸ‘€
  • -J, --json β€” print what was written as JSON.
  • -u, --unset <FIELD> β€” remove this field from the task; repeat it for several.
  • -e, --env <ENV> β€” use mise.<ENV>.toml in the current directory, or .mise.<ENV>.toml if that exists.

--env local uses mise.local.toml, which is for tasks you keep to yourself. 🧚 And just so we're clear β€” this is not the same as the global -E, which only chooses which config files are loaded.

  • -g, --global β€” use the global config file.
  • -p, --path <PATH> β€” use this config file, or the config file in this directory.
  • -a, --alias <ALIAS> β€” other names for the task.
  • -d, --depends <TASK> β€” tasks to run before this one.
  • -D, --dir <DIR> β€” run the task in a specific directory.
  • -H, --hide β€” hide the task from mise tasks and completions.
  • -q, --quiet β€” do not print the command before running.
  • -r, --raw β€” connect the task directly to the terminal's stdin, stdout, and stderr.
  • -s, --sources <GLOB> β€” glob patterns of files this task uses as input.
  • -w, --wait-for <TASK> β€” wait for these tasks to finish if they are also being run.
  • --confirm <MESSAGE> β€” ask this question before the task runs, and run it only if the answer is yes.
  • --depends-post <TASK> β€” tasks to run after this one.
  • --description <DESCRIPTION> β€” description of the task.
  • --env-var <KEY=VALUE> β€” set an environment variable for the task; repeat for several.

Written to the task's env table. And remember, --env chooses the config file instead. Two very different girlies. πŸ’–

  • --outputs <GLOB> β€” glob patterns of files this task creates, used to skip it when they are up to date.
  • --run-windows <COMMAND> β€” command to run on Windows (TOML tasks only; ignored with --file).
  • --shell <SHELL> β€” run the task in a specific shell.
  • --silent β€” do not print the command or its output. 🀫
  • --tools <TOOL@VERSION> β€” tool the task needs, such as node@24 or npm:prettier@3; repeat for several.

Written to the task's tools table. Without a version, writes latest. Slay.

Arguments

  • <TASK> β€” name of the task to change.
  • <RUN> β€” command to run instead of the current one, given after --.

🌸 Examples 🌸

Change a task's description:

mise tasks set build --description "Build the app for release"

Add an environment variable and remove the quiet flag:

mise tasks set test --env-var RUST_BACKTRACE=1 --unset quiet

Change the command of a task in mise.local.toml:

mise tasks set --env local lint -- npx eslint --fix .

⭐ MISE TASKS VALIDATE ⭐

The vibe check for your task definitions. It checks each task for:

  • dependency cycles
  • references to tasks that do not exist
  • #USAGE specs that do not parse
  • invalid timeout values
  • aliases that more than one task uses
  • missing or non-executable file tasks
  • invalid dir paths and templates
  • missing shell executables
  • invalid sources and outputs globs
  • broken task references in run arrays
  • empty scripts
  • tasks with nothing to run
  • required daemons that no readable [daemons] section declares
  • secrets grants that conflict with the sandbox or [env], or β€” when the config is trusted β€” that name keys missing from the secrets source

Exits 1 if any error is found, so you can run it in CI. Errors-only? No β€” warnings are reported but do not fail the command. 😌

Usage:

mise tasks validate [OPTIONS] [<TASKS>] ...

✨ OPTIONS ✨

  • --errors-only β€” only show errors (skip warnings).
  • --json β€” output validation results in JSON format.
  • -h, --help β€” print help.

Arguments

  • <TASKS> β€” tasks to validate (default: all tasks).

πŸ¦‹ Examples πŸ¦‹

Validate all tasks:

mise tasks validate

Validate specific tasks:

mise tasks validate build test

Output results as JSON:

mise tasks validate --json

Only show errors (skip warnings):

mise tasks validate --errors-only

πŸ”₯ MISE TEST-TOOL πŸ”₯

Test that a tool installs and runs. Literally the whole point.

It installs each tool and runs the test command from its registry entry (registry/<tool>.toml), checking the output. Use it when adding or changing a registry entry. The minimum release age is ignored so that new releases can be tested right away. ⚑

πŸ’€ Warning: before testing, this deletes every installed version of each tested tool, along with its cache and downloads directories, so the test installs from scratch. To keep your installs and caches, run it with throwaway MISE_DATA_DIR and MISE_CACHE_DIR directories. Not me losing your whole toolchain, bestie. Be careful.

Registry tools with no test entry, or that registry/ marks as unsupported on this OS, are skipped without output, and the command still exits 0. Pass --include-non-defined to run <tool> --version for tools with no test entry.

Usage:

mise test-tool [OPTIONS] [<TOOLS>] ...

✨ OPTIONS ✨

  • -a, --all β€” test every registry tool that defines a test and supports this OS.
  • -j, --jobs <JOBS> β€” number of tools to test in parallel (default 4).

Environment: MISE_TEST_TOOL_JOBS

  • --all-config β€” test all tools specified in config files.
  • --include-non-defined β€” also test registry tools that have no test entry by running <tool> --version.

These always report a failure that shows the output, for use when writing a test. Kinda the opposite of passing, but make it useful. πŸ™ˆ

  • --raw β€” connect the install commands' stdin, stdout, and stderr to the terminal.

Implies --jobs=1.

  • -h, --help β€” print help.

Arguments

  • <TOOLS> β€” tools to test.

πŸ“ Examples πŸ“

Reinstall ripgrep and run its registry test:

mise test-tool ripgrep

Test every tool in the config without touching your installs:

MISE_DATA_DIR=$(mktemp -d) MISE_CACHE_DIR=$(mktemp -d) mise test-tool --all-config

πŸ‘‘ MISE TOKEN πŸ‘‘

Show which Git provider token mise uses. It shows the token mise would send to a GitHub, GitLab, or Forgejo host and where it came from, to debug authentication.

See https://mise.jdx.dev/dev-tools/github-tokens.html

Usage:

mise token [OPTIONS] <COMMAND>

✨ OPTIONS ✨

  • -h, --help β€” print help.

πŸ’œ MISE TOKEN FORGEJO πŸ’œ

Show the Forgejo token mise uses for a host. It shows the token and where it came from, to debug authentication. The token is masked unless you pass --unmask.

Usage:

mise token forgejo [OPTIONS] [<HOST>]

✨ OPTIONS ✨

  • --unmask β€” show the full unmasked token.
  • -h, --help β€” print help.

Arguments

  • <HOST> β€” Forgejo hostname. Default: codeberg.org.

🌈 Examples 🌈

Show the token for codeberg.org:

mise token forgejo codeberg.org: xxxx…xxxx (source: FORGEJO_TOKEN)

Show the whole token:

mise token forgejo --unmask codeberg.org: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (source: FORGEJO_TOKEN)

Check a self-hosted Forgejo instance:

mise token forgejo forgejo.mycompany.com forgejo.mycompany.com: (none)

🫢 MISE TOKEN GITHUB 🫢

Show the GitHub token mise uses for a host. It shows the token and where it came from, to debug authentication. The token is masked unless you pass --unmask or --raw.

Usage:

mise token github [OPTIONS] [<HOST>]

✨ OPTIONS ✨

  • --git-credential <GIT_CREDENTIAL> β€” speak Git's credential helper protocol.
  • --oauth β€” use only native GitHub OAuth (a cached token, a refresh, or the device-code flow), ignoring other token sources.
  • --raw β€” print only the token, unmasked, for use in scripts.
  • --refresh β€” with --oauth, get a new OAuth token even if the cached one has not expired, through the refresh-token grant or a new device-code flow.

Use it after changing the GitHub App's installations or permissions: cached tokens keep their original access until they expire. Iconic footgun behavior, honestly. πŸ’…

  • --unmask β€” show the full unmasked token.
  • -h, --help β€” print help.

Arguments

  • <HOST> β€” GitHub hostname. Default: github.com.

⭐ Examples ⭐

Show the token for github.com:

mise token github github.com: ghp_…xxxx (source: GITHUB_TOKEN)

Show the whole token:

mise token github --unmask github.com: ghp_xxxxxxxxxxxx (source: GITHUB_TOKEN)

Check a GitHub Enterprise host:

mise token github github.mycompany.com github.mycompany.com: (none)

Get a new token through native GitHub OAuth:

mise token github --oauth --refresh github.com: gho_…xxxx (source: GitHub OAuth)

Pass the resolved token to another tool:

GH_TOKEN=$(mise token github --raw) gh api user

πŸ’– MISE TOKEN GITLAB πŸ’–

Show the GitLab token mise uses for a host. It shows the token and where it came from, to debug authentication. The token is masked unless you pass --unmask.

Usage:

mise token gitlab [OPTIONS] [<HOST>]

✨ OPTIONS ✨

  • --unmask β€” show the full unmasked token.
  • -h, --help β€” print help.

Arguments

  • <HOST> β€” GitLab hostname. Default: gitlab.com.

🌸 Examples 🌸

Show the token for gitlab.com:

mise token gitlab gitlab.com: glpa…xxxx (source: GITLAB_TOKEN)

Show the whole token:

mise token gitlab --unmask gitlab.com: glpat-xxxxxxxxxxxx (source: GITLAB_TOKEN)

Check a self-managed GitLab instance:

mise token gitlab gitlab.mycompany.com gitlab.mycompany.com: (none)

πŸ’… MISE TOOL πŸ’…

Okay bestie, this one's literally the "who IS she" command for a tool β€” it spills everything mise knows about it ✨

It shows you the tool's backend, its description and project URL when known, the installed, active, and requested versions, the config file that requests it, its tool options, and the backend's security features. Want just one thing? Pass a field flag like --backend and it prints that single field. Want the whole buffet? --json.

Usage: mise tool [OPTIONS] <TOOL>

πŸŽ€ Options

  • -J, --json β€” output it all in JSON format, for when you're piping it somewhere
  • --active β€” only show the active versions
  • --backend β€” only show the backend field
  • --config-source β€” only show the config source
  • --description β€” only show the description field
  • --installed β€” only show the installed versions
  • --requested β€” only show the requested versions
  • --tool-options β€” only show the tool options
  • --url β€” only show the project URL from the registry
  • -h, --help β€” print help

🌸 Arguments

  • <TOOL> β€” the tool, like node or aqua:jqlang/jq

πŸ¦‹ Examples

Show everything mise knows about node:

mise tool node

and the receipts look like this, no cap:

Backend:            core:node
Installed Versions: 22.0.0 24.0.0
Active Version:     24.0.0
Requested Version:  24
Config Source:      ~/.config/mise/config.toml
Tool Options:       [none]
Security:           checksum (sha256), gpg

Print only the backend:

mise tool node --backend

which gives you core:node and nothing else. iconic πŸ’…


🧚 MISE TOOL-STUB 🧚

Run a tool stub file! This is such a cute little trick, lowkey obsessed 🫢

So a tool stub is an executable file whose shebang is #!/usr/bin/env -S mise tool-stub, and whose body is TOML that names a tool, a version, and an executable. Running the stub runs this command, which installs the tool if needed and then runs it with the stub's arguments. You rarely call it directly β€” the move is to create stubs with mise generate tool-stub.

#!/usr/bin/env -S mise tool-stub
# Node.js 24

tool = "node"
version = "24"
bin = "node"

See https://mise.jdx.dev/dev-tools/tool-stubs.html for the full lore.

Usage: mise tool-stub <FILE> [<ARGS>] ...

✨ Arguments

  • <FILE> β€” path to the TOML tool stub file to execute

Every field is optional, bestie: version defaults to latest, tool defaults to the stub's file name (or http:<file name> when the stub sets url or platform URLs), and bin defaults to the stub's file name. A stub can also set backend-specific options πŸ’–

  • <ARGS> β€” arguments to pass to the tool

Every argument after the stub path is passed to the tool unchanged, including a literal --. Nothing gets eaten, promise.


πŸ‘‘ MISE TRUST πŸ‘‘

Mark a config file as trusted πŸ’…

Trust is what lets mise load the parts of a config file that can run code or change your environment. Without it, mise prompts, skips the file, or fails with an untrusted-config error when it can't prompt. So yeah β€” trust is the vibe check for configs.

A file with no template syntax that contains only min_version, [tools] entries with plain version strings (or arrays of them), and [tasks] in which no task lists secrets does not need trust unless paranoid mode is on. Commands that run project code (mise run, task shorthand such as mise build, mise install, mise exec, mise watch, and mise daemons start|restart|register) trust their active config automatically 🫢

In paranoid mode, mise trust with no path also trusts the env files and scripts that config reads (env._.file, env._.source and the env_file setting), which have trust of their own. Give a file's path to trust only that file.

Trusting a config file in a repository's main checkout also trusts the same path in its git worktrees. Paranoid mode (https://mise.jdx.dev/paranoid.html) turns off automatic and worktree trust and requires trust, tied to the file's contents, for every config outside the global and system config. See https://mise.jdx.dev/security.html#configuration-trust

Usage: mise trust [OPTIONS] [<CONFIG_FILE>]

πŸ’œ Options

  • -a, --all β€” trust all config files in the current directory, its parents, and its subdirectories

Subdirectories are walked respecting .gitignore, skipping hidden directories and common build and dependency directories (node_modules, vendor, target, dist, build). Very "respecting boundaries" of it 🌸

  • --ignore β€” do not trust this config and ignore it in the future
  • --show β€” show the trust status of config files in the current directory and its parents

Does not trust or untrust any files. Strictly a read, bestie.

  • --untrust β€” remove explicit trust for this config
  • -h, --help β€” print help

πŸ“ Arguments

  • <CONFIG_FILE> β€” the config file whose trust status to change

🌈 Examples

Trust the nearest untrusted config in this directory or a parent, and in paranoid mode the env files it reads:

mise trust

Trust a specific file:

mise trust ~/src/app/mise.toml

List configs here and above with their trust status:

mise trust --show

πŸ’€ MISE UNINSTALL πŸ’€

Remove installed tool versions β€” the "you're not coming to the function" command 😭

It removes installed versions but does not edit mise.toml. If you want to remove a tool from mise.toml and uninstall it, that's mise unuse. A tool name or version prefix, such as node or node@22, must match exactly one installed version unless you pass --all.

--project removes the installed versions that the project's own config files request. Heads up: installs are shared by every project, so other projects that use the same versions have to install them again. fr fr.

Usage: mise uninstall [OPTIONS] [<INSTALLED_TOOL@VERSION>] ...

πŸ”₯ Options

  • -a, --all β€” remove every installed version of the named tools, or of every tool when none is named
  • --project β€” remove the installed versions the nearest project config requests

The project is the nearest directory, starting at the current one and moving up, that has a mise config file. Every config file in that directory counts, such as mise.toml, mise.local.toml, conf.d fragments, .tool-versions and idiomatic version files. Configs in parent directories and global or system configs do not. Every version those files name is removed, including one that a later file overrides. It lists what it will remove and asks for confirmation unless --yes or a dry run is given. Tools set to a path: or system version are never removed πŸ™…β€β™€οΈ

  • -n, --dry-run β€” show what would change without changing anything
  • --dry-run-code β€” like --dry-run, but exit with code 1 if there are tools to uninstall

Use it in scripts that check whether tools need uninstalling. very clever, love that for you

  • -h, --help β€” print help

🌸 Arguments

  • <INSTALLED_TOOL@VERSION> β€” tools to remove, such as node@22.0.0

πŸ¦‹ Examples

Uninstall a specific version:

mise uninstall node@22.0.0

Uninstall node when exactly one version is installed:

mise uninstall node

Uninstall every installed version of node:

mise uninstall --all node

Preview the versions this project's config requests:

mise uninstall --project --dry-run

πŸŽ€ MISE UNSET πŸŽ€

Remove environment variables from mise.toml β€” the undo button for mise set ✨

It edits the same file mise set writes: the lowest-precedence TOML file in the nearest config directory, or the global config when run in your home directory. Use --global or --file to pick another file.

Usage: mise unset [OPTIONS] [<ENV_KEY>] ...

πŸ’– Options

  • -f, --file, --path <FILE> β€” the TOML file to edit instead of the default target

Can be a file or a directory. For a directory, mise uses the config file in it, or one named by MISE_DEFAULT_CONFIG_FILENAME (default mise.toml): https://mise.jdx.dev/configuration/settings.html#default_config_filename

Wanna move the global config file? Set MISE_GLOBAL_CONFIG_FILE: https://mise.jdx.dev/configuration/settings.html#global_config_file

  • -g, --global β€” use the global config file
  • --override β€” use the global override file, config.override.toml

See https://mise.jdx.dev/configuration.html#override-file

  • -h, --help β€” print help

🫢 Arguments

  • <ENV_KEY> β€” environment variables to remove, such as NODE_ENV

🌈 Examples

Remove NODE_ENV from the project config:

mise unset NODE_ENV

Remove NODE_ENV from the global config:

mise unset -g NODE_ENV

🧚 MISE UNTRUST 🧚

Remove explicit trust for a config 😀

After this, mise asks again before loading the parts of the file that can run code. With no file, it untrusts the nearest config in this directory or a parent. Same as mise trust --untrust β€” literally the same thing, just a shorter path.

Usage: mise untrust [OPTIONS] [<CONFIG_FILE>]

⭐ Options

  • -h, --help β€” print help

πŸ“ Arguments

  • <CONFIG_FILE> β€” the config file to untrust

πŸ’œ Examples

Stop trusting a specific file:

mise untrust ~/src/app/mise.toml

πŸ¦‹ MISE UNUSE πŸ¦‹

Remove tool requests from config files and prune unused installations β€” the double-duty queen πŸ‘‘

Without --path, --global, or --env, mise edits the first loaded config that declares one of the tools; in your home directory it edits the global config. A version argument matches the configured request literally: to remove node = "20", use mise unuse node@20, not the installed version it resolved to. Important distinction, iykyk. Omit the version to remove every request for that tool from the selected file.

The installed versions the arguments name are pruned only when no remaining tracked config or tool stub needs them; mise says which file keeps one. A tool named without a version has all of its unused versions pruned. Pass --no-prune to edit the config and keep the installations. And if you want to remove an installation without editing config, that's mise uninstall.

Usage: mise unuse [OPTIONS] <INSTALLED_TOOL@VERSION> ...

πŸ”₯ Options

  • -e, --env <ENV> β€” edit mise.<ENV>.toml in the current directory, or .mise.<ENV>.toml if that exists

Not the same as the global -E, which only chooses which config files are loaded. Don't get it twisted πŸ’…

  • -g, --global β€” use the global config file (~/.config/mise/config.toml) instead of the local one
  • -p, --path, --file <PATH> β€” edit this config file, or the config file in this directory
  • --override β€” write to the global override file, config.override.toml

The override file outranks all project config. With --env, writes config.<ENV>.override.toml instead. See https://mise.jdx.dev/configuration.html#override-file

  • --no-prune β€” do not also prune the installed version
  • -h, --help β€” print help

🌸 Arguments

  • <INSTALLED_TOOL@VERSION> β€” tools to remove from the config, with the version written as in the config

πŸŽ€ Examples

Remove node@22.0.0 from mise.toml and uninstall it if nothing else uses it:

mise unuse node@22.0.0

Remove it from the global config instead:

mise unuse -g node@22.0.0

Remove the node@20 request from mise.staging.toml:

mise unuse --env staging node@20

MISE UPGRADE

okay so mise upgrade is the glow-up command β€” it takes your outdated tools and makes them ✨current✨. No cap.

By default it keeps the range in mise.toml: if you've got node = "20", it installs the newest 20.x release. Use --bump to upgrade to the newest release overall and update the version in mise.toml. It also updates mise.lock when lockfiles are enabled β€” see https://mise.jdx.dev/dev-tools/mise-lock.html πŸ’–

The version you upgraded from gets removed after the upgrade.prune_after setting's grace period β€” unless a tracked config or tool stub still uses it. Pass --prune to remove it now, or --no-prune to keep it around. πŸŽ€

Usage: mise upgrade [OPTIONS] [<INSTALLED_TOOL@VERSION>] ...

OPTIONS

  • -b, --bump β€” Upgrade past the configured range to the newest release, and update the config to match

The config keeps its precision: node = "20" becomes node = "22", and node = "20.0.0" becomes node = "22.1.0". If you name a version on the command line (node@latest, node@3, or node@prefix:3), that request is written instead; mise upgrade node@latest --bump writes latest. With the pin setting on, a version request such as node@3 is written as the version it resolved to, and a bare mise upgrade --bump writes the resolved version for every request that is not exact, such as latest or 20. Requests that do not come from a config file mise can write, such as MISE_NODE_VERSION, are upgraded but not written. πŸ¦‹

  • --pin β€” With --bump, write the resolved version instead of keeping the request's precision

node = "latest" and node = "20" become node = "24.14.0". A named request such as node@3 is written as the version it resolved to. Make this the default with the pin setting (MISE_PIN=1).

  • -i, --interactive β€” Choose which tools to upgrade from a multiselect menu
  • -j, --jobs <JOBS> β€” Number of jobs to run in parallel (default: the jobs setting) Environment: MISE_JOBS
  • -l β€” Deprecated shorthand for --bump
  • -n, --dry-run β€” Show what would change without changing anything
  • -x, --exclude <INSTALLED_TOOL> β€” Tools to exclude from upgrading, such as go python
  • --dry-run-code β€” Like --dry-run, but exit with code 1 if there are outdated tools

Use it in scripts that check whether tools need upgrading.

  • --inactive β€” Also upgrade installed tools that the current config does not request
  • --global β€” Only upgrade tools defined in the global config

Upgrades the requests in the global and system config (~/.config/mise/config.toml, /etc/mise/config.toml), even where a project config or a MISE_<TOOL>_VERSION environment variable sets its own version of the tool. It runs as if from outside any project, so project config, lockfiles, and [env] are neither read nor changed. Tools that update themselves, such as coding agents, run this instead of their own updater; see https://mise.jdx.dev/dev-tools/self-updating-tools.html πŸ‘‘

  • --local β€” Deprecated alias for --no-global
Removed in mise 2027.7.0. rip to it πŸ’€
  • --no-global β€” Only upgrade tools defined in project config files

Skips tools defined in the global config (~/.config/mise/config.toml) and tools set through MISE_<TOOL>_VERSION environment variables.

  • --minimum-release-age <MINIMUM_RELEASE_AGE> β€” Only upgrade to versions released before this date or older than this duration

Supports absolute dates such as "2024-06-01" and relative durations such as "90d" or "1y".

Applies only to requests that can match several versions, such as "20" or "latest". Exact versions such as "22.5.0" are not filtered.

  • --monorepo β€” Placeholder for future monorepo upgrades; mise upgrade --monorepo is not implemented yet.

(yes bestie, it's giving "coming soon" energy πŸ™ˆ)

  • --no-prune β€” Do not uninstall the versions that were upgraded away from

The old version is left in place and is not scheduled for removal. Use this when something outside mise points at the install directory.

Set upgrade.auto_prune = false to make this the default.

  • --prune β€” Immediately uninstall the versions that were upgraded away from

Use this to bypass upgrade.prune_after, or to override upgrade.auto_prune = false for a single run.

  • --raw β€” Connect the install commands' stdin, stdout, and stderr to the terminal

Implies --jobs=1.

  • -h, --help β€” Print help

ARGUMENTS

  • <INSTALLED_TOOL@VERSION> β€” Tools to upgrade, such as node@20 python@3.10

Upgrades every configured tool when omitted.

EXAMPLES

Upgrade every configured tool within its range πŸŒ€

mise upgrade

Upgrade only node

mise upgrade node

Upgrade every tool to its newest release and update mise.toml

mise upgrade --bump

Show what would be upgraded

mise upgrade --dry-run

Upgrade everything except go

mise upgrade --exclude go

Choose tools from a menu

mise upgrade --interactive

Upgrade claude within the global config's request, leaving project config alone

mise upgrade --global claude

MISE USE

mise use is the main-character command fr β€” it installs a tool and adds it to your configuration. 🫢

It installs missing tool versions and records the requests in a config file. By default, mise selects the nearest directory with a supported config and writes to its lowest-precedence file, such as mise.toml rather than mise.local.toml. If no project config exists, it creates one in the current directory. Run from your home directory, it writes to the global config. 🏠

Use --path for an explicit file or directory, --global for personal defaults, or --env to write mise.ENV.toml in the current directory (an existing .mise.ENV.toml is used instead). If you pass more than one, the last one wins. πŸ’…

See https://mise.jdx.dev/configuration.html#target-file-for-write-operations for filename overrides and config precedence. The change takes effect in an activated shell at its next prompt, and immediately in mise exec commands.

Usage: mise use [OPTIONS] [TOOL@VERSION]…

OPTIONS

  • -e, --env <ENV> β€” Write mise.<ENV>.toml in the current directory, or .mise.<ENV>.toml if that exists
Not the same as the global -E, which only chooses which config files are loaded. don't mix them up bestie 😭
  • -f, --force β€” Reinstall even if already installed
  • -g, --global β€” Write to the global config instead of the project config

Updates the global config file that already declares the tool, otherwise the file set by the write_targets.tools setting, otherwise ~/.config/mise/config.toml.

  • -j, --jobs <JOBS> β€” Number of jobs to run in parallel (default: the jobs setting) Environment: MISE_JOBS
  • -n, --dry-run β€” Show what would change without changing anything
  • -p, --path <PATH> β€” Write to this config file, or to the config file in this directory

For a directory, mise picks the file by the usual write-target rules.

  • --override β€” Write to the global override file, config.override.toml

The override file outranks all project config. With --env, writes config.<ENV>.override.toml instead. See https://mise.jdx.dev/configuration.html#override-file πŸ”₯

  • --dry-run-code β€” Like --dry-run, but exit with code 1 if there are changes to make

Use it in scripts that check whether tools need to be added or removed.

  • --fuzzy β€” Write the version as requested, such as 20 for node@20

This is the default unless the pin setting is on.

  • --minimum-release-age <MINIMUM_RELEASE_AGE> β€” Only install versions released before this date or older than this duration

Supports absolute dates such as "2024-06-01" and relative durations such as "90d" or "1y".

  • --pin β€” Write the resolved version, such as 20.19.5 for node@20

If the request exactly matches an available release, mise uses that release rather than an installed version that only matches it as a prefix. Write prefix: before the version, as in node@prefix:20, to force prefix matching. Make this the default with the pin setting (MISE_PIN=1).

To record exact versions without editing mise.toml, use a lockfile: https://mise.jdx.dev/dev-tools/mise-lock.html πŸŽ€

  • --raw β€” Connect the install commands' stdin, stdout, and stderr to the terminal

Implies --jobs=1.

  • --remove <TOOL> β€” Remove these tools from the config file
  • -h, --help β€” Print help
  • --postinstall <COMMAND> β€” Command to run after installing this tool
  • --tool-option <KEY=VALUE> β€” Set an option for the tool that follows; repeat for several options

Values use inline tool-option types; unquoted text is a string. Put these flags before the tool they apply to.

ARGUMENTS

  • <TOOL@VERSION> β€” Tool to add to the config file, such as node@24, cargo:ripgrep@latest, or npm:prettier@3

Without a version, mise requests latest but reuses the newest installed version. Write @latest to install the newest release; in locked mode the lockfile still decides. With --pin it writes the resolved version. Tool options can also be set inline:

mise use "cargo:ripgrep[features=pcre2]"

EXAMPLES

Choose tools from an interactive selector 🌈

mise use

Use node 24.x in the project config and record the request 24

mise use node@24

Run a command after installing a tool

mise use --postinstall "mbx setup --defaults" mr-boxington

Give each tool its own postinstall command

mise use --postinstall "corepack enable" node@24 --postinstall "python -m pip install -U pip" python@3.13

Enable a Rust tool option while installing Rust and mbx

mise use --tool-option mr_boxington=true rust mr-boxington

Use node 24.x globally and record the exact version it resolves to

mise use -g --pin node@24

Write mise.local.toml (an existing .mise.local.toml is used instead)

mise use --env local node@24

Write mise.staging.toml, which mise loads when MISE_ENV=staging

mise use --env staging node@24

🌸 MISE VARS 🌸

List, set, and ask for config vars πŸ’…

Lowkey it's giving mise set energy: with no arguments it lists every var and where it came from, mise vars NAME=VALUE saves a value on this machine, and mise vars NAME prints one out. Saved values live in $MISE_STATE_DIR/vars.toml β€” that's outside every config file, bestie β€” and they sit above a var's default but below any value a config file sets. Priority queen. πŸ‘‘

mise vars prompt asks for the [vars] that declare a prompt; only it and mise bootstrap --prompt-vars ever ask. Periodt.

See https://mise.jdx.dev/configuration/vars.html#prompt

Usage: mise vars [OPTIONS] [<NAME[=VALUE]>] ... [COMMAND]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format
  • --json-extended β€” output in JSON format with sources
  • --no-header β€” do not print the table header
  • -h, --help β€” print help

πŸŽ€ Arguments πŸŽ€

  • <NAME[=VALUE]> β€” values to save (NAME=VALUE) or to print (NAME)

πŸ¦‹ Examples πŸ¦‹

Save a value on this machine without asking:

mise vars git_name="Ada Lovelace"

Print the saved value of git_name:

mise vars git_name

List every var and its source:

mise vars

🌈 MISE VARS LS 🌈

List every var, with the file it comes from 🫢

Lists the [vars] of every config file mise loads here, plus the answers saved on this machine (source: $MISE_STATE_DIR/vars.toml). Values hidden with redact show as [redacted] β€” privacy icon behavior πŸ™ˆ. A required var that is still unset only warns here, it doesn't throw hands. --json prints an object of names and values, and --json-extended adds each var's source.

Usage: mise vars ls [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” output in JSON format
  • --json-extended β€” output in JSON format with sources
  • --no-header β€” do not print the table header
  • -h, --help β€” print help

πŸ’– MISE VARS PROMPT πŸ’–

Ask for the prompt vars that have no saved answer, or set answers directly πŸ’…

Enter accepts the suggested default. Every answer β€” accepted defaults included β€” is saved and never asked for again; use mise vars unset to be asked again. With no arguments, it asks about every unanswered prompt var in the config files that apply here. NAME asks for only that var; NAME=VALUE saves the answer without asking, exactly like mise set does for an env var, so it needs no terminal at all. Main character energy, no tty required. 😌

Usage: mise vars prompt [OPTIONS] [<NAME[=VALUE]>] ...

✨ OPTIONS ✨

  • -h, --help β€” print help

πŸŽ€ Arguments πŸŽ€

  • <NAME[=VALUE]> β€” vars to ask for (NAME) or answers to save (NAME=VALUE)

πŸ¦‹ Examples πŸ¦‹

Ask for every unanswered prompt var:

mise vars prompt

Ask for git_name only:

mise vars prompt git_name

Set the answer for git_name without asking:

mise vars prompt git_name="Ada Lovelace"

🧚 MISE VARS UNSET 🧚

Forget saved answers so they are asked for again 🫢

Edits $MISE_STATE_DIR/vars.toml; no config is loaded. The next mise vars prompt or mise bootstrap --prompt-vars asks again. It's giving selective memory loss, on purpose. 😭

Usage: mise vars unset [OPTIONS] [<NAME>] ...

✨ OPTIONS ✨

  • -h, --help β€” print help

πŸŽ€ Arguments πŸŽ€

  • <NAME> β€” the vars whose answers to forget

πŸ¦‹ Examples πŸ¦‹

Be asked for git_name again:

mise vars unset git_name

⭐ MISE VERSION ⭐

Show the version of mise πŸ‘‘

Prints the version, OS, architecture, and build date, and warns when a newer release is available. mise --version, mise -V, and mise -v with no other arguments print the same line β€” three ways to get the same slay. πŸ’…

Usage: mise version [OPTIONS]

✨ OPTIONS ✨

  • -J, --json β€” print the version information in JSON format
  • -h, --help β€” print help

πŸ¦‹ Examples πŸ¦‹

Show the version:

mise version 2026.10.4 linux-x64 (2026-10-07)

Also show the latest release and the build time, as JSON:

mise version --json

πŸ”₯ MISE WATCH πŸ”₯

Run tasks and rerun them when files change πŸ¦‹

Runs the tasks with mise run under watchexec, then reruns them whenever one of their sources changes β€” including the sources of their dependencies unless you pass --skip-deps. When no selected task declares sources, watchexec watches the current directory. With no task, it runs the default task. Automatic reruns, no cap. ✨

Choose what to watch with --watch, --exts, and --filter, and use --print-events to see what triggered a run. Arguments for the task go after --. Requires watchexec, which mise use -g watchexec installs. Go get it bestie.

To keep a server or database running alongside your tasks, with readiness checks and automatic restarts, see mise daemons (experimental): https://mise.jdx.dev/daemons.html. For cron scheduling and standalone process management, see pitchfork: https://pitchfork.jdx.dev

Usage: mise watch [OPTIONS] [<TASK>] [<ARGS>] ...

✨ OPTIONS ✨

  • -t, --task-flag <TASK_FLAG> β€” tasks to run
  • -g, --glob <GLOB> β€” globs to watch instead of the tasks' sources
  • --skip-deps β€” run and watch only the named tasks, not the tasks they depend on
  • --once β€” wait for a change, run the tasks once, and exit with their status

Nothing runs at start: mise waits until one of the watched sources changes, runs the tasks once, and exits with the status of that run. So --postpone is implied, and passing it as well changes nothing. To run the tasks now and then once more after a change, use mise run build && mise watch build --once.

Use it in scripts and agents that need to block until a file changes. mise exits with 1 if watchexec stops before a change, and with 130 on Ctrl+C. With --once mise runs the tasks itself, so the flags that set how watchexec runs them, such as --restart and --clear, are refused. Rude, but fair. πŸ’€

  • -w, --watch <PATH> β€” watch a file or directory

By default, mise watches each task's directory and any source directory outside it, and filters events to the tasks' sources. When no task declares sources, watchexec watches the current directory. Paths given here are added to the task directories, or replace the current-directory default when there are no sources. Events are still filtered to the sources, so use --filter to widen what triggers a rerun.

To watch a single file, watch its directory and filter on the file name instead: some editors replace a file when they save it, and some platforms do not report changes to the replacement. Sneaky little editors. πŸ™ˆ Repeat the flag to watch several paths.

  • -W, --watch-non-recursive <PATH> β€” watch a directory without recursing into it

Repeat the flag to watch several directories.

  • -F, --watch-file <PATH> β€” read paths to watch from a file, one per line

Each line is treated like a --watch value. The value - reads from stdin and cannot be combined with --stdin-quit.

  • -c, --clear <MODE> β€” clear the screen before each run

If the default clear mode leaves output behind, use --clear=reset. Because the mode is optional, mise watch --clear build reads build as the mode: put --clear after the task name, as in mise watch build --clear, or write the mode with =. Gotcha alert 🚨 β€” that one bites.

  • -o, --on-busy-update <MODE> β€” what to do when files change while the tasks are running

do-nothing (the default) ignores the change, so files the tasks write do not trigger another run. queue runs the tasks again when the current run finishes. restart stops the running tasks and starts them again. signal sends the --signal signal and keeps the tasks running, for programs that reload their configuration on a signal. Default: do-nothing

  • -r, --restart β€” restart the tasks if they are still running when files change

Same as --on-busy-update=restart.

  • -s, --signal <SIGNAL> β€” signal to send to the running tasks when files change

Implies --on-busy-update=signal. Accepts the same forms as --stop-signal. Signals are not supported on Windows, where the tasks are always killed. πŸ’€

  • --stop-signal <SIGNAL> β€” signal that stops the tasks before a restart (default on Unix: SIGTERM)

Used by the restart and signal modes of --on-busy-update unless --signal is given. Accepts a full name (SIGTERM), a short name (TERM), or a number (15), in any case. If the tasks have not exited after --stop-timeout, they are killed. On Windows the tasks are always killed.

  • --stop-timeout <TIMEOUT> β€” how long to wait for the tasks to stop before killing them (default: 10s)

Takes a duration such as 5s or 1min 20s. Set it to 0 to kill the tasks right away. Has no effect on Windows, where the tasks are always killed. Default: 10s

  • --map-signal <SIGNAL:SIGNAL> β€” translate a signal that watchexec receives into one it sends to the tasks

Takes two signal names separated by a colon, such as TERM:INT. Leave out the second name to discard the first signal (TERM:). A mapped SIGINT or SIGTERM no longer stops watching; INT:INT passes Ctrl+C to the tasks without stopping watchexec. Repeat the flag to map several signals.

  • -d, --debounce <TIMEOUT> β€” how long to wait for more changes before running (default: 50ms)

One save can produce several events, and a file can be written in pieces, so watchexec waits this long after an event before running the tasks. Takes a duration such as 500ms or 2s. Default: 50ms

  • --stdin-quit β€” exit when stdin closes
  • --exit-on-error β€” stop watching when a run fails, and exit with its status

By default watchexec keeps watching whatever the tasks exit with. With this flag the first failed run ends mise watch, which then exits with that run's status. --once always exits after its run, so this changes nothing there. Needs watchexec 2.5.0 or later.

  • --no-vcs-ignore β€” do not apply Git and other version control ignore files

Use it to watch files that Git ignores. A task can turn this on for itself with watch = { no_vcs_ignore = true }.

  • --no-project-ignore β€” do not apply ignore files in the project, such as .gitignore and .ignore
  • --no-global-ignore β€” do not apply global ignore files, such as ~/.gitignore and ~/.config/watchexec/ignore
  • --no-default-ignore β€” do not apply watchexec's built-in ignores

They cover editor swap files, *.pyc, .DS_Store, and version control directories such as .git.

  • --no-discover-ignore β€” do not look for ignore files at all

Same as --no-global-ignore --no-vcs-ignore --no-project-ignore, but faster. The built-in ignores still apply though β€” those never leave the group chat πŸ™ˆ

  • --ignore-nothing β€” ignore nothing at all

Same as --no-discover-ignore --no-default-ignore. Patterns you passed with --ignore and --ignore-file still apply, bestie β€” this isn't a full pardon πŸ’…

  • -p, --postpone β€” wait for the first change before running the tasks

Like, chill first. Run later. 😌

  • --delay-run <DURATION> β€” wait this long after a change before running the tasks, e.g. 5s

Debounce era fr fr ⏳

  • --poll <INTERVAL> β€” poll for changes instead of using native file watching

Use this on file systems where native events just do not work β€” network shares being the classic vibe killer. Takes an optional interval such as 2s (default: 30s). Also accepted as --force-poll.

  • --shell <SHELL> β€” use a different shell

By default, Watchexec will use $SHELL if it's defined, or a default of sh on Unix-likes, and either pwsh, powershell, or cmd (CMD.EXE) on Windows, depending on what Watchexec detects is the running shell.

With this option you can override all of that and use a different shell β€” for example one with more features, or one that has your custom aliases and functions. customization era ✨

If the value has spaces, it is parsed as a command line, and the first word is used as the shell program, with the rest as arguments to the shell.

The command is run with the -c flag (except for cmd on Windows, where it's /C).

The special value none can be used to disable shell use entirely. In that case, the command provided to Watchexec will be parsed, with the first word being the executable and the rest being the arguments, and executed directly. Ngl that parsing is rudimentary, and may not work as expected in all cases 🫠

Using none is a little more efficient and can enable a stricter interpretation of the input, but it also means that you can't use shell features like globbing, redirection, control flow, logic, or pipes. no pipes bestie. none. zero. πŸ’€

Examples:

Use without shell:

$ watchexec -n -- zsh -x -o shwordsplit scr

Use with powershell core:

$ watchexec --shell=pwsh -- Test-Connection localhost

Use with CMD.exe:

$ watchexec --shell=cmd -- dir

Use with a different unix shell:

$ watchexec --shell=bash -- 'echo $BASH_VERSION'

Use with a unix shell and options:

$ watchexec --shell='zsh -x -o shwordsplit' -- scr
  • -n β€” shorthand for --shell=none

One character, whole lotta meaning πŸŽ€

  • --emit-events-to <MODE> β€” configure event emission

Watchexec can emit event information when running a command, which can be used by the child process to target specific changed files. so organized of it

One thing to take care with is assuming inherent behaviour where there is only chance. Notably, it could appear as if the RENAMED variable contains both the original and the new path being renamed. In previous versions, it would even appear on some platforms as if the original always came before the new. However, none of this was true. It's impossible to reliably and portably know which changed path is the old or new, "half" renames may appear (only the original, only the new), "unknown" renames may appear (change was a rename, but whether it was the old or new isn't known), rename events might split across two debouncing boundaries, and so on. 😭 do not build your whole personality on rename ordering, i am begging

This option controls where that information is emitted. It defaults to none, which doesn't emit event information at all. The other options are environment (deprecated), stdio, file, json-stdio, and json-file.

The stdio and file modes are text-based: stdio writes absolute paths to the stdin of the command, one per line, each prefixed with create:, remove:, rename:, modify:, or other:, then closes the handle; file writes the same thing to a temporary file, and its path is given with the $WATCHEXEC_EVENTS_FILE environment variable.

There are also two JSON modes, which are based on JSON objects and can represent the full set of events Watchexec handles. Here's an example of a folder being created on Linux:

{
  "tags": [
    {
      "kind": "path",
      "absolute": "/home/user/your/new-folder",
      "filetype": "dir"
    },
    {
      "kind": "fs",
      "simple": "create",
      "full": "Create(Folder)"
    },
    {
      "kind": "source",
      "source": "filesystem"
    }
  ],
  "metadata": {
    "notify-backend": "inotify"
  }
}

The fields are as follows:

  • tags, structured event data.
    • tags[].kind, which can be:
      • path, along with:
        • absolute, an absolute path.
        • filetype, a file type if known (dir, file, symlink, other).
      • fs:
        • simple, the "simple" event type (access, create, modify, remove, or other).
        • full, the "full" event type, which is too complex to fully describe here, but looks like General(Precise(Specific)).
      • source, along with:
        • source, the source of the event (filesystem, keyboard, mouse, os, time, internal).
      • keyboard, along with:
        • keycode. Currently only the value eof is supported.
      • process, for events caused by processes:
        • pid, the process ID.
      • signal, for signals sent to Watchexec:
        • signal, the normalised signal name (hangup, interrupt, quit, terminate, user1, user2).
      • completion, for when a command ends:
        • disposition, the exit disposition (success, error, signal, stop, exception, continued).
        • code, the exit, signal, stop, or exception code.
  • metadata, additional information about the event.

The json-stdio mode will emit JSON events to the standard input of the command, one per line, then close stdin. The json-file mode will create a temporary file, write the events to it, and provide the path to the file with the $WATCHEXEC_EVENTS_FILE environment variable.

Finally, the environment mode was the default until 2.0. It sets environment variables with the paths of the affected files, for filesystem events:

$WATCHEXEC_COMMON_PATH is set to the longest common path of all of the below variables, and so should be prepended to each path to obtain the full/real path. Then:

  • $WATCHEXEC_CREATED_PATH is set when files/folders were created
  • $WATCHEXEC_REMOVED_PATH is set when files/folders were removed
  • $WATCHEXEC_RENAMED_PATH is set when files/folders were renamed
  • $WATCHEXEC_WRITTEN_PATH is set when files/folders were modified
  • $WATCHEXEC_META_CHANGED_PATH is set when files/folders' metadata were modified
  • $WATCHEXEC_OTHERWISE_CHANGED_PATH is set for every other kind of pathed event

Multiple paths are separated by the system path separator, ; on Windows and : on unix. Within each variable, paths are deduplicated and sorted in binary order (i.e. neither Unicode nor locale aware).

This is the legacy mode, is deprecated, and will be removed in the future. The environment is a very restricted space, while also limited in what it can usefully represent. Large numbers of files will either cause the environment to be truncated, or may error or crash the process entirely. The $WATCHEXEC_COMMON_PATH is also unintuitive, as demonstrated by the multiple confused queries that have landed in my inbox over the years. Default: none

like genuinely do not start new projects on environment mode ok 🚩

  • --only-emit-events β€” only emit events to stdout, run no commands.

This is a convenience option for using Watchexec as a file watcher, without running any commands. It is almost equivalent to using cat as the command, except that it will not spawn a new process for each event.

This option requires --emit-events-to to be set, and restricts the available modes to stdio and json-stdio, modifying their behaviour to write to stdout instead of the stdin of the command. πŸ‘‘

  • --watchexec-env <KEY=VALUE> β€” add env vars to the command

This is a convenience option for setting environment variables for the command, without setting them for the Watchexec process itself.

Use key=value syntax. Multiple variables can be set by repeating the option.

This is watchexec's --env. In mise, -E/--env selects the mise environment (mise.<ENV>.toml), as it does for every other command. name collision spotted, this is why we can't have nice things 🫢

  • --wrap-process <MODE> β€” how to wrap the task process: group, session, or none

By default watchexec uses a session on macOS, a process group on other Unix systems, and a Job Object on Windows. Some programs need a session, and some do not work in a process group; none runs the command directly. On Windows, group and session both use a Job Object. πŸŒ€

  • -N, --notify β€” alert when commands start and end

With this, Watchexec will emit a desktop notification when a command starts and ends, on supported platforms. On unsupported platforms, it may silently do nothing, or log a warning. it's giving "sent from my macbook" energy πŸ””

  • --color <MODE> β€” when to use terminal colours

Setting the environment variable NO_COLOR to any value is equivalent to --color=never.

Default: auto

  • --timings β€” print how long the command took to run

This may not be exactly accurate, as it includes some overhead from Watchexec itself. Use the time utility, high-precision timers, or benchmarking tools for more accurate results. ⏱️ numbers are vibes-adjacent, not gospel

  • --watchexec-quiet β€” don't print starting and stopping messages

Silence. Peace. finally 🀫

  • --quiet β€” okay so normally Watchexec prints a lil message when the command starts and when it stops, and this flag turns that off, so literally only the command's output, warnings, and errors get printed. Ngl this is watchexec's own --quiet. In mise, -q/--quiet quiets mise's own messages, the same way it does for every other command. two different quiets, iykyk πŸ’…
  • --bell β€” rings the terminal bell when the command finishes πŸ”” cute lil audio cue
  • --project-origin <DIRECTORY> β€” sets the project origin

Watchexec tries to figure out the project's "origin" (or "root") by hunting for a bunch of markers, like files or directory patterns. It does its best but sometimes gets it wrong β€” yes, it literally does its best, and you can override it with this option. 🫢

The project origin is what determines the path of certain ignore files, which VCS is being used, the meaning of a leading / in filtering patterns, and maybe more stuff in the future.

When you set it, Watchexec also won't bother searching, which can be significantly faster ⚑

The directory must contain every watched task's sources, because mise makes them relative to it.

  • --workdir <DIRECTORY> β€” has no effect: mise runs each task from its own dir

It's accepted so that scripts that pass it keep working. Forwarding it would make the nested mise run look for tasks in that directory instead of this project. so like, it's a no-op on purpose, don't @ me 😭

  • -e, --exts <EXTENSIONS> β€” only react to files with these extensions, e.g. js,ts

Give extensions with or without the leading dot. Repeat the flag or separate extensions with commas. easy ✨

  • -f, --filter <PATTERN> β€” only react to files that match this glob

It's combined with the patterns mise derives from the tasks' sources. Repeat the flag for more patterns. Events that don't come from files β€” like signals β€” pass through. πŸ¦‹

  • --filter-file <PATH> β€” files to load filters from

Give it a path to a file containing filters, one per line. Empty lines and lines starting with # are ignored. Uses the same pattern format as the --filter option.

This can also be used via the $WATCHEXEC_FILTER_FILES environment variable. Environment: WATCHEXEC_FILTER_FILES

  • -J, --filter-prog <EXPRESSION> β€” [experimental] filter programs.
⚠️ /!\ This option is EXPERIMENTAL and may change and/or vanish without notice. fr fr, do not build your whole life on it πŸ’€

You provide your own custom filter programs in jaq (similar to jq) syntax. Programs are given an event in the same format as described in --emit-events-to and must return a boolean. Invalid programs will make watchexec fail to start; use -v to see program runtime errors.

On top of the jaq stdlib, watchexec adds some custom filter definitions:

  • path | file_meta returns file metadata or null if the file does not exist.
  • path | file_size returns the size of the file at path, or null if it does not exist.
  • path | file_read(bytes) returns a string with the first n bytes of the file at path. If the file is smaller than n bytes, the whole file is returned. There is no filter to read the whole file at once β€” that's on purpose, to encourage limiting the amount of data read and processed.
  • string | hash, and path | file_hash return the hash of the string or file at path. No guarantee is made about the algorithm used: treat it as an opaque value. πŸ”’
  • any | kv_store(key), kv_fetch(key), and kv_clear provide a simple key-value store. Data is kept in memory only, there is no persistence. Consistency is not guaranteed.
  • any | printout, any | printerr, and any | log(level) will print or log any given value to stdout, stderr, or the log (levels = error, warn, info, debug, trace), and pass the value through (so [1] | log("debug") | .[] will produce a 1 and log [1]).

All filtering done with such programs β€” and especially those using kv or filesystem access β€” is much slower than the other filtering methods. If filtering is too slow, events will back up and stall watchexec. Take care when designing your filters, bestie, this is the spicy part 🌢️

If the argument to this option starts with an @, the rest of the argument is taken to be the path to a file containing a jaq program.

Jaq programs are run in order, after all other filters, and they short-circuit: if a filter (jaq or not) rejects an event, execution stops right there, and no other filters are run. Additionally, they stop after outputting the first value, so you'll want to use any or all when iterating, otherwise only the first item will be processed, which can be quite confusing! 😭

Find user-contributed programs or submit your own useful ones at https://github.com/watchexec/watchexec/discussions/592.

Examples:

Regexp ignore filter on paths:

all(.tags[] | select(.kind == "path"); .absolute | test("[.]test[.]js$")) | not

Pass any event that creates a file:

any(.tags[] | select(.kind == "fs"); .simple == "create")

Pass events that touch executable files:

any(.tags[] | select(.kind == "path" and .filetype == "file"); .absolute | file_meta | .executable)

Ignore files that start with shebangs:

any(.tags[] | select(.kind == "path" and .filetype == "file"); .absolute | file_read(2) == "#!") | not
  • -i, --ignore <PATTERN> β€” ignore files that match this glob

Repeat the flag for more patterns. Events that don't come from files β€” signals, for example β€” pass through. πŸ™ˆ

  • --ignore-file <PATH> β€” read ignore patterns from a file, one per line

Empty lines and lines that start with # are skipped. The patterns use the same format as --ignore. Also read from $WATCHEXEC_IGNORE_FILES. Environment: WATCHEXEC_IGNORE_FILES

  • --fs-events <EVENTS> β€” filesystem events to filter to

This is a quick filter to only emit events for the given types of filesystem changes. Choose from access, create, remove, rename, modify, metadata. Multiple types can be given by repeating the option or by separating them with commas. By default, this is all types except for access.

This may apply filtering at the kernel level when possible, which can be more efficient, but may be more confusing when reading the logs. πŸ‘€ Default: create,remove,rename,modify,metadata

  • --no-meta β€” don't emit fs events for metadata changes

This is a shorthand for --fs-events create,remove,rename,modify. Using it alongside the --fs-events option is non-sensical and not allowed. pick one, babe πŸ’…

  • --print-events β€” print the events that trigger each run

Use it to check which files --watch, --filter, and the tasks' sources are reacting to. lowkey the best debugging tool here πŸ”₯

  • --manual β€” show the manual page

This shows the manual page for Watchexec, if the output is a terminal and the man program is available. If not, the manual page is printed to stdout in ROFF format (suitable for writing to a watchexec.1 file).

  • -h, --help β€” print help

Arguments:

  • <TASK> β€” task to watch (default: default); separate several tasks with :::
  • <ARGS> β€” arguments for the task; ::: starts the next task

Examples:

Run build and rerun it whenever its sources change 🌈

mise watch build

Clear the screen before each run ✨

mise watch build --clear

Start an API server and restart it when Rust files in ./src change πŸ¦‹

mise watch serve --watch src --exts rs --restart

Pass arguments after -- to the task

mise watch test -- --verbose

Wait for a source to change, run test once, and exit with its status πŸ‘‘

mise watch test --once

πŸŽ€ MISE WHERE πŸŽ€

Show the install directory of a tool version.

It fails if no matching version is installed. no silent vibes here, it will tell you πŸ’€

Usage:

mise where [OPTIONS] <TOOL@VERSION> [<ASDF_VERSION>]

✨ Options ✨

  • -h, --help β€” print help

Arguments:

  • <TOOL@VERSION> β€” tool to look up, such as ruby@3

With a version prefix, it shows the newest installed version that matches it. Otherwise, it shows the active installed version. 🫢

  • <ASDF_VERSION> β€” the version prefix to use when querying the latest version, same as the first argument after the @, used for asdf compatibility

Examples:

Show the newest installed node 20.x

mise where node@20
~/.local/share/mise/installs/node/20.0.0

Show the active node, or the newest installed node if no config requests one

mise where node
~/.local/share/mise/installs/node/20.0.0

πŸ¦‹ MISE WHICH πŸ¦‹

Show the path a tool's executable resolves to.

It prints the real path of the executable mise would run for BIN_NAME in the current directory, bypassing shims. Use --version or --plugin to see which tool version provides it. iykyk πŸ‘‘

Usage:

mise which [OPTIONS] [<BIN_NAME>]

✨ Options ✨

  • -t, --tool <TOOL@VERSION> β€” look in a specific tool version, such as mise which npm --tool=node@20
  • --complete β€” (no description in the original, it's just there being mysterious πŸ’…)
  • --plugin β€” show the name of the tool that provides the executable
  • --version β€” show the version instead of the path
  • -h, --help β€” print help

Arguments:

  • <BIN_NAME> β€” the executable to look up

Examples:

Show the path of the node executable

mise which node
~/.local/share/mise/installs/node/20.0.0/bin/node

Show the tool that provides it

mise which node --plugin
node

Show the version that provides it

mise which node --version
20.0.0

🌈 EXAMPLES 🌈

okay bestie here's the whole greatest-hits tour, no cap πŸŽ€

Install node 24 and add it to the project's mise.toml

mise use node@24

Make node 24 your global default πŸ‘‘

mise use -g node@24

Install every tool the config requests

mise install

Run a command with the project's tools on PATH

mise x -- npm install

Run a command with a tool that is not in the config 🧚

mise x python@3.13 -- python app.py

Add an environment variable to mise.toml

mise set NODE_ENV=production

Run the build task

mise run build

Rerun the build task when its sources change πŸ”₯

mise watch build

Choose tools to upgrade from a menu

mise upgrade --interactive

Turn off color in the global config

mise settings color=0

πŸ‘‘ AUTHOR πŸ‘‘

Lowkey the whole thing was written by Jeff Dickey <@jdx> β€” yes, the one and only, the main character who built this so the rest of us could vibe πŸ’…


okay bestie that's a wrap, we literally made it to the end πŸŽ€ this is the MISE(1) manual page, version 1, dated as it says in the footer β€” go touch some grass, then come back and mise all the things βœ¨πŸ¦‹ you're gonna slay, fr fr πŸ’œ

πŸ“¦ where this page comes from