MISE(1)
π¦ 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 themise.<ENV>.tomlconfig files (same asMISE_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 thejobssetting. 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 inmise.toml, such asnode@24 python@3.13.-v,--verboseβ Show extra output (use-vvfor 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 asMISE_NO_CONFIG=1.--no-envβ Do not load environment variables from config files. Same asMISE_NO_ENV=1.--no-hooksβ Do not run hooks from config files. Same asMISE_NO_HOOKS=1.--no-timingsβ Hide the elapsed time printed after each task completes. SetMISE_TASK_TIMINGS=0to hide it by default.--output <OUTPUT>β How task output is displayed when running a task (same asmise run --output).--rawβ Connect tasks and install commands directly to the terminal. Commands then run one at a time. Same asMISE_RAW=1or therawsetting.--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 asMISE_LOCKED=1or thelockedsetting.--silentβ Suppress all task output and mise non-error messages. Full ghost mode. π»--timingsβ Show the elapsed time after each task completes. SetMISE_TASK_TIMINGS=1to 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 formise 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 configurednix: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 theoptpath 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 capdaemonsβ [experimental] manages project daemons with pitchfork π§- Aliases:
daemon
- Aliases:
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 updaemons 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 groupdaemons registerβ [experimental] registers project daemons so they can start on demand β¨daemons stopβ [experimental] stops project daemonsdaemons restartβ [experimental] restarts project daemonsdaemons lsβ [experimental] lists project daemons- Aliases:
list
- Aliases:
daemons urlsβ [experimental] shows each daemon's URL and port πdaemons logsβ [experimental] shows the output of project daemonsdaemons statusβ [experimental] shows the status of project daemonsdaemons 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
- Aliases:
dotfiles addβ starts deploying a file, or copies its edits back to the sourcedotfiles applyβ links, copies, and renders[dotfiles]entries into place β¨dotfiles captureβ runs a command and saves tracked files before and after itdotfiles conflictsβ compares both sides of a sync conflict, so you can see who did what πdotfiles diffβ shows whatmise dot applywould changedotfiles editβ opens a dotfile's source in your editor πdotfiles excludeβ never saves paths matching a glob, boundaries bestiedotfiles historyβ browses saved versions of your tracked files π°οΈdotfiles history describeβ sets the description of a checkpointdotfiles history diffβ compares checkpoints, or compares your files against onedotfiles history lsβ lists checkpoints, newest first- Aliases:
list
- Aliases:
dotfiles history purgeβ erases a path's saved versions from history πdotfiles history showβ shows a checkpoint: its trigger, changes, and operation journaldotfiles 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 repositorydotfiles origin setβ connects an origin repositorydotfiles pathsβ lists tracked paths and how they're saveddotfiles pullβ writes fetched changes from other machines into your tracked files π«Άdotfiles recoverβ recovers an interrupted dotfile operation, we love a comebackdotfiles rollbackβ returns files to the version a checkpoint holds βͺdotfiles saveβ saves a checkpoint of the tracked files, right now, periodtdotfiles statusβ shows the state of your dotfiles and their history- Aliases:
ls
- Aliases:
dotfiles syncβ pushes saved checkpoints and fetches incoming changes πdotfiles trackβ tracks a file or directory in placedotfiles unapplyβ removes files thatmise dot applydeployeddotfiles undoβ reverses the tracked-file changes from an operation β©οΈdotfiles untrackβ stops tracking a file or directorydotfiles watchβ saves tracked files as they change πdoctorβ checks your mise setup for problems π©Ί- Aliases:
dr
- Aliases:
doctor pathβ prints the directories mise adds toPATH- Aliases:
paths
- Aliases:
doctor projectβ runs the project's diagnostic checksenβ starts a subshell with mise's tools and environment πenvβ prints the environment for the current configuration- Aliases:
e
- Aliases:
execβ runs a command with mise's tools and environment- Aliases:
x
- Aliases:
fmtβ formats mise TOML configuration πgenerateβ generates project files like CI workflows, git hooks, and scripts- Aliases:
gen,g
- Aliases:
generate configβ generates amise.tomlfilegenerate 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
- Aliases:
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 misegenerate task-docsβ generates Markdown documentation for project tasks πgenerate task-stubsβ generates scripts that run mise tasksgenerate tool-stubβ generates or updates a tool stubimplodeβ removes the mise CLI and all related data π₯ (yes, all of it, so dramatic)editβ editsmise.tomlinteractively βοΈinstallβ installs the tools in your config, or specific tool versions- Aliases:
i
- Aliases:
install-intoβ installs a tool version into a directory outside miseinstallsβ [experimental] inspects and chooses identity-layout installationsinstalls lsβ lists the installations of the identity install layout- Aliases:
list
- Aliases:
installs migrateβ reinstalls legacy installations into the identity install layoutinstalls selectβ chooses which installation mise uses when no lockfile pins one π―latestβ prints the latest version that matches a version requestlinkβ symlinks a tool version into mise- Aliases:
ln
- Aliases:
lockβ creates or refreshes lockfile versions, checksums, and download URLs πlsβ lists installed and active tool versions- Aliases:
list
- Aliases:
ls-remoteβ lists tool versions available to install- Aliases:
list-all,list-remote
- Aliases:
lspβ runs the language server for mise config files over stdin/stdoutmcpβ runs the Model Context Protocol server over stdin/stdout π€ociβ [experimental] builds, pushes, and runs OCI images of a project's toolsoci buildβ [experimental] builds an OCI image from the currentmise.tomloci 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 itpackslipβ inspects and resets the signers mise has pinned for packslip toolspackslip forgetβ forgets a project's pinned signer so the next accepted release sets itpackslip pinsβ lists the signer mise has pinned for each packslip project π- Aliases:
list
- Aliases:
outdatedβ shows outdated tool versions π΅patronsβ shows the individuals supporting mise as Patron-tier members πpluginsβ manages plugins- Aliases:
p,plugin,plugin-list
- Aliases:
plugins installβ installs plugins from a configured source, Git URL, or archive- Aliases:
i,a,add
- Aliases:
plugins linkβ links a local plugin directory into mise for development- Aliases:
ln
- Aliases:
plugins lsβ lists installed plugins- Aliases:
list
- Aliases:
plugins ls-remoteβ lists registry tools that have an asdf or vfox plugin backend- Aliases:
list-remote,list-all
- Aliases:
plugins uninstallβ removes an installed plugin- Aliases:
remove,rm
- Aliases:
plugins updateβ updates installed plugins- Aliases:
up,upgrade
- Aliases:
depsβ [experimental] manages project dependencies- Aliases:
dep,prepare
- Aliases:
deps addβ adds packages to the project's dependencies βdeps installβ installs project dependenciesdeps removeβ removes packages from the project's dependencies βpruneβ deletes tool versions that nothing uses π§Ήregistryβ lists registry shorthand names and their backendsreshimβ creates shims for executables provided by installed toolsrunβ runs tasks and their dependencies πββοΈ- Aliases:
r
- Aliases:
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
- Aliases:
self-updateβ updates mise itself β¨setβ sets, shows, or lists environment variables inmise.toml- Aliases:
ev,env-vars
- Aliases:
settingsβ manages settings βοΈsettings addβ appends a value to an array settingsettings getβ shows the effective value of a settingsettings lsβ lists configured settings and their sources- Aliases:
list
- Aliases:
settings setβ sets a setting- Aliases:
create
- Aliases:
settings unsetβ removes a setting from the global or project config- Aliases:
rm,remove,delete,del
- Aliases:
shellβ sets a tool version for the current shell session π- Aliases:
sh
- Aliases:
sshβ opens an SSH session, optionally borrowing read-only GitHub access πshell-aliasβ manages shell aliasesshell-alias getβ shows the command for a shell aliasshell-alias lsβ lists shell aliases- Aliases:
list
- Aliases:
shell-alias setβ sets a shell alias in the global config- Aliases:
add,create
- Aliases:
shell-alias unsetβ removes a shell alias from the global config- Aliases:
rm,remove,delete,del
- Aliases:
skillsβ lists and links the agent skills that active tools ship π§- Aliases:
skill
- Aliases:
skills lsβ lists the skills the active tools declare- Aliases:
list
- Aliases:
skills syncβ links the active tools' skills where an agent looks for themsponsorsβ shows the companies sponsoring mise and the jdx.dev open source tools π«Άsyncβ uses tool versions installed by other version managerssync nodeβ symlinks node versions installed by nvm, nodenv, or Homebrew into misesync 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
- Aliases:
tasks addβ adds a tasktasks depsβ shows the dependency tree of tasks π³tasks editβ opens a task in your editortasks graphβ shows the monorepo project graph πtasks infoβ shows a task's definitiontasks 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:
~/.bashrcfor Bash~/.zshrcfor Zsh~/.config/fish/config.fishfor Fish$PROFILEfor PowerShell
For Nushell, Elvish and other shells, see https://mise.jdx.dev/shell-setup.html π
The mise executable has to be onPATHbefore that line runs. If it isn't, use its absolute path instead, for exampleeval "$(~/.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 runhook-envautomatically
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 onPATHinstead of updatingPATHat 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 amise: <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 withname,path, andsymlink(implies--bin-names)-h,--helpβ prints help
Arguments
<TOOL@VERSION>β only list these tools, such asruby@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.
accounts, thenplugins(package manager plugins)fileswithphase = "pre-packages", then built-inpackages- The remaining
files, thenservices,firewall, andcompose repos, thendotfilesmise-shell-activate,macos-defaults, andmacos-launchd-agentslinux-systemd-units, thenuser(the login shell)tools- Plugin
packages, then userserviceswithrequires_tools = true task(thebootstraptask, if defined), thenfinal-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--fromcheckout (default:$MISE_DATA_DIR/bootstrap-repo)--config-dir <DIR>β Link the global config directory to this directory of the--fromcheckout
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 apromptand 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 status1if 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 ofdenyorrejectunless a rule allows the current connection or the config setsallow_lockout = true. That's your lockout protection, no cap. Always checkapply --dry-runbefore 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 status1if 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 status1if 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 status1if 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 status1if 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 status1if 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".
applyinstalls what's missing and removes what is declared absentuseadds an entry and installs itupgradeupdates configured packages that are installedpruneuninstalls Homebrew formulae, casks, or package plugin packages that no config declaresimportrecords installed Homebrew formulaestatusshows 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.applyfails for it only when you pass--manageror 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,aptrunsapt-get updateanddnfadds--refresh. Meanwhilebrew,brew-cask,flatpak,flatpak-user,macos-app,mas, andsnapignore this flag entirely (not them being unbothered π)-h,--helpβ print help π
π§Ύ ARGUMENTS π§Ύ
<PACKAGE>β packages asmanager: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, likeowner/repo<URL>β the GitHub URL of the tap; defaults tohttps://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, likeowner/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 thewrite_targets.packagesfile 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 π
β οΈ Forbrew(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-runfirst, or record your existing formulae withmise bootstrap packages importbefore 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β removebrew-caskcasks 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 asmanager: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 thewrite_targets.packagesfile 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 inmanager: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, asbrew:<formula>orbrew:<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 thebootstraptask are not planned here. If you want the whole run previewed, domise bootstrap --dry-runinstead. 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β exits0if nothing would change,2if something would, and1on 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 status1if 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 plustar,mktemp,cksum, anduname. 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 onPATH--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-ooption; 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-repoor--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 thegithub_relaysettings (needs--github-relay-read-only)--github-relay-log-format <FORMAT>β relay log and summary format,textorjsonl(needs--github-relay-read-only)--github-relay-max-duration <DURATION>β end borrowed access after a duration such as1h;0slasts 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 status1if 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 asnode
π 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 asnode
π 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 thepackslip: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 astools.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. Usemise useto install and select a version together. For environment variables and settings,mise setandmise settings setare shorter, but they choose their file differently:mise setwrites the nearestmise.toml, andmise settings setwrites 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 astools.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 asapi, or qualified, such asshop/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 asapi, or qualified, such asshop/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 asapi, or qualified, such asshop/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 asapi, or qualified, such asshop/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 asapi, or qualified, such asshop/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 topitchfork 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, ortemplate(default: whatever thedotfiles.default_modesetting 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 withmise dot pull --take-remoteor--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,absententries, 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, ortemplate(default: thedotfiles.default_modesetting)-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 (0for all). Default:20--path <PATH>β only checkpoints where this path (or something under it) changed--trigger <TRIGGER>β only checkpoints with this trigger, such asedit,save,agent,bootstrap,apply,rollback, orundo--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, orcommit:<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β exit1when 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, orcommit:<sha><B>β compareAwith 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 (0for all). Default:20--path <PATH>β only checkpoints where this path (or something under it) changed--trigger <TRIGGER>β only checkpoints with this trigger, such asedit,save,agent,bootstrap,apply,rollback, orundo--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 underrefs/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 withgit update-ref -donce 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>β resolvelatest~Namong the checkpoints where this path changed-h,--helpβ print help
Arguments
<REF>β numeric checkpoint ID,latest(the default),latest~N, orcommit:<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 bymise 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 withmise 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 getsmain, which the first push creates. π¦--sync <MODE>β how to sync with the repository:sync,fetch-only, ormanual.syncpushes saved checkpoints and applies incoming changes automatically.fetch-onlyfetches automatically and never pushes.manualmakes no automatic network calls:mise dot syncpushes and fetches, andmise dot pullapplies, only when you run them; local history is still saved automatically. When omitted, mise prompts; with--yes, it uses thehistory.syncsetting.-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;pullskips 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-localkeep 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-remotetake 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 (seemise 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, orcommit:<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 asave,agent, orupdatecheckpoint. 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 code1if any dotfile is not in its desired state (missing,source missing, ordiffers). 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_ENVor-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 onmise 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, orcommit:<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:--oncemeans zero retries. One shot, one sync, and if it flops you get exit1. 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 asnode@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 thejobssetting. Values below1are treated as1. 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-readfor everything else)--allow-write <PATH>β Allow writes to PATH (implies--deny-writefor everything else)--deny-allβ Block reads, writes, network, and env vars--deny-envβ Block env var inheritance exceptPATH,HOME,USER,SHELL,TERM,COLORTERM,LANG. On Windows it also keeps the variables programs need to start, such asSystemRootandTEMP.--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 asnode@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
sourcesandoutputs task_config.global_inputsandinput_groupsredactions
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; exits1if 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-versionsfile into the config, without opening the editor π«Ά-h,--helpβ print help
ARGUMENTS
<PATH>β config file to edit or create; defaults tomise.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 tomcr.microsoft.com/devcontainers/base:ubuntu-m,--mount-mise-dataβ keep installed tools in amise-data-volumeDocker volume so they survive rebuilds πΎ Mounts the volume at/mnt/mise-data, setsMISE_DATA_DIRto it, and adds its shims directory toPATH.-n,--name <NAME>β container name; defaults tomise-w,--writeβ write to.devcontainer/devcontainer.jsoninstead 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, orcore.hooksPathwhen it is set. An existing hook of the same name is moved to<HOOK>.old.--hook <HOOK>β which git hook to write, such aspre-pushDefault:pre-commit-h,--helpβ print help
ARGUMENTS
<MISE_ARG>β mise flags to embed in the generated hook, given after--These are inserted betweenmiseandrun, 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 subdirmakes 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>.ymlinstead 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 (.miseby default) π Use--localized-dirto 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 releasemise self-updatewould install π-w,--write <PATH>β write the script to PATH (./bin/misewhen 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--outputfile π― Replaces everything between<!-- mise-tasks -->and<!-- /mise-tasks -->in the--outputfile, 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--outputto 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 tomisefrom 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:
- Uses mise from PATH, or
~/.local/bin/mise - Otherwise installs mise to
~/.local/binwith the embedded installer - Runs the tool stub with mise
--bootstrap-version <BOOTSTRAP_VERSION>β mise version the--bootstrapscript 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 aslinux-x64:bin/tool; repeatable--platform-url <PLATFORM_URL>β Download URL for one platform, asPLATFORM:URLor 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-versionsfile into the config, without opening the editor-h,--helpβ Print help
π¦ Arguments π¦
<PATH>β Config file to edit or create; defaults tomise.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 noTOOLarguments, it reinstalls every configured tool π (no cap, that's a lot)-j,--jobs <JOBS>β how many tools to install in parallel; defaults to thejobssetting. 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 whethermise installhas 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--monorepoto include tasks from every configured root π«Ά--include-lazyβ also install tools configured withlazy = true. By default, a baremise installleaves 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 as2024-06-01or a duration such as90dor1y. Overrides theminimum_release_agesetting and tool option π°οΈ--monorepoβ also install tools from every config root in[monorepo].config_roots. Requiresmonorepo_root = trueand an explicitconfig_rootslist in the monorepo root's config. Uses the activeMISE_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(orMISE_SYSTEM_DATA_DIR/installs). On Unix, binary-download backends invokesudoto publish into protected system directories unlesssystem_packages.sudois disabled. Run mise as your user, withoutsudoβ οΈ-h,--helpβ print help
π ARGUMENTS π
<TOOL@VERSION>β tools to install, such asnode@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 asnode@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 as2024-06-01or a duration such as90dor1y. Overrides theminimum_release_agesetting and tool option π°οΈ-h,--helpβ print help
π ARGUMENTS π
<TOOL@VERSION>β tool, optionally with a version prefix, such asnodeornode@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
π MISE LINK
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.lockand 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 thejobssetting. 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 aslinux-x64,macos-arm64. Defaults to thelockfile_platformssetting 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 lockrefreshes 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.--bumpnever modifies config files: exact versions resolve to themselves and stay unchanged (usemise upgrade --bumpto rewrite pins inmise.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, somise lock --jsonprints[]when no version changed, even though it still updates the lockfile. Suppresses the human-readable output. Combine with--dry-runto detect available updates without writing the lockfile.--localβ updatemise.local.lock, for tools inmise.local.toml, instead ofmise.lock--minimum-release-age <AGE>β only lock versions released before a date or at least a duration ago. Takes a date such as2024-06-01or a duration such as90dor1y. Overrides theminimum_release_agesetting 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. Seehttps://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 tomise.lock; seehttps://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--jsonfor machine-readable output, or with--localand--globalto choose the lockfiles.-h,--helpβ print help
π«Ά Arguments π«Ά
<TOOL>β tools to lock, such asnode python; defaults to every configured tool and every tool a task needs. Usetool@versionto lock an exact version. If it falls outside the configured request,mise.tomlis 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 asaqua,cargo,core, orgo. Registry shorthands count as the backend they resolve to, sojqis listed underaqua. 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--backendto filter JSON output.-J,--jsonβ output in JSON format-l,--localβ deprecated alias for--no-global. Removed in mise2027.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, andMISE_<TOOL>_VERSIONenvironment variables. See--projectfor 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 asmise.toml,mise.local.toml,conf.dfragments,.tool-versionsand idiomatic version files. Configs in parent directories and global or system configs do not, nor doMISE_<TOOL>_VERSIONenvironment variables. A version that a later file in that directory overrides is not listed, as with--no-global;mise uninstall --projectstill 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 somise prunekeeps the versions they use.--monorepoβ also list tools from every config root in[monorepo].config_roots. Requiresmonorepo_root = trueand an explicitconfig_rootslist in the monorepo root's config. Uses the activeMISE_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 withPREFIX(requires a tool argument)--prunableβ list only tools that can be pruned withmise 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 as2024-06-01or a duration such as90dor1y. This overrides theminimum_release_agesetting and tool option.-J,--jsonβ output in JSON format, with metadata such ascreated_atwhen available π--no-versions-hostβ fetch versions from the tool's upstream instead of mise's version mirror. Same asuse_versions_host = falsefor this command.--prereleaseβ include prerelease versions. Works for backends that report prerelease metadata or detect prereleases by pattern. Same asMISE_PRERELEASES=1or theprereleasessetting, 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--jsonand--no-versions-host.-h,--helpβ print help
π¦ Arguments π¦
<TOOL@VERSION>β the tool to get versions for<PREFIX>β version prefix to filter by; same asTOOL@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 fmtdoes - 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_forandrun = [{ task = "..." }](and of templates inextends), 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=trueadds the rest)mise://tasksβ task definitions, including monorepo subproject tasksmise://envβ environment variablesmise://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 effectrun_taskβ run a task with your permissions; it can change files and call external servicesinstall_toolβ install a tool version, asmise installdoes
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. β
β οΈ Requiresmise settings experimental=true(orMISE_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].fromand theoci.default_fromsetting)--include-globalβ also package tools from the global and system configs. By defaultmise oci buildpackages 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.tomlend up in the image.-t,--tag <TAG>β tag to record in the image index (theorg.opencontainers.image.ref.nameannotation)--mount-point <MOUNT_POINT>β where tools install inside the image. Overrides[oci].mount_pointand theoci.default_mount_pointsetting.--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_idand[oci].group_id. Defaults to0:0. IfGIDis omitted, it defaults toUID. This affects file ownership only;[oci].usercontrols the imageUSERdirective.-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].fromand theoci.default_fromsetting π.--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. Seemise oci build --helpfor the details πΈ.--mount-point <MOUNT_POINT>β where tools install inside the image. Overrides[oci].mount_pointand theoci.default_mount_pointsetting π.--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]>β theUID[:GID]to assign to every tar entry when building. Overrides[oci].user_idand[oci].group_id. Defaults to0:0. IfGIDis omitted, it defaults toUID. Heads up: this affects file ownership only β[oci].usercontrols the imageUSERdirective β.--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. Runmise oci push --update-indexfrom 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;autoprefers podman and falls back to docker. Default:autoπ.--from <FROM>β base image for the build. Overrides[oci].fromand theoci.default_fromsetting π.--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. Seemise oci build --helpfor 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 repeatedmise oci runcalls 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_pointand theoci.default_mount_pointsetting.--no-miseβ don't embed the running mise binary at/usr/local/bin/mise.--owner <UID[:GID]>β theUID[:GID]to assign to every tar entry when building. Overrides[oci].user_idand[oci].group_id. Defaults to0:0. IfGIDis omitted, it defaults toUID. Again: file ownership only β[oci].usercontrols the imageUSERdirective π .--volume <HOST:CONTAINER>β bind-mount a host path (repeatable,HOST:CONTAINER[:MODE]). Unlikedocker run, there's no-vshort form because mise uses-vfor--verboseπ. Use--volumeor--mount.-e,--env <KEY=VAL>β set environment variable in the container (repeatable,KEY=VAL) π.-i,--interactiveβ run interactively (passes-ito the engine).-t,--ttyβ allocate a TTY (passes-tto 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 changemise.lock. If the lockfile records the old signer, delete the tool's entries and runmise 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 withnode = "20"in your config,mise outdatedreports the newest 20.x release. With this flag thelatestcolumn shows the newest release overall, like24.1.0, and abumpcolumn shows the request thatmise upgrade --bumpwould write, like24. π-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 defaultmise outdatedchecks 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 aMISE_<TOOL>_VERSIONenvironment variable sets its own version of the tool: basically whatmise upgrade --globalwould 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 throughMISE_<TOOL>_VERSIONenvironment variables.--monorepoβ placeholder for future monorepo outdated checks;mise outdated --monorepois 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 asnode@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 asmise 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 asmain 1234abc--userβ list installed plugins. This is the default behavior but can be used with--coreto 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: thejobssetting)-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
π MISE PLUGINS LINK
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 asmise 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 asmain 1234abc--userβ list installed plugins. This is the default behavior but can be used with--coreto 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:--purgedoes not remove the tools of a backend plugin (<plugin>:<tool>). You gotta uninstall those first withmise 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: thejobssetting)-h,--helpβ print help
Arguments:
<PLUGIN>β plugins to update; append#refto 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 aPROVIDERargument)-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, likenpm:reactornpm:@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 aPROVIDERargument)-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, likenpm: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 code1if there are tools to prune
Use it in scripts that check whether tools need pruning. π€
--monorepoβ placeholder for future monorepo pruning;mise prune --monorepois 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 withmise 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 toMISE_AFFECTED_BASE, CI metadata, orHEAD~1.--affected-committedβ Count committed changes between the base and head revisions. Alone, it ignores the working tree. Combines with--affected-uncommittedand--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 byMISE_AFFECTED_COMMITTED.--affected-explainβ Explain why--affectedselected each project and task. π΅οΈββοΈ--affected-head <REV>β Git head revision for--affected. Defaults toMISE_AFFECTED_HEAD, CI metadata, orHEAD.--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 byMISE_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 byMISE_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: thejobssetting). 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 labelinterleaveβ Print directly to stdout/stderr instead of by linereplacingβ Stdout is replaced each time, stderr is printed as istimedβ Only show stdout lines if they are displayed for more than 1 secondkeep-orderβ Print stdout/stderr by line, prefixed with the task's label, but keep the order of the outputquietβ Deprecated; use--output interleave --quietsilentβ 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 therawsetting 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 withenv = trueorenv = "exec", never those withenv = 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 ownshell. Defaults tosh -o errexit -con Unix andcmd /con Windows, from theunix_default_inline_shell_argsorwindows_default_inline_shell_argssetting. A task'sshellproperty 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-envfor 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-readfor everything else).--allow-write <PATH>β Allow writes to a specific path (implies--deny-writefor everything else).--deny-allβ Block reads, writes, network, and env vars. Full lockdown mode. π«--deny-envβ Block env var inheritance exceptPATH,HOME,USER,SHELL,TERM,COLORTERM, andLANG. On Windows it also keeps the variables programs need to start, such asSystemRootandTEMP.--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 haveauto = truebefore the tasks.--no-timingsβ Hide the elapsed time printed after each task completes. Settask.timings = falseto 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. Settask.run_auto_install = falseto make this the default.--task-cache <TASK_CACHE>β [experimental] Set artifact cache access for this run:read-writeβ Read cached results and write new resultsread-onlyβ Read cached results without writing new resultswrite-onlyβ Write new results without reading cached resultsoffβ Disable the artifact cachelocal-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.30sor5m. Overrides thetask.timeoutsetting. β°--timingsβ Show the elapsed time after each task completes. Settask.timings = trueto 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
π MISE SEARCH
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, orfuzzy. 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
envsetting 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) andexec(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 as7d. Defaults to theself_update.minimum_release_agesetting, then theminimum_release_agesetting, else24h-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 tomise.<ENV>.tomlin the current directory, or to.mise.<ENV>.tomlif 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 writesconfig.<ENV>.override.tomlinstead. 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 theage.key_filesetting (or~/.config/mise/age.txtif it exists) and to~/.ssh/id_ed25519and~/.ssh/id_rsawhen 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 byMISE_DEFAULT_CONFIG_FILENAME(defaultmise.toml): https://mise.jdx.dev/configuration/settings.html#default_config_filename β to move the global config file, setMISE_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 asNODE_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 aspython<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 passSETTING=VALUEinstead, 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 aspython. 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. Setglobal_config_fileand similar through their environment variables, andceiling_pathsand similar in amiserc.tomlfile or their environment variables. Also,--localrefuses settings that only the global config can set, such asyes. 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 passSETTING=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: thejobssetting).
Environment: MISE_JOBS
-u,--unsetβ Remove a version set earlier withmise shell.--allβ With--unset, remove everyMISE_<TOOL>_VERSIONin 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 asnode@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 thegithub_relay.log_requestssetting is on.--github-relay-log-format <FORMAT>β Relay log and summary format:textorjsonl(default: thegithub_relay.log_formatsetting).--github-relay-max-duration <DURATION>β End borrowed access after a duration such as1h;0slasts 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 passALIAS=COMMANDlike 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 theskills.dirdirectory under your home directory instead of the project's. With the defaultskills.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 mise2027.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 (forfzfand 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 asmise tasks infodoes
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>β usemise.<ENV>.tomlin the current directory, or.mise.<ENV>.tomlif 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 frommise tasksand 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 asnode@24ornpm:prettier@3; repeat for several
Written to the task's tools table. Without a version, writes latest.
--usage <SPEC>β usage spec for the task's arguments and flags: https://usage.jdx.dev/spec/-h,--helpβ print help
πΈ 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 (forfzfand 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>β usemise.<ENV>.tomlin the current directory, or.mise.<ENV>.tomlif 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
--dependsreplaces the whole list. Not merges, not appends β replaces. --env-varand--toolsare the exceptions: they add or replace single entries of the task'senvandtoolstables.--unsetremoves a field, and that's also how a flag such ashidegoes back to false. Sneaky but correct. π«Ά- A command given after
--replaces the task'srun.
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: usemise tasks editfor them. Don't come attasks setwith 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>β usemise.<ENV>.tomlin the current directory, or.mise.<ENV>.tomlif 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 frommise tasksand 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 asnode@24ornpm:prettier@3; repeat for several.
Written to the task's tools table. Without a version, writes latest. Slay.
--usage <SPEC>β usage spec for the task's arguments and flags: https://usage.jdx.dev/spec/-h,--helpβ print help.
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
#USAGEspecs that do not parse- invalid
timeoutvalues - aliases that more than one task uses
- missing or non-executable file tasks
- invalid
dirpaths and templates - missing shell executables
- invalid
sourcesandoutputsglobs - broken task references in
runarrays - empty scripts
- tasks with nothing to run
- required
daemonsthat no readable[daemons]section declares secretsgrants 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 throwawayMISE_DATA_DIRandMISE_CACHE_DIRdirectories. 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 atestand supports this OS.-j,--jobs <JOBS>β number of tools to test in parallel (default4).
Environment: MISE_TEST_TOOL_JOBS
--all-configβ test all tools specified in config files.--include-non-definedβ also test registry tools that have notestentry 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, likenodeoraqua: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 asnode@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 asNODE_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>β editmise.<ENV>.tomlin the current directory, or.mise.<ENV>.tomlif 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: thejobssetting) 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 asgo python--dry-run-codeβ Like--dry-run, but exit with code1if 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 --monorepois 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 asnode@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>β Writemise.<ENV>.tomlin the current directory, or.mise.<ENV>.tomlif 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: thejobssetting) 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 code1if 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 as20fornode@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 as20.19.5fornode@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 asnode@24,cargo:ripgrep@latest, ornpm: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.gitignoreand.ignore--no-global-ignoreβ do not apply global ignore files, such as~/.gitignoreand~/.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, orother).full, the "full" event type, which is too complex to fully describe here, but looks likeGeneral(Precise(Specific)).
source, along with:source, the source of the event (filesystem,keyboard,mouse,os,time,internal).
keyboard, along with:keycode. Currently only the valueeofis 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_PATHis set when files/folders were created$WATCHEXEC_REMOVED_PATHis set when files/folders were removed$WATCHEXEC_RENAMED_PATHis set when files/folders were renamed$WATCHEXEC_WRITTEN_PATHis set when files/folders were modified$WATCHEXEC_META_CHANGED_PATHis set when files/folders' metadata were modified$WATCHEXEC_OTHERWISE_CHANGED_PATHis 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_PATHis 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, ornone
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/--quietquiets 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 owndir
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_metareturns file metadata or null if the file does not exist.path | file_sizereturns 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, andpath | file_hashreturn 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), andkv_clearprovide a simple key-value store. Data is kept in memory only, there is no persistence. Consistency is not guaranteed.any | printout,any | printerr, andany | 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 a1and 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 asruby@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 asmise 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
- arch rolling: mise 2026.10.25-1 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms