devAlice
← Mac

Mac 语言工具链 — 用一个 mise 替代 nvm + pyenv + rbenv + goenv

用单一工具替代 nvm、pyenv、rustup-light、goenv 和 rbenv。项目级自动切换、Shell 集成与迁移路径。

第一年你为 Node 安装了 nvm,第二年加了 pyenv,第三年又叠上了 rustup、goenv 和 rbenv,.zshrc 已膨胀了 30 行。各个 Shell hook 相互争抢,在新机器上重现配置变成了一件苦差事。

我认为版本管理工具的问题不在于各个工具本身的质量,而在于多工具叠加后的摩擦。以前每种语言各用一个管理器;如今用 mise 统一管理,因为单一工具带来的一致性比多工具各自优化更有价值。

mise(前身为 rtx)将这一切整合为单一二进制文件。兼容 asdf,用 Rust 编写,快且轻巧。本指南以 mise 为核心,涵盖 Node、Python、Rust、Go、Ruby 的统一工作流。

TL;DR

  1. 一个 mise 替代所有语言版本管理器
  2. .mise.toml(或 .tool-versions)中锁定每个项目的版本
  3. cd 自动切换 — 无需手动执行 use
  4. 一条 mise install 即可在新机器上恢复所有语言/版本
  5. 卸载 nvm/pyenv/rbenv — 重叠有害

前提条件

  • macOS 12+ 并已安装 Homebrew(Mac 初始配置
  • (可选)现有 nvm/pyenv 状态 — 参见迁移章节

1. 为什么选 mise

可替代的工具

  • Node.js(nvm、n、fnm、volta)
  • Python(pyenv)
  • Rust(部分 — 正式 Rust 开发建议保留 rustup,见第 10 节)
  • Go(goenv)
  • Ruby(rbenv、rvm)
  • Java(jenv)
  • 其他 — Elixir、Erlang、Lua、Bun、Deno、Terraform、kubectl……

优势

  • 快速 — 单一 Rust 二进制;支持无 shim 的纯 PATH 模式
  • 兼容 asdf.tool-versions 文件开箱即用
  • 自动切换 — 仅需 cd 即可切换版本,无需 use
  • 全局 vs 项目mise use --global vs mise use

劣势

  • 部分 rustup 功能缺失 — 工具链 channel(stable/nightly/beta)和组件(clippy、rustfmt、rust-analyzer)在 rustup 中更顺畅。如果只锁定单一 Rust 版本,mise 完全够用。
  • 非官方语言工具 — 偶有边缘情况(如 Python 的 python-build 选项)。

2. 安装

brew install mise

Shell 集成(追加到 .zshrc):

eval "$(mise activate zsh)"

打开新终端,用 mise --version 确认。

bash:mise activate bash。fish:mise activate fish

3. 初次使用 — 安装 Node

# 浏览可用版本
mise ls-remote node
 
# 全局安装
mise use --global node@22
 
# …或 LTS
mise use --global node@lts

验证:

node --version    # v22.x
which node        # ~/.local/share/mise/installs/node/22/bin/node

4. 锁定每个项目的版本

在项目文件夹中:

cd ~/work/my-app
mise use node@20.18.0    # 该项目锁定 Node 20.18.0

这会创建 .mise.toml

[tools]
node = "20.18.0"

或 asdf 兼容格式(.tool-versions):

node 20.18.0
python 3.12.7

.mise.toml 优先级更高。迁移现有项目或需要 asdf 兼容时使用 .tool-versions

自动切换

cd 即可让 mise 读取 .mise.toml 并切换版本。node --version 立即反映。

5. 多语言项目

cd ~/work/fullstack
mise use node@22
mise use python@3.12
mise use go@1.23

.mise.toml

[tools]
node = "22"
python = "3.12"
go = "1.23"

mise install — 一次性安装所有缺失版本。

6. 全局 vs 本地

mise use --global node@22     # ~/.config/mise/config.toml
mise use node@20              # 当前目录的 .mise.toml

优先级(从高到低):

  1. 环境变量 MISE_NODE_VERSION
  2. 从当前目录向上查找的 .mise.toml / .tool-versions
  3. 全局 ~/.config/mise/config.toml
  4. 系统 PATH 默认值

7. 日常命令

# 所有已安装版本
mise ls
 
# 某工具的可用远端版本
mise ls-remote python
 
# 安装锁文件中声明的所有内容
mise install
 
# 升级单个工具
mise upgrade node
 
# 卸载某版本
mise uninstall node@18
 
# 查看环境
mise env
 
# 一次性执行
mise exec -- node --version
mise x -- npm test

8. .envrc / direnv 集成

mise 0.30+ 支持在 .mise.toml 中声明环境变量:

[tools]
node = "22"
 
[env]
DATABASE_URL = "postgresql://localhost/myapp"
NODE_ENV = "development"

不再需要单独配置 direnv — mise 在 cd 时自动导出环境变量。

9. 从 nvm/pyenv 迁移

nvm → mise

# 当前用的哪个 Node?
nvm current
# v20.18.0
 
# 在 mise 中安装相同版本
mise use --global node@20.18.0
 
# 删除 nvm
brew uninstall nvm
# 或
rm -rf ~/.nvm
 
# 删除 .zshrc 中的 nvm hook 行

pyenv → mise

pyenv versions
# 确认当前使用的版本
 
mise use --global python@3.12.7
 
# 删除 pyenv
brew uninstall pyenv pyenv-virtualenv
rm -rf ~/.pyenv
 
# 清理 .zshrc

asdf → mise

# 现有 .tool-versions 直接可用
brew uninstall asdf
brew install mise
 
# 将 .zshrc 中的 asdf 行替换为 mise activate 行

对大多数插件,mise 与 asdf 插件兼容。通过 mise plugins ls-remote 查看。

10. Rust — mise vs rustup

Rust 的工具链概念(stable、nightly)和组件(clippy、rustfmt、rust-analyzer)很强大,rustup 处理得更好。仅当锁定单一版本时才用 mise 管理 Rust。

建议:

  • 正式 Rust 开发:保留 rustup,其他语言用 mise。
  • 偶尔用 Rust:mise 锁定一个 stable 版本即可。

保留 rustup 的方法:

brew install rustup-init
rustup-init -y
# .zshrc 自动激活 rustup 环境

验证

  1. mise --version — 安装成功
  2. cd ~/work/proj-a && node --version → 项目 A 锁定的版本
  3. cd ~/work/proj-b && node --version → 项目 B 的版本(自动切换)
  4. mise install — 安装 .mise.toml 中声明的所有内容
  5. 新机器:brew install mise && mise install → 完整恢复

故障排除

command not found: node

  • .zshrc 中缺少 eval "$(mise activate zsh)"
  • 打开新终端,或执行 . ~/.zshrc

自动切换不生效

  • .mise.toml.tool-versions 应位于项目根目录
  • mise current 显示当前激活的版本
  • 首次进入新目录时会出现信任提示:执行一次 mise trust

pip install 权限错误

mise 的 Python 是用户本地安装。不要与系统 Python 混用。推荐使用 venv:

python -m venv .venv
source .venv/bin/activate
pip install ...

Node 原生模块构建失败

  • mise 的 Node 使用预构建包 — 运行 npm rebuild 或显式调用 node-gyp
  • macOS 需要 Xcode CLT:xcode-select --install

asdf 社区插件缺失

少数 asdf 社区插件(asdf-foo)不在 mise 核心列表中。手动添加:mise plugins install foo https://github.com/...

构建不可复现

.mise.toml 中锁定精确版本(node = "20.18.0",而非 "20")。这相当于团队协作的锁文件。

参考资料

更新日志

  • 2026-05-12 — 初始英文翻译(devAlice M3 i18n 种子)