mise.lock 锁文件完全指南:锁定工具版本、校验和与可复现安装
【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise
mise.lock是 mise(dev tools、env vars、task runner)项目中用于锁定已解析工具版本与产物校验和的锁文件:mise.toml记录项目接受的版本请求,mise.lock记录这些请求最终解析到的具体版本,支持的后端还会记录产物的下载 URL、校验和与验证元数据。本文完整讲解锁文件的启用方式、TOML 文件格式、环境/全局/本地/Monorepo 锁文件、严格锁定模式、mise lock --bump自动依赖更新工作流、后端支持差异与安全模型,并给出可直接复制的命令与配置示例。
概述:为什么需要锁文件
锁文件把"例行安装"与"有意升级"分离开来。日常开发中执行mise install安装的永远是锁定的版本,而升级只发生在显式执行更新命令时:
mise lock # 解析已配置的工具但不安装 mise install # 安装锁文件中记录的具体版本 mise lock --bump node # 在 node 的配置请求范围内重新解析到最新版本提交更新前务必先审查锁文件的 diff。需要明确的是:锁定工具版本并不等于锁定应用依赖——mise.lock不锁定你的应用包(如 npm 依赖)、系统库,也不锁定外部安装器拉取的全部传递依赖。因此package-lock.json、uv.lock等生态锁文件仍需照常维护。
锁文件中存储的 URL 可以减少发布发现的 API 调用次数;但私有下载、未缓存的产物以及验证或策略检查仍可能需要网络访问与认证。相关细节见下文 后端支持 一节与 GitHub tokens。
启用锁文件
执行mise lock可以显式创建项目锁文件。若希望工具安装或升级时自动创建并维护锁文件,在mise.toml中配置:
[settings] lockfile = true如果想为所有项目设置个人默认值:
mise settings set lockfile=true从源码角度看,锁文件相关的设置行为在 src/config/settings.rs 中有清晰划分:lockfile_enabled()在lockfile未设置时默认返回true(即更新现有锁文件),而lockfile_creation_enabled()仅在lockfile == Some(true)时才为真(即自动创建新锁文件)。这正是文档中"未设置时,mise 会更新已有锁文件但不会自动创建新文件"的底层逻辑。
MISE_LOCKFILE=1环境变量保留"更新已有文件"这一兼容行为,它不等同于在 TOML 中显式配置lockfile = true。- 全局锁文件只能通过
mise lock --global创建。
工作原理
- 锁文件创建与更新:配置
lockfile = true后,运行mise install或mise use会以实际安装的精确版本创建或更新mise.lock;当lockfile未设置时,这些命令只更新已有锁文件而不创建新文件。 - 版本解析复用:mise 会复用与当前配置请求、后端和选项完全匹配的既有锁条目。
- 校验和验证:对支持的后端,mise 会存储并校验所下载工具的校验和。
mise lock不仅解析配置级工具,也解析各个任务(task)中声明的工具。它会读取任务定义(包括继承的模板和被 include 的任务文件),但不会运行任务本身、任务依赖、hooks 或工具安装器。这保证了任务专属工具可以在首次执行任务之前就被锁定。这些条目使用相同的[[tools.*]]格式,写入拥有该任务的配置对应的锁文件。对应实现可见 src/cli/lock.rs:该命令会加载config.tasks_with_context并把任务工具纳入待锁定集合。
文件格式
锁文件是 TOML 格式。下面是一个精简示例,展示了一个请求如何绑定到具体版本,以及单个平台上的产物元数据如何存储。请用mise lock生成项目实际需要的条目,不要直接复制本示例:
lockfile_version = 1 [[tools.node]] version = "26.8.1" backend = "core:node" specifiers = ["26.8.1"] [tools.node."platforms.macos-arm64"] checksum = "sha256:6e577fd0d9db776db82306629e441a9dace416702622aebdd171c9dfaa41f4d2" url = "https://nodejs.org/dist/v26.8.1/node-v26.8.1-darwin-arm64.tar.gz"格式版本与升级
- 新锁文件使用当前带版本号的格式。当前实现中
CURRENT_LOCKFILE_VERSION为1(见 src/lockfile.rs 中const CURRENT_LOCKFILE_VERSION: u32 = 1)。 - 无版本号的旧锁文件被视作版本 0,普通更新时保持该格式,以避免意外的锁文件漂移;读取到高于当前支持版本的锁文件会直接报错(源码中
bail!("unsupported lockfile version ..."))。 - 执行
mise lock --upgrade可有意升级旧格式锁文件。 - 版本 1 的关键改进:把每个原始工具请求(
specifiers)记录在其解析到的具体条目上,因此"1"与"1.0.0"这类重叠请求可以可靠地选择不同的锁定版本。源码中bind_request()会按(version, options)定位目标条目并把 specifier 绑定到其上。
平台信息(Platform Information)
平台条目以带引号的键写入,例如[tools.node."platforms.macos-arm64"]。平台标识通常是os-arch,其元数据可能包含:
checksum(可选):用于完整性验证的 SHA256 或 Blake3 哈希size(遗留字段):文件字节数;读取旧锁文件时接受,但当前写入器不再输出url(可选):产物下载 URLurl_api(可选):API 下载 URL,用于需要认证资产请求的源provenance与provenance_verified:可用的验证方式,以及验证是否成功signer与attested_by:Packslip 的身份承诺
工具条目字段(Tool Entry Fields)
每个工具条目([[tools.name]])可以包含:
version(必填):工具的精确版本backend(可选):安装工具所用的后端(如core:node、aqua:BurntSushi/ripgrep)specifiers(版本 1):解析到该版本及选项变体的原始请求options(可选):标识产物的后端特定选项(如{exe = "rg", matching = "musl"})platforms(可选):平台特定元数据(校验和、URL、大小)
当产物的身份不仅取决于平台键时,同一版本的工具可以拥有多条条目。例如 Swift 为每个 Linux 发行版发布不同的 tarball,因此其条目会记录各自描述的对象:
[[tools.swift]] version = "6.3.1" backend = "core:swift" options = { swift_platform = "ubuntu24.04" } [[tools.swift]] version = "6.3.1" backend = "core:swift" options = { swift_platform = "fedora39" }条目按 options精确匹配,因此某台机器只会针对自己发行版对应的条目做验证。可以通过swift.platform固定让所有 Linux 机器解析到同一产物,并提交该条目。若某平台没有对应产物(例如ubi9没有 arm64 构建),该平台会被报告为skipped而不是锁定。
平台键(Platform Keys)
平台键格式通常为os-arch,但可由后端自定义:
- 标准格式:
linux-x64、macos-arm64、windows-x64 - 后端特定:部分后端(如 Java)可能使用更具体的平台标识
- 工具特定:
ubi等后端可能在平台键中包含额外的工具特定信息
环境特定锁文件
使用 环境特定配置文件(例如mise.test.toml)时,每个环境拥有独立的锁文件:
| 配置文件 | 锁文件 |
|---|---|
mise.toml | mise.lock |
mise.test.toml | mise.test.lock |
mise.staging.toml | mise.staging.lock |
mise.local.toml | mise.local.lock |
mise.test.local.toml | mise.test.local.lock |
例如设置MISE_ENV=test时:
MISE_ENV=test mise lock # 同时创建 mise.lock 和 mise.test.lock来自mise.toml的工具写入mise.lock,来自mise.test.toml的工具写入mise.test.lock。
解析规则:当MISE_ENV=test时,mise 为mise.test.toml中定义的工具读取mise.test.lock,为mise.toml中的工具读取mise.lock。环境特定锁文件严格限定在其对应配置的范围内——只包含该配置定义的工具。
这种设计意味着:不设置MISE_ENV的 CI 环境只依赖mise.lock,因此mise.dev.lock中的开发工具版本升级不会使 CI 缓存失效。
mise.lock与mise.<env>.lock都应提交到版本控制;mise.local.lock与mise.<env>.local.lock则应与其对应配置文件一起加入.gitignore。环境文件的本地变体约定可参考 docs/configuration/environments.md。
全局锁文件
全局配置(~/.config/mise/config.toml)中声明的工具不会被普通的mise lock锁定——普通命令只针对当前活动的项目配置根。请使用mise lock --global:
mise lock --global # 更新全局(及系统)配置锁文件::: tip 当全局配置是指向 dotfiles 仓库的符号链接时也是如此,例如~/.config/mise/config.toml->~/dotfiles/mise.toml。mise 通过两条路径访问同一个文件并视为全局配置,因此在仓库内运行mise lock会提示"项目范围内未配置任何工具"。请改用mise lock --global;锁文件会写在符号链接目标旁边(~/dotfiles/mise.lock)。 :::
本地锁文件
mise.local.toml(通常已被 gitignore)中定义的工具使用独立的mise.local.lock文件,将本地工具配置与已提交的锁文件分离:
# mise.local.toml 的工具写入 mise.local.lock mise use --path mise.local.toml node@22 # 常规 mise.toml 工具写入 mise.lock mise use --path mise.toml node@20使用mise lock --local更新所有平台的本地锁文件:
mise lock --local # 更新 mise.local.lock mise lock --local node python # 更新 mise.local.lock 中的指定工具在 src/cli/lock.rs 中,--local与--global是互斥的目标选择参数,分别作用于本地配置与全局/系统配置的锁文件集合。
Monorepo
当monorepo_root = true时,mise 可以在 Monorepo 根目录使用单一锁文件。设置[monorepo] lockfile = true可启用根锁文件变体,如mise.lock、mise.ci.lock与mise.local.lock:
[monorepo] lockfile = true- 已有子项目锁文件会在下一次锁感知命令执行时迁移进根锁文件。
- 不设置该配置则保持各子项目独立锁文件,便于逐步推广。
- 使用
mise*.lock文件的 Monorepo 会在 mise2026.12.0开始收到警告,未设置默认值将在 mise2027.6.0切换到根锁文件。 - 旧版 mise 无法理解这种布局下的子项目工具归属,需要兼容混合版本的项目可以固定旧行为:
[monorepo] lockfile = false详见 Monorepo 任务。源码中migrate_monorepo_lockfiles与monorepo_lockfile_union(见 src/lockfile.rs 与 src/cli/lock.rs)负责子项目锁文件向根锁文件的合并与迁移,并保证 monorepo 场景下mise lock不会误把根配置自身的条目当作过期数据清理掉。
严格锁文件模式
locked设置在通过支持 URL 锁定的后端安装工具前,要求锁文件中存在当前平台的 URL。它能在安装阶段捕获缺失的产物解析,而不是静默解析;它不是离线模式,且部分后端豁免。
# 启用严格模式 mise settings set locked=true # 或通过环境变量 MISE_LOCKED=1 mise install默认情况下,调用级锁定模式作用于 project(项目)、user-global(用户全局)与 system(系统)配置。使用locked_scopes排除那些有意包含滚动版本或发行版托管工具的作用域:
# 位于 ~/.config/mise/config.toml 或 /etc/mise/config.toml [settings] locked = true locked_scopes = ["project"]- 合法作用域为
project、global、system(src/config/settings.rs 中对非法值会报错 "expected one of: project, global, system")。 - 显式工具参数与环境提供的工具版本仍然保持锁定,因为它们不属于某个配置作用域。
- 排除某作用域只是放宽该作用域的锁定模式;mise 在存在锁文件时仍会使用既有锁文件。
- 若全局工具需要锁定但锁文件中缺失,运行
mise lock -g生成全局锁文件。 locked_scopes仅限全局设置,项目配置无法削弱用户的锁定策略。
若只想对单一配置根声明的工具强制执行严格模式,使用tool_config.locked代替调用级设置:
[tool_config] locked = true [tools] node = "24"该策略属于所在配置根:mise.toml、mise.local.toml及共享该根的其他配置声明的工具,都必须存在于各自锁文件中。从全局或父配置根继承的工具保留自己的策略。即使某作用域被locked_scopes排除,配置根级策略仍然生效。
启用后,若某工具在锁文件中没有当前平台的 URL,mise install会失败。修复方式是先用mise lock填充 URL:
mise lock # 刷新已有平台,或为新文件生成默认平台集 mise lock --platform linux-x64,macos-arm64 # 或指定平台该检查只覆盖能记录 URL 的后端。asdf、cargo、gem、go、npm、pipx、ubi、core:dotnet、core:rust、core:swift通过外部工具安装或在安装时解析下载,vfox 的backend插件尚无法上报 URL,因此严格模式会跳过它们而不是失败——混合使用这些工具与可锁定工具的项目仍能安装。vfox 的tool插件能记录 URL,会像其他可锁定后端一样被检查。由 tool stub 解析的工具同样跳过。各后端记录内容的明细见下文 后端支持。
严格模式建议在 CI 中使用,以捕获受支持后端的锁条目缺失。注意验证与认证下载仍可能发起 API 请求。
工作流
初始设置
# 生成锁文件 mise lock # 使用锁定版本安装工具 mise install日常使用
# 从锁文件安装精确版本 mise install # 更新工具与锁文件 mise upgrade更新版本
# 更新 mise.toml 中的工具版本 mise use node@26 # 这会同时更新安装与 mise.lock推进锁定版本(Bump Locked Versions)
mise lock --bump会针对模糊版本选择器(如latest、lts或"22"这类前缀)重新解析到最新匹配版本并更新锁文件——不安装任何东西,也不修改mise.toml。精确固定的版本保持不变(改写mise.toml中的固定版本请使用mise upgrade --bump):
# mise.toml 中 node = "22" 锁定在 22.14.0;此后发布了 22.15.0 mise lock --bump # 锁文件现在固定 22.15.0,mise.toml 仍写着 "22" mise lock --bump node # 只推进 node mise lock --bump --dry-run # 只展示将发生的变更,不写入该能力专为自动化依赖更新设计:在 CI 上定时运行,锁文件变化时打开 PR。--json以机器可读格式输出变更(并抑制人类可读输出)。只有版本级变更会被报告——版本未变时的校验和/URL 刷新不会产生条目——且版本列表保持配置/锁文件顺序而非排序。从配置中移除的工具会以空的new_versions报告:
mise lock --bump --dry-run --json[ { "name": "node", "backend": "core:node", "lockfile": "~/src/myproj/mise.lock", "old_versions": ["22.14.0"], "new_versions": ["22.15.0"] } ]--json输出结构对应源码 src/cli/lock.rs 中的LockChange序列化结构(name、backend、lockfile、old_versions、new_versions),其compute_version_changes仅在新旧版本集合不同时才生成变更条目,并刻意不做版本排序。
::: tip 在安全模式下运行 bump 自动化 当任务针对你无法控制的配置运行时——最常见的是机器人程序在 PR 分支上 bumpmise.lock——设置MISE_SAFE=1以防止项目配置执行代码。安全模式会拒绝模板exec()、_.source脚本、hooks、tasks、asdf 插件脚本与插件安装,而--bump基于 HTTP 后端的版本解析仍正常工作:
MISE_SAFE=1 mise lock --bump --json:::
固定锁定版本(Pinning a Locked Version)
可以在保持mise.toml中模糊选择器不变的同时,在锁文件里固定某个具体版本:
# mise.toml 中是 node = "latest" 或 node = "22" mise upgrade node@22.15.0 # 安装 22.15.0 并更新 mise.lock mise lock node@22.15.0 # 不重装,仅更新 mise.lock若指定版本与当前配置前缀不匹配,配置会被自动更新。例如mise.toml中为node = "20",执行mise upgrade node@22.15.0后,配置会被更新为node = "22"(保持同样的精度级别),锁文件设置为22.15.0。该行为对应源码中compute_config_bumps_for_paths与apply_config_bumps的实现——--bump模式下明确跳过配置改写("Never under --bump, which is documented to leave config files untouched")。
各命令与锁文件的交互
下表展示每个命令如何与mise.toml和mise.lock交互:
| 命令 | 安装 | 更新mise.toml | 更新mise.lock |
|---|---|---|---|
mise use node@22 | 是 | 是(设置node = "22") | 是 |
mise install | 是 | 否 | 是 |
mise install node | 是 | 否 | 是(安装 node 的配置版本) |
mise install node@22.15.0 | 是 | 否 | 否(一次性安装,非配置驱动) |
mise upgrade | 是 | 否 | 是 |
mise upgrade node | 是 | 否 | 是(在范围内升级 node) |
mise upgrade node@22.15.0 | 是 | 仅当版本不匹配前缀时 | 是 |
mise upgrade --bump | 是 | 是(前缀推进以匹配) | 是 |
mise lock | 否 | 否 | 是(为所有工具重新生成) |
mise lock --bump | 否 | 否 | 是(选择器重新解析到最新) |
mise lock node@22.15.0 | 否 | 仅当版本不匹配前缀时 | 是 |
要点:
mise use改变所选配置文件(通常是mise.toml)中请求的版本mise install安装配置中的内容而不修改它——mise install node安装配置版本的 node 并更新锁文件,而mise install node@22.15.0是一次性安装,不更新锁文件mise upgrade在配置范围内升级工具并更新锁文件——传tool@version可指定具体版本mise lock不安装,只重新生成锁条目——传tool@version可固定具体版本,--bump把模糊选择器推进到最新匹配版本
后端支持
请检查生成的实际条目确认当前工具与平台。支持程度因后端、工具选项以及发布物是预编译产物还是源码构建而异:
| 后端家族 | 可预期的内容 |
|---|---|
| 下载型后端,如 aqua、GitHub/GitLab/Forgejo、HTTP 与 S3 | 源提供或 mise 可计算的平台产物元数据 |
| Packslip | 签名产物信息与签名者承诺;策略在安装时检查 |
| 内置语言 | 工具特定支持;Node、Python、Ruby 有产物解析路径,外部安装器则有不同限制 |
| 语言包安装器 | 顶层工具版本不会锁定所有传递包或构建输入 |
| vfox tool 插件 | 插件 hook 提供的下载 URL 可参与严格 URL 锁定 |
| asdf 与 vfox backend 插件 | 无严格 URL 锁定要求;插件执行仍决定安装方式 |
provenance字段与经过密码学验证的 provenance 结果是两种不同状态。在把锁文件元数据当作验证证据前,请先阅读 来源与安全。
最佳实践
版本控制
更改请求时,将项目配置与锁文件一起提交:
git add mise.toml mise.lock git commit -m "chore: update development tools"环境锁文件与其共享配置一同提交。.local变体不进入版本控制。审查变更时,除版本号外还要关注产物 URL、后端 options 与验证元数据。
团队工作流
- 用
mise use更改请求,或用mise lock --bump <tool>推进既有请求。 - 运行
mise install与项目相关检查。 - 提交审查过的配置与锁文件变更。
- 拉取代码后,团队成员运行
mise install安装记录中的版本。
任何更新项目的人都可以遵循此流程;锁文件变更不需要单独的团队角色。
CI/CD
检出仓库并安装 mise 后:
- name: Install locked tools run: mise install env: MISE_LOCKED: "1"提交锁文件前,先为 runner 的平台准备条目。若使用jdx/mise-action,它也提供工具安装与缓存;请把锁文件保留在该 action 使用的 checkout 中。缓存能加速安装,但不能替代锁文件或其检查。
故障排查
重新生成校验和
校验和不匹配意味着下载的字节与记录的产物不一致。先核对错误与锁文件中的工具、平台、URL 与后端 options。可能的原因:厂商替换了资源、镜像提供了不同内容,或条目描述的是另一个构建。
确认为有意的上游变更后,只刷新受影响工具的元数据并审查 diff:
mise lock node git diff -- mise.lock把node替换为受影响工具。不要删除校验和或卸载所有工具来绕过失败。如果新产物出乎意料,请保留现有锁文件,在接受新字节前调查发布源。
Ruby 预编译构建修订版发布
预编译 Ruby 二进制可能对同一 Ruby 版本存在构建修订版发布。锁文件保持version = "3.3.11",但在平台url中固定所选构建修订:
url = "https://github.com/jdx/ruby/releases/download/3.3.11-1/ruby-3.3.11.x86_64_linux.tar.gz"这里3.3.11-1表示构建修订1。关于修订存在的原因、未锁定安装的行为以及如何更新旧锁文件,参见 Ruby 预编译构建修订。
锁文件冲突
合并不同锁文件的分支时:
- 先在配置中解决预期的版本请求。
- 解决锁文件冲突,同时保留相应的请求绑定与平台条目。运行
mise lock刷新元数据并检查其 diff。 - 运行
mise install与相关项目检查,然后提交结果。
为特定项目禁用
# 位于项目的 mise.toml [settings] lockfile = false从其他工具迁移
从 asdf 迁移
预览导入现有版本文件,然后生成配置:
mise generate config --tool-versions .tool-versions --dry-run mise generate config --tool-versions .tool-versions --yes mise lock mise install在没有现有mise.toml的项目中使用此流程,或把预览审查合并进现有文件。若团队成员仍在使用 asdf,请保持共享的.tool-versions一致;参见 asdf 迁移。
从 package.json engines 迁移
engines.node通常描述的是兼容范围(如>=22),而不是精确版本请求。为项目选择一个受支持的 Node.js 版本并显式锁定:
mise use node@24 mise lock node启用 惯用版本文件 后,mise 会在自动项目发现中读取受支持的devEngines字段。不要把任意 npm 范围语法直接传给mise use。
来源与安全
对受支持的后端,mise lock会记录可用的 provenance 元数据,例如 SLSA、Cosign、Minisign 或 GitHub attestations。Aqua 与 GitHub 可以在锁定期间下载并密码学验证当前平台的产物。成功的检查会以provenance_verified单独记录。跨平台元数据可能描述了一种可用的验证方式,但并未在本地验证过。源码中 src/lockfile.rs 的ProvenanceType枚举定义了 Minisign、Cosign、SLSA(可携带.intoto.jsonl的 URL)与 GitHub Attestations 四种机制及其优先级顺序(低到高:Minisign < Cosign < SLSA < GithubAttestations),验证时按优先级尝试。
安装期间,校验和加已记录的已验证 provenance 结果可以让 mise 跳过重复的 provenance 检查。因此锁文件是信任输入:审查它,并从可信的项目来源获取。产物校验和验证始终生效。仅有 provenance 字段并不证明字节被验证过。
如果 GitHub Artifact Attestations 已启用,但 GitHub API 确认某个校验和后端产物不存在任何 attestation,mise 可能记录github_attestations = "unavailable"。这是一个否定缓存条目,不是 provenance:它只在后续从该锁文件安装时跳过冗余的 GitHub attestation 探测。SLSA、Cosign、Minisign 与校验和验证等其他验证路径照常运行。
GitHub 的文档展示了用actions/attest从已有产物路径生成二进制 attestation,REST API 按 subject digest 列出 attestations。这意味着 attestation 可能出现在 release 资源上传之后。之后的mise lock运行或MISE_LOCKED_VERIFY_PROVENANCE=1 mise install可以发现锁文件记录为 unavailable 之后新增的 attestation。
需要更高安全性时,可以强制每次安装都重新验证 provenance:
[settings] locked_verify_provenance = true或通过环境变量:
MISE_LOCKED_VERIFY_PROVENANCE=1 mise install这在 paranoid 模式下也会自动启用:
[settings] paranoid = true启用后,对正在安装的产物会重新运行受支持的验证路径,而不是信任之前锁文件中的验证结果。这不会为从未发布过 provenance 的 release 创造 provenance;已安装的工具可能不会被重新下载。它与 Packslip 签名者及签名列表策略相互独立。相关实现中,设置locked_verify_provenance与paranoid的合并逻辑见 src/config/settings.rs(self.locked_verify_provenance || self.paranoid)。
最小发布年龄(Minimum Release Age)
除锁文件外,mise 使用minimum_release_age设置限制供应链风险——只安装已发布满一定时长的版本。默认值为24h:
[settings] minimum_release_age = "7d" # 覆盖默认的 24h 延迟这与锁文件配合良好——用minimum_release_age避免选中刚发布的新版本,用锁文件固定经过你验证的精确版本。
- 该设置过滤顶层模糊版本解析(针对提供发布时间的后端)。
- 无时间戳的版本默认包含在内。
- 目前只有
npm:与pipx:会把同一截止时间转发到传递依赖解析。其他后端可能选择较旧的顶层工具版本,但不会约束工具安装器/编译器拉取的依赖。 mise lock还提供--minimum-release-age命令行参数(别名--before),支持绝对日期(如"2024-06-01")与相对时长(如"90d"或"1y"),只影响"20"或"latest"这类模糊匹配;精确固定的版本不受过滤,既有匹配的锁条目会被保留。
参见
- 配置设置 —— 全部可用设置
- 工具版本管理 —— 工具版本的工作方式
- 后端 —— 后端特定的校验和支持
- GitHub tokens —— 私有下载与认证
- Monorepo 任务 —— Monorepo 锁文件细节
- 安全模式 —— bump 自动化中的
MISE_SAFE=1 - paranoid 模式 —— 强制 provenance 重新验证
【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考