1---2name: mise-tool-management3description: Use mise (mise.jdx.dev) to manage binary CLI / build tools (swiftlint, swiftformat, xcbeautify, gitleaks, lefthook, etc.) on both dev machines and CI, sharing a single `.mise.toml` for version parity. Invoke when choosing a tool version manager (vs asdf / Homebrew / manual), writing `.mise.toml`, or when asked "how do I manage swiftlint / xcbeautify versions".4---56# mise Tool Management78## When to invoke910- Starting a new project and picking a version manager for binary CLI / build tools.11- Writing the first `.mise.toml`.12- Adding new binary tools (swiftlint, swiftformat, xcbeautify, gitleaks, lefthook, jq, yq, ...).13- Setting up CI (e.g. Xcode Cloud `ci_scripts/`) that needs to call tools.14- User asks "asdf vs mise", "why isn't Homebrew enough", "what about CI / local version drift".1516## Default decisions1718- **Adopt `mise`** ([mise.jdx.dev](https://mise.jdx.dev/)) to manage binary CLI / build tools.19- **Dev machine and CI share the same `.mise.toml`**, committed to git.20- Plugin backend priority: core plugin → `aqua:` → `github:`/`gitlab:` (release assets) → `asdf:` (legacy). `ubi:` is deprecated — mise's own release-backend docs mark it "Legacy release installer (deprecated)".21- **Xcode Cloud has no mise preinstalled** — its build environment ships only Homebrew, so a `ci_post_clone.sh` that starts with a bare `mise` command fails with "command not found". Commit a bootstrapped `bin/mise` (`mise generate bootstrap -l -w bin/mise`) and call it explicitly: first line `./bin/mise trust`, then `./bin/mise install`; subsequent tool invocations always go through `./bin/mise exec -- <tool> <args>` (see `xcode-cloud-single-track-ci` for the full hook). On a dev machine or any CI runner that already has mise on `PATH`, drop the `./bin/` prefix: `mise exec -- <tool> <args>`.22- **A freshly cloned repo or a freshly created git worktree starts with `.mise.toml` untrusted** — `mise install` / `mise exec` don't apply the pinned versions until `mise trust` has run once in that directory. Every new agent worktree and every CI checkout hits this; run `mise trust` before the first `mise install`/`mise exec` in each.2324## Rationale2526- A single file (`.mise.toml`) is the single source of truth; version drift is eliminated at the root.27- mise manages multiple languages / tools at once, no need for a separate version manager per tool.28- Stronger than Homebrew: pin to minor / patch versions, not "latest is the version".29- Faster than asdf: written in Rust, with small shell-hook overhead.3031## Example `.mise.toml`3233```toml34[tools]35swiftlint = "0.54"36xcbeautify = "1"37"aqua:gitleaks/gitleaks" = "8"38"aqua:evilmartians/lefthook" = "1"39# Xcode's own swift toolchain is already on PATH — don't pin it via a40# `swift = "system"` entry: mise deprecated @system tool versions41# ("use MISE_DISABLE_TOOLS instead"; set that env var if you need to42# suppress a swift entry inherited from a parent .mise.toml).43# Xcode is NOT pinned here; the toolchain SSOT is README / foundations.md +44# the Xcode Cloud workflow setting. A mise Xcode plugin is optional.45```4647## Deviation considerations4849- **Team already uses asdf heavily**: keep it for now, but new repos go to mise; mise can read `.tool-versions` as a transition.50- **Tool not in mise registry / aqua / ubi**: prefer a non-Homebrew path first. For a Go51 CLI, `go install <module>@latest` (a Go toolchain can itself come from mise). Otherwise,52 download the tool's plain GitHub Releases tarball directly for your platform — same53 install pattern as `idb` in `interactive-simulator-ux-audit`. Homebrew is a last resort;54 if a project policy bans it, record the exception in *that project's* README.55- **CI runner already has the target version preinstalled**: still run `mise install` to enforce parity; the extra overhead is small.56- **macOS-only tools on a mixed-OS CI fleet** (Xcode-project generators, macOS57 artifact bundlers — e.g. `tuist`, `LicensePlist`): guard them with an `os`58 field, `"aqua:tuist/tuist" = { version = "4", os = ["macos"] }`. A Linux CI job59 (L10n / lint / markdown gates run fine on Ubuntu) runs `mise install` which60 installs **every** tool; an unguarded macOS-only tool fails at setup61 (`unsupported env: linux/amd64`) **before any gate runs**, blocking *all* PRs.62 This can appear suddenly with no change of yours — an upstream registry can flip63 a tool to darwin-only mid-day, so earlier PRs pass and later identical ones fail64 at "install pinned tools". When CI dies at the mise-install step, read for65 `unsupported env: linux/amd64` and add the `os` guard.6667## Verification checklist6869- `.mise.toml` lives at the repo root, committed to git.70- After local `mise install`, `mise exec -- <tool> --version` matches CI log.71- CI scripts go through `mise exec`, never calling `/usr/local/bin/<tool>` or other preinstalled paths.72- The repo's contributor setup guide starts with 'install mise → `mise trust` → `mise install`'.7374## Related skills7576- `xcode-cloud-single-track-ci`: `ci_scripts/` activates tools through mise.77- `apple-public-repo-security`: gitleaks + lefthook installed through mise.