npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mihomo-cli

v4.14.0

Published

A terminal-based mihomo (Clash.Meta) client for macOS

Readme

mihomo-cli

一个基于命令行的 mihomo (Clash.Meta) 客户端,仅支持 macOS

服务托管依赖 launchd、目录/UI 打开依赖 open、提权依赖 sudo,均无其他平台实现,故在非 macOS 上会直接报错退出而非部分可用。Windows / Linux 适配尚无时间表。

功能特性

  • 🌐 订阅管理 - 添加/更新订阅,支持流量统计和到期时间显示
  • 🔄 自动更新 - 启动时自动检查并更新过期订阅
  • 🔍 模糊匹配 - sub use / update / remove 均支持订阅名称模糊匹配(大小写不敏感)
  • 📝 覆写配置 - 在订阅基础上进行自定义覆写,支持强制覆盖、数组合并、按 name 就地 patch、按订阅名通配限定作用域、单文件启停
  • 🔄 智能重启 - sub use 切换订阅、ow on/off 切换覆写后自动重启
  • 🚀 进程管理 - 启动/停止/切换模式,自动清理残留进程
  • 🛡️ 服务托管 - 基于 launchd,崩溃/登录自动拉起,代理后台常驻;日常 start/stop 全程免密
  • 🔄 双模式支持 - Mixed 模式和 TUN 透明代理模式
  • 📊 状态监控 - 查看运行状态、内存占用、订阅流量、到期时间与更新新鲜度(紧急度着色,--json 机器可读)
  • 🩺 体检诊断 - mihomo doctor 一键检查内核/服务/端口/订阅/配置/连通性/内核与 CLI 版本并给修复指引
  • 🔌 端口逃生口 - 默认 7890/9090 可经 settings.jsonports 覆盖,status 与 mihomo ui 会显示实际端口
  • 🔌 连通性探测 - 启动与状态展示独立确认「代理真的通」,不通时归因到订阅过期/流量用尽/节点失效
  • 🔎 查看生效配置 - mihomo config [--json] [--reveal] 展示由订阅与覆写推导出的运行配置,停止状态下同样可用;节点密码、UUID、provider 订阅 token 等凭据默认脱敏
  • 📝 日志管理 - 每次启动归档上一次日志,保留 7 天,支持列表/跟随/编号查看
  • 🎨 Web UI - 一键打开 Web 控制面板 (zash/metacubexd/yacd)
  • 🔄 内核更新 - 自动检查更新,支持 GitHub 镜像加速
  • 💡 容错提示 - 命令/子命令拼错时给出 did-you-mean 纠错建议
  • ⌨️ 命令别名 - mihomo / mhm / mh 均可调用

安装

方式一:npm 全局安装

npm install -g mihomo-cli

方式二:源码安装

git clone [email protected]:adaex/mihomo-cli.git
cd mihomo-cli
npm install
npm run build
npm link

快速开始

全新环境直接运行 mihomo(不带参数)会显示状态与「开始使用」引导:缺哪步列哪步。

1. 下载内核

# 自动选择通道:gh > 本机代理 > 直连
mihomo kernel

# 国内网络强制走镜像(裸 --mirror 固定走裸域 gh-proxy.org)
mihomo kernel --mirror

# 或用短别名指定镜像(纯 IPv6 网络用 v6)
mihomo kernel --mirror cdn
mihomo kernel --mirror v6

2. 添加订阅

mihomo sub add "https://your-subscription-url" "my-proxy"

# 或先在机场页面复制订阅链接,再运行(交互下自动读取剪贴板,确认后添加)
mihomo sub add

3. 安装服务

mihomo install

Mixed 模式由 launchd 服务托管(崩溃/登录自动拉起),只需装这一次。全程免密,详见「服务托管」。

4. 启动代理

# Mixed 模式(默认),同时开启登录自启
mihomo start

# 再次执行 start = 重启并应用新配置
mihomo start

# 停止并关闭登录自启
mihomo stop

# 临时 TUN 透明代理(不走服务,需管理员权限)
mihomo tun

5. 打开 Web UI

mihomo ui          # 默认 zash
mihomo ui dash     # metacubexd
mihomo ui yacd     # YACD

命令参考

核心命令

| 命令 | 说明 | | --------------------------- | ---------------------------------------------------------------------------- | | mihomo install | 安装服务(Mixed 模式的前置,只需一次;升级用户会顺带清理旧的 root 服务) | | mihomo start [tun\|mixed] | 启动代理并开启登录自启(-s 跳过订阅更新,-u 更新超时) | | mihomo stop | 停止代理并关闭登录自启 | | mihomo uninstall | 卸载服务 | | mihomo status | 查看运行状态(含订阅流量、到期、更新新鲜度;--json 机器可读,--no-probe 跳过连通性探测) | | mihomo logs | 列出所有日志(当前 + 历史归档) | | mihomo logs <编号> | 查看指定日志(0=当前,1+=归档,-f 实时跟随,-n N 行数,-o 打开) | | mihomo logs -f | 跟随当前日志(省略编号时默认当前,等价 logs 0 -f) |

订阅管理

| 命令 | 说明 | | ----------------------------- | -------------------------------------- | | mihomo sub | 列出所有订阅(含流量、到期时间) | | mihomo sub use <name> | 切换当前订阅(支持模糊匹配,自动重启;重启透传 -s/-u 等启动选项) | | mihomo sub add [url] [name] | 添加订阅并自动切换(名称不可重复;交互下不带 URL 时自动读剪贴板并确认) | | mihomo sub update | 更新所有订阅 | | mihomo sub update <name> | 更新指定订阅(支持模糊匹配) | | mihomo sub remove <name> | 删除订阅(别名 rm/delete;精确名直接删,模糊匹配需确认,-y 跳过) |

节点测速请用 mihomo ui 打开的 Web 面板(zash/metacubexd/yacd 均内置逐节点实时测延迟), 或直接在订阅里配置 url-test 分组由内核自动选路——两者都比一次性的命令行快照更实时。

覆写配置

| 命令 | 说明 | | ------------------------------ | -------------------------- | | mihomo ow | 查看覆写配置状态和文件列表(别名 enable/disable 亦可用于开关) | | mihomo ow on | 启用覆写配置(默认已启用,自动重启) | | mihomo ow off | 禁用覆写配置(自动重启) | | mihomo config [--json] [--reveal] | 查看当前生效的运行配置(由订阅与覆写推导,停止状态下同样可用;凭据默认脱敏,--reveal 显示原文) |

ow on/ow off全局总开关(一次开关所有覆写)。只想停用某一个文件,在该文件里写 enabled: false,见单个文件的开关

其他命令

| 命令 | 说明 | | --------------------------------- | ------------------------------------------------------------------- | | mihomo kernel [--mirror [镜像]] | 更新内核(自动选择通道:gh > 本机代理 > 直连;--mirror 强制镜像,--mirror direct 强制直连) | | mihomo update | 更新 mihomo-cli(先查 npm 最新版,已是最新则跳过重装) | | mihomo ui [zash\|dash\|yacd] [-c] | 打开 Web UI(-c 把控制器访问密钥复制到剪贴板;默认只提示、不动剪贴板) | | mihomo dir | 显示数据目录位置 | | mihomo dir open [target] | 打开指定目录(root, subs, logs, data, runtime, kernel) | | mihomo reset [目标...] [--full] [-y] | 重置用户数据(可用目标:subs, logs, data, runtime, settings, kernel, overwrites, service--full 删全部,-y 跳过确认) | | mihomo doctor | 体检诊断(内核/服务/端口/订阅/配置/连通性/CLI 版本,有异常退出码 1) | | mihomo version | 显示版本信息 | | mihomo help [命令] | 显示帮助(无参数显示全部;也可用 mihomo <命令> -h) |

命令别名

以下任意命令等效:

  • mihomo-cli (原名)
  • mihomo
  • mhm
  • mh

子命令组亦有别名:subscription = sub/subs/subscriptionsdirectory = dir/dirs/directoriesoverwrite = ow

快捷命令

常用操作的快捷方式:

| 快捷命令 | 等效于 | | ---------------------- | -------------------------- | | mihomo tun | mihomo start tun | | mihomo use <name> | mihomo subscription use <name> | | mihomo restart | mihomo start(start 本身即重启) |

模式说明

Mixed 模式(默认)

  • HTTP + SOCKS5 混合端口
  • 由 launchd 服务托管,崩溃/登录自动拉起
  • 需先 mihomo install(一次),之后 start/stop 全程免密
  • 需要手动配置应用代理

TUN 模式(透明代理)

  • 全局自动路由,所有流量自动走代理
  • 临时进程,不走 launchd(用完 mihomo stop 收掉)
  • 需要 sudo / 管理员权限
  • 首次使用会自动配置 DNS 和路由
  • 与服务互斥:服务运行时会被拦下,需先 mihomo stop

服务托管

Mixed 模式由 macOS 原生的 launchd 托管:内核崩溃、被系统 kill(如内存不足)、重新登录后都会自动拉起,无需手动 start

mihomo install         # 安装服务(只需一次,装完不启动)
mihomo start           # 启动 + 开启登录自启
mihomo stop            # 停止 + 关闭登录自启
mihomo uninstall       # 卸载服务
mihomo status          # 查看状态

以上全部免密。安装为用户级 LaunchAgent(~/Library/LaunchAgents/gui/<uid> 域),不需要 root,因此日常启停不会打断你去输密码。

语义

| 命令 | 做了什么 | 重新登录后 | | --- | --- | --- | | install | 写 plist,不启动 | 不启动 | | start | enable + bootstrap | 自动启动 | | stop | bootout + disable | 不启动 | | uninstall | 停止 + 删 plist | 不启动 |

stop 会一并关闭自启,这是它与「杀掉进程」的区别——只停不关的话,下次登录代理又自己回来了,而 CLI 已经告诉你「已停止」。

uninstall 只卸服务,订阅/内核/日志仍留在数据目录(重装后可继续用)。要彻底移除 mihomo-cli:mihomo reset --full 删全部数据,再 npm uninstall -g mihomo-cli——uninstall 结束时也会提示这两步。

顺序别反:先 npm uninstall -g 的话,LaunchAgent plist 会留下来,而能清理它的命令已经没了(plist 带 KeepAlive,仍会尝试拉起一个不存在的内核)。npm 卸载时会打印一条残留提醒(升级触发同一脚本,忽略即可),但最好仍按上面的顺序来。真反了也能救,手动执行:

launchctl bootout gui/$(id -u)/com.mihomo-cli.daemon 2>/dev/null
rm -f ~/Library/LaunchAgents/com.mihomo-cli.daemon.plist
rm -rf ~/.mihomo-cli                     # 数据目录
  • KeepAlive — 内核崩溃或被杀后由 launchd 自动拉起(约 10 秒节流后重启)
  • RunAtLoad — 登录后自动启动
  • 常驻的是系统 launchd 进程本身,不额外占用资源、无轮询
  • 切换订阅、开关覆写后的重启优先走内核热重载,免密且不中断连接
  • start 会确认内核真的跑起来了才报「已启动」:坏配置下内核启动即退出时报错并附日志尾部,而不是报成功后让 KeepAlive 静默地反复重试
  • 「系统设置 → 通用 → 登录项与扩展」中显示为 mihomo-cli-service(plist 指向一个同名符号链,否则那里只会显示一个没有上下文的 mihomo

关于 macOS 本地网络授权

服务以当前用户身份运行(不是 root)。macOS 15+ 对用户身份进程访问局域网其他设备有隐私限制: 首次连接时会弹出「允许访问本地网络」,点允许即可,之后永久生效,条目可在 「系统设置 → 隐私与安全性 → 本地网络」查看和开关。

大多数人碰不到这个127.0.0.1 / ::1 属于 loopback,不出网卡,不算本地网络。 自己运行 ssh -D 127.0.0.1:1080 并把节点指向它,不受本地网络授权影响 只有节点直接指向 192.168.x.x10.x.x.x*.local 这类地址时才会触发。

服务始终以当前用户运行,局域网节点按 macOS 的授权流程处理

/Library/LaunchDaemons 仍有旧 root 服务,它可能持续自启并抢占端口;install/uninstall/stop/tun 和需要停机的 reset 会检测并清理,删除 root 文件时需要一次管理员密码

若确实有局域网节点且始终不弹框、连不通,本地网络授权没有便捷的重置手段(它不在 TCC 数据库里, tccutil reset LocalNetwork 会直接失败),只能进恢复模式删 /Library/Preferences/com.apple.networkextension.*.plist, 且会清掉所有 App 的授权。遇到这种情况建议提 issue 说明场景。

另外,系统按代码签名与可执行文件 UUID 识别进程,而 mihomo 内核是 GitHub 下载的 Go 二进制(ad-hoc 签名), mihomo kernel 更新内核后可能需要重新授权一次

TUN 与服务共存

TUN 是临时模式,不走 launchd(本就需要 sudo,且用完即走)。两者会抢占同一组端口,因此服务运行时执行 mihomo tun 会被拦下:

mihomo stop      # 先停服务
mihomo tun       # 起临时 TUN(需 sudo)
mihomo stop      # 收掉 TUN
mihomo start     # 恢复服务

mihomo tun 会自动关掉服务的登录自启,并在启动时提示。原因是服务与 TUN 共用同一份运行时配置:TUN 一跑,那份配置就是 TUN 模式,而服务以普通用户身份运行、无权创建 TUN 设备。若自启还开着,用户不 stop 直接关机,下次开机 launchd 就会拿这份配置反复拉起一个必然失败的内核。

TUN 用完后 mihomo start 会按 Mixed 重建配置并恢复自启。

TUN 下 DNS 恒为开启。若订阅或覆写里写了 dns.enable: false,TUN 模式会强制改回 true 并显示「配置提示」——TUN 会劫持 53 端口流量(dns-hijack),内置 DNS 关着就没有任何组件接管,网络直接不可用。只锁 enable 这一个键,nameserverenhanced-mode 等仍按你的配置走。Mixed 模式不受影响,那里关 DNS 是合法配置。

不要用 sudo 运行

sudo mihomo … 会被直接拒绝。服务是用户级 LaunchAgent(域 gui/<uid>),以 root 运行时域变成 gui/0 —— 一个不存在的域,所有服务操作都会静默跳过却报成功。TUN 需要的 root 权限由 CLI 内部按需申请,无需在外层加 sudo

日志

每次 mihomo start 会把上一次的 mihomo.log 归档为 mihomo.<时间戳>.log,归档保留 7 天。运行期间日志持续追加到 mihomo.log;若单次运行就写超 10MB,配置变更触发的重启会顺便轮转,不会无限增长。

mihomo logs         # 列出当前日志与归档
mihomo logs 0 -f    # 实时跟随当前日志
mihomo logs 1       # 查看最新的归档

内核更新通道

mihomo kernel 按优先级自动选择下载通道,无需手动指定:

  1. gh:检测到 GitHub CLI(gh)时,经 gh release download 直连 GitHub
  2. 本机代理:mihomo 代理在跑时,经混合端口直连 GitHub(TLS 端到端)
  3. 直连:以上都不可用时

镜像不持久化——每次按当前环境独立决策,换网络不会用到上次的镜像。

版本查询(GitHub API)在代理开着时同样经本机代理;镜像绝不作用于 API—— 内核二进制在 TUN 模式下会以 root 运行,下载地址必须由 GitHub 官方 API 给出,不能让镜像自己指定。

手动覆盖:

mihomo kernel                # 自动选择通道
mihomo kernel --mirror       # 强制走镜像(裸域 gh-proxy.org;不探测网络,纯 IPv6 网络请显式 v6)
mihomo kernel --mirror v6    # 显式走 v6.gh-proxy.org
mihomo kernel --mirror cdn   # 短别名指定镜像(cdn/v4/v6/axisnow)
mihomo kernel --mirror hk.gh-proxy.org  # 任意镜像主机名或完整 URL
mihomo kernel --mirror direct  # 强制直连(绕过 gh/代理自动通道)

镜像经第三方中转,无法验证来源完整性;gh 与本机代理通道直连 GitHub,优先使用。

可用镜像:

| 镜像 | 短别名 | 说明 | | -------------------- | ------ | -------------------- | | gh-proxy.org | — | 裸 --mirror 的默认主机 | | v6.gh-proxy.org | v6 | 纯 IPv6 网络显式指定 | | v4.gh-proxy.org | v4 | 强制 IPv4 | | cdn.gh-proxy.org | cdn | CDN 节点 | | axisnow.gh-proxy.org | axisnow | |

订阅自动更新

  • 默认更新间隔:12 小时(订阅服务端可通过 profile-update-interval 覆盖)
  • 触发时机:start 命令(sub 列表只读)
  • 服务常驻期间不会自动更新:launchd 只负责拉起内核,不会跑 startstatus 会在订阅超过更新间隔时黄标提醒(已超过 N 小时间隔,建议 mihomo sub update),此时手动跑 mihomo sub updatemihomo start 即可
  • 更新失败时继续使用本地缓存,不影响使用
  • 自动更新默认超时 10 秒,可通过 -u <ms> 调整;使用 -s 可完全跳过自动更新

选项写法

带值选项支持三种等价写法,长短选项对应关系:

| 短 | 长 | 用途 | 默认 | | --- | --- | --- | --- | | -u | --update-timeout | 启动时自动更新订阅超时(ms) | 10000 | | -n | --lines | 日志显示行数 | 100 |

mihomo start -u 30000            # 短选项 + 空格
mihomo start --update-timeout 30000   # 长选项 + 空格
mihomo start --update-timeout=30000   # 长选项 + 等号

布尔开关:-s(跳过订阅更新)、--no-update-y/--yes(跳过确认)、-o(用系统默认程序打开)。

上述数值选项只接受 >= 1 的整数,非法值(0、负数、5sabc)会直接报错而非静默取默认值——避免静默产出看似成功的错误结果。

数据保护

  • 订阅内容校验:下载到的内容必须含 proxies / proxy-groups / proxy-providers 之一才写盘。机场返回配额或错误 JSON(如 {"error":"quota exceeded"})时报错并保留磁盘上原有的可用配置,不会被覆盖
  • sub add 失败回滚:下载失败时移除半成品订阅,且不改动当前活跃订阅
  • settings.json 损坏恢复:格式损坏(含合法 JSON 但非对象的情况)时自动备份为 .bak 并回退默认设置
  • 运行配置校验:启动或重载前,由已安装的 mihomo 内核执行 -t 校验;配置被拒绝时保留现有 config.yaml,不会自动删除错误节点、分组或规则
  • reset 停止确认:需要停止进程的重置会先确认进程已终止,失败则中止删除

mihomo reset 清订阅、日志和运行数据,保留内核、覆写文件、其他设置及服务安装;--full 额外删除这些内容并卸载服务。指定多个目标时顺序不影响结果,reset overwrites 恢复覆写默认开启状态

数据目录

用户数据存储位置(与安装位置分离,更新不丢失):

~/.mihomo-cli/
├── settings.json         # 用户设置(订阅列表、当前订阅、覆写开关、端口覆盖等)
├── settings.lock         # 设置读改写的跨进程锁
├── subscription-cache.lock  # 订阅缓存读改写的跨进程锁
├── service.lock          # 服务启停的跨进程锁
├── service-stop-epoch    # 并发启停的停止计数
├── overwrite.yaml        # 覆写配置(主文件,可选)
├── overwrite.*.yaml      # 覆写配置(扩展文件,如 overwrite.dns.yaml)
├── subscriptions/
│   ├── cache.json        # 订阅动态缓存(更新时间、流量、到期时间等)
│   └── <name>.yaml       # 订阅原始配置
├── kernel/
│   └── mihomo            # mihomo 内核二进制
├── logs/
│   ├── mihomo.log        # 当前日志
│   └── mihomo.YYYY-MM-DD_HH-MM-SS[.N].log  # 归档日志(同秒二次轮转加序号)
├── data/                 # mihomo 运行数据(GeoIP 等,由内核自行管理)
└── runtime/              # 运行时配置与临时文件
    ├── pid               # 进程 PID
    └── config.yaml       # 内核校验通过后的最终配置

可通过环境变量 MIHOMO_CLI_DIR 自定义数据目录位置。

覆写配置

覆写配置允许你在订阅配置基础上进行自定义修改,原始订阅文件保持独立

节点与分流规则按显式配置合并,最终交给 mihomo 校验。新增节点会按内核的 include-all / include-all-proxies 语义进入分组;需要排除时,在相应分组显式配置 exclude-filter

使用方法

  1. ~/.mihomo-cli/ 目录下创建覆写文件:
    • overwrite.yaml — 主覆写文件(只认 .yaml;写成 overwrite.yml 不会被加载,CLI 会打一行提示)
    • overwrite.dns.yaml — 按功能拆分的扩展文件(overwrite.*.yaml / overwrite.*.yml 格式)
  2. overwrite.yaml 始终最先加载,扩展文件按文件名排序加载
  3. 覆写默认即启用,放好文件后重启生效(mihomo start);如曾 ow off 禁用过,用 mihomo ow on 重新启用(会自动重启)

特殊语法

覆写配置支持以下特殊操作符,只在覆写文件的顶层生效

| 语法 | 作用 | 示例 | | -------- | ----------------------------------------- | -------------------- | | key! | 强制覆盖整个对象(不深度合并) | dns!: { ... } | | +key | 数组前置插入 | +proxies: [...] | | key+ | 数组追加 | rules+: [...] | | ~key | 按 name 就地合并数组元素,找不到则追加 | ~proxies: [...] | | ~?key | 按 name 就地合并,找不到则忽略(不新增) | ~?proxy-groups: [...] | | <+key> | 顶层键名以 +/~ 等符号开头时转义(仅顶层需要,见下文) | <+dns>: { ... } |

操作符可与转义组合(如 +<+dns> 前置到名为 +dns 的键、~<weird> 按 name 合并名为 weird 的数组)。

嵌套层(映射里的映射)的键一律按字面名合并+/~/! 在那里不是操作符——mihomo 原生配置的键名本来就可能带这些符号(如 nameserver-policyhosts 里的 +.域名 通配键),直接照写即可,不需要也不能用 <...> 转义:

dns:
  nameserver-policy:
    '+.corp.example.com': 'https://dns.corp.example.com/dns-query'
hosts:
  '+.google.cn': 8.8.8.8   # 嵌套层不需要转义;写成 <+.google.cn> 会连尖括号原样进配置、永不匹配

嵌套映射的普通键仍逐键深度合并;要改嵌套的数组(如 dns.nameserver)请写全量值(普通键整体替换)。嵌套层出现形似操作符的键名(如 ~xx+)时会提示一行「已按字面处理」——若那是 mihomo 原生键可忽略(+. 开头的通配域名不提示)。

~key~?key 都用于只修改数组里某一个元素的部分字段,而不动其余元素、也不必复制整个元素,以 name 为主键匹配。两者只在「找不到同名元素」时不同:

  • ~key 追加——补丁本身就是个完整元素时用它,比如下文 ssh 出口那节用 ~proxies 新增一个 socks5 节点。
  • ~?key 忽略——补丁只带 name 和一两个要改的字段时用它,表达「订阅下发了这个元素我才改它」。典型场景:同一机场的多条订阅套餐不同,Developer 分组只在其中一条里有;用 ~key 会把补丁追加成一个缺 type 的残缺分组,内核直接拒绝加载整份配置(ProxyGroup Developer: '' has unset fields: type),用 ~?key 则在没有该分组的订阅上自动跳过。被跳过时会打印一行提示,避免与「分组名拼错」混淆。

~key / ~?key / +key / key+ 都是数组语义:若目标键已存在且不是数组(如 ~dns 作用于映射、log-level+ 作用于字符串),会直接报错而非静默包成单元素数组——后者会丢掉原有字段并生成 mihomo 无法解析的配置。要覆盖非数组值请用 key!(强制覆盖)或直接写 key(深度合并)。

作用域限定(match)

在覆写文件顶部加 match: 块,可让该文件只对指定订阅生效(无 match 则全局生效)。所列条件需全部满足(AND),条件值为数组时其内部为 OR:

| 匹配键 | 作用 | | ------------- | ----------------------------- | | name | 按订阅名匹配,支持 * / ? 通配(大小写不敏感,与 sub use 口径一致) | | subscription | name 的同义写法,能力完全相同;两者不可同时出现 | | url-domain | 按订阅 URL 的 hostname 后缀匹配(大小写不敏感) |

订阅名支持 shell 风格通配,全串匹配

| 写法 | 命中 | 不命中 | | ---- | ---- | ------ | | edu* | edu1edu2edu-hk | mini1xedu1(不是半匹配) | | edu? | edu1edu2 | edu-hk? 只顶一个字符) | | edu1 | edu1 | edu10(不含通配符时就是精确匹配) |

只有 *? 是通配符,.+[ 等字符一律按字面处理(不是正则)。

* 开头的值必须加引号:YAML 里 * 开头是别名语法,name: *edu 会解析失败、整个文件被跳过(CLI 会提示加引号)。写成 name: "*edu" 即可。结尾的 *edu*)不受影响

match写错会直接报错(键名拼错、值为空、空块、namesubscription 同时出现),而不是静默忽略后对所有订阅生效——写了 match 显然是想限定作用域,悄悄放宽比报错危险得多。

url-domain 命中该域名下的所有订阅。同一机场的多条订阅(如 edu1mini1)URL 往往同域名,用 url-domain 会一并生效;要在同机场内按套餐区分,用 name 通配(如 name: edu*)。若只是担心某条订阅没有要改的分组,用 ~?key 就够了(它会自动跳过),不必为此改作用域;match 应当按「这份覆写在语义上属于哪些订阅」来写。

mihomo status 会按当前活跃订阅区分「生效」与「不适用」,括号里只列本次真正参与合并的文件:

覆写: 已启用 (seal,1 个不适用,1 个已禁用)
  glados 不适用于当前订阅 mini1(作用域 name=edu*)

「不适用」指文件本身是启用的,只是 match 没命中当前订阅——切到命中的订阅(sub use)或改 match 才会生效,与 enabled: false 的「已禁用」是两回事。mihomo ow 列表不做这个判断(它不绑定某条订阅),那里的作用域一栏只说明该文件管哪些订阅。--json 形态下 overwrite.applied 是生效清单(ow off 全局关闭时为空数组),overwrite.files 仍是「未被 enabled: false 停用」的全部文件;语法或元数据键写错的文件进 overwrite.errors(不混进 files/applied)。

坏文件不阻断诊断、但阻断启动:YAML 语法错误(含 enabled: no 这类元数据键错误)的文件在 mihomo owstatus 中以「加载失败」红字标出,诊断命令永远可用;但该文件不参与合并,mihomo start/doctor 会硬失败并给出原因——曾经语法错只警告一行就跳过、退出码 0,启动成功但覆写根本没生效。

单个文件的开关(enabled)

在覆写文件顶部写 enabled: false,可只停用这一个文件,其余覆写照常生效:

# ~/.mihomo-cli/overwrite.seal.yaml
enabled: false    # 暂时停用这份覆写,不用改名或删除

+proxies:
  - name: Seal-Host
    type: socks5
    server: 127.0.0.1
    port: 1080
  • 不写该键即启用;被停用的文件仍会出现在 mihomo ow 列表里并标注 [已禁用](改名成 .bak 则会从列表里消失,不知道自己还有这份配置)
  • mihomo ow off 是两层:后者是全局总开关,一次关掉所有覆写
  • 必须写 false,不能写 no / off:YAML 里这两个是字符串而非布尔值,CLI 会直接报错而不是按「真值」放行——否则你以为停用了、配置却照常生效
  • enabledmatch 同属元数据键,不会进入最终的 mihomo 运行配置;它们不接受操作符,也必须小写enabled!+matchEnabled 都会直接报错——那些写法既不停用文件,还会把键当普通配置写进运行配置,而内核对未知顶层键不报错、你不会收到任何提示)

示例

# ~/.mihomo-cli/overwrite.yaml

# 强制覆盖 dns 配置
dns!:
  enable: true
  enhanced-mode: fake-ip
  nameserver:
    - 223.5.5.5

# 将规则放到订阅规则之前,避免被已有 MATCH 提前匹配
+rules:
  - 'DOMAIN-SUFFIX,example.com,DIRECT'
# ~/.mihomo-cli/overwrite.glados.yaml
# 只对该机场 edu 系列的订阅生效:把订阅下发的 Developer 分组默认选中改为 TW Fixed IP
match:
  name: edu*                      # edu1、edu2 命中;同机场的 mini1 不命中
  url-domain: glados-config.com   # 与上一条同时满足才生效(AND)

# 用 ~? 而非 ~:该机场的精简套餐没有 Developer 分组,
# ~ 会把这段补丁追加成一个缺 type 的残缺分组、导致内核拒绝加载;
# ~? 在没有该分组的订阅上自动跳过(并打印一行提示)
~?proxy-groups:
  - name: Developer
    default-selected: TW Fixed IP

注:default-selected 由 mihomo 内核决定默认选中项,优先级低于 store-selected 缓存的历史选择。若之前手动选过、且开启了 store-selected,需 mihomo reset data 清缓存后才能看到默认值接管。

同时使用多个机场

本 CLI 是单活跃订阅模型(sub use 切换),不合并多条订阅。要把第二个机场的节点并进当前订阅,用覆写引入 mihomo 原生的 proxy-providers——节点池由内核按 interval 自动刷新,不受单订阅模型限制:

# ~/.mihomo-cli/overwrite.providers.yaml
proxy-providers:
  second-airport:
    type: http
    url: https://second-airport.example.com/api/v1/client/subscribe?token=xxx
    interval: 86400              # 节点池自动刷新间隔(秒)
    path: ./second-airport.yaml  # 缓存文件(mihomo 管理,相对 data 目录)
    health-check:
      enable: true
      url: https://www.gstatic.com/generate_204
      interval: 300

# 新增一个走第二机场的分组(+ 是数组前置插入,订阅分组不动)
+proxy-groups:
  - name: SecondAirport
    type: select
    use: [second-airport]

# 在订阅规则之前分流到该分组
+rules:
  - 'DOMAIN-SUFFIX,corp.example.com,SecondAirport'

provider 节点与订阅节点同池参与分组选择;节点延迟与手动切换在 Web UI(mihomo ui)里操作。若想让订阅里已有的某个分组也纳入第二机场的节点,用 ~?proxy-groups 按 name 就地 patch 该分组、加 use 字段(用 ~? 而非 ~:这是「改已有分组」,订阅里没有该分组时应跳过而不是新建一个残缺分组)

用 ssh -D 做节点

先运行 ssh -D 127.0.0.1:1080 -N host,再把本地端口作为 socks5 节点写进覆写:

# ~/.mihomo-cli/overwrite.ssh.yaml
~proxies:
  - {name: SSH-work, type: socks5, server: 127.0.0.1, port: 1080}
+rules:
  - DOMAIN-SUFFIX,example.internal,SSH-work

Web UI

内置三个常用 Web UI:

| 名称 | 地址 | 说明 | | ---- | ---------------------------------------- | -------------------- | | zash | https://board.zash.run.place | 现代简洁界面(默认) | | dash | https://metacubex.github.io/metacubexd | MetaCubeX 官方 UI | | yacd | https://yacd.metacubex.one | 经典 YACD 界面 |

故障排除

一键体检

mihomo doctor

逐项检查内核可执行性、数据目录可写、settings 有效性(含端口覆盖合法性)、订阅配置与新鲜度、服务状态、端口占用、 配置的内核原生校验、代理连通性、内核版本(落后时提示 mihomo kernel)、CLI 版本(落后时提示 mihomo update); 两个版本检查都访问网络,GitHub/npm 不可达则跳过、不算异常。每项给出 ✓/!/✗ 与修复命令; 存在异常项时退出码为 1(警告不影响退出码)。

启动失败

mihomo start 先用内核检查候选配置,错误会直接显示并保留现有运行配置。CLI 不再自动修复重名节点或失效引用,需要修改订阅或覆写后重试

内核只报「哪个键不合法」,说不出「这个键是覆写加进来的」,所以提示里会附上本次实际生效的覆写文件与作用域:

配置错误: 内核拒绝加载配置

  ProxyGroup Developer: '' has unset fields: type

  当前生效的覆写文件:
    overwrite.glados.yaml (url-domain=glados-config.com)
    overwrite.seal.yaml (全局)
  若报错的元素来自覆写追加(~key 未匹配到同名元素时会新增),改用 ~?key 可在缺少该元素的订阅上跳过。

  请修正订阅或覆写;当前运行时配置未改动。

清单已按 ow 开关、文件内 enabledmatch 过滤,即本次真正参与合并的文件;(全局) 表示该文件没有 match、对所有订阅生效,有 match 时按你写的键名回显(如 name=edu*)。没有覆写生效时不显示这一段(问题就在订阅本身)。mihomo doctor 给出同样的信息,mihomo ow 可看全部覆写文件(含被停用的)

校验通过后仍需确认内核已运行:端口占用、系统权限等启动问题会报错并附日志尾部,退出码非 0。异常退出原因与 status 使用同一口径(退出码 N被信号终止(Killed: 9)

mihomo logs 0        # 看完整原因
mihomo stop          # 止住 launchd 的反复重试

status 显示「不在运行」但带「内核上次异常退出」的提示,说明内核正在崩溃循环中被反复拉起,同样按上面两步处理。提示会区分两种死法:退出码 N(内核自己退的,多为配置问题)与 被信号终止(Killed: 9)(被外部杀掉,常见于系统内存不足时被 OOM killer 干掉)。

进程无法停止

sudo pkill -9 mihomo

TUN 模式无法启动

  1. 运行 mihomo tun,按提示提供管理员密码,无需在命令前加 sudo
  2. 检查是否有其他程序占用 53 端口
  3. 查看日志:mihomo logs 0 -f

订阅更新失败

  • 检查网络连接
  • 确认订阅 URL 有效且未过期
  • URL 中的 token 等敏感信息会自动脱敏

端口被占用

默认端口(CLI 强制,不受订阅/覆写影响):

  • 混合端口 (HTTP + SOCKS5): 7890
  • 外部控制器: 127.0.0.1:9090

与其他代理工具冲突或需要并存时,可在 settings.json 中覆盖端口(两键均可选,需为 1-65535 的整数且互不相同):

{
  "ports": { "mixed": 17890, "controller": 19090 }
}

改动后 mihomo start 重新生成配置即生效;Web UI 连接地址与系统代理里的端口请使用新值(mihomo status 会显示实际端口)

安全特性

  • URL 脱敏:订阅 URL 中的 token、key、password 等敏感参数(含 query、userinfo 及路径型令牌)自动替换为 ***。按整条 URL 处理、不按逗号切分——逗号在 query 中合法,切开会让 ?nodes=us,hk&token=xxx 的 token 参数识别不出而明文输出
  • 文件权限:配置文件使用 0o600 权限(仅所有者可读可写),目录使用 0o700 权限
  • 入站固定只监听回环allow-lan 由本工具恒定为 false订阅与覆写都改不了(自 v4.13.0;此前订阅里写 allow-lan: true 即可把混合端口开到全网卡)。确需局域网设备连入的场景请在本机另起一个 mihomo 实例,不通过订阅投递
  • 入站与控制面由本工具独占:订阅与覆写里的入站端口(mixed-port/port/socks-port/redir-port/tproxy-port)、独立入站服务端(tuic-server/ss-config/vmess-config)、通用入站声明(listeners/tunnels)、局域网暴露与入站鉴权(allow-lan/bind-address/authentication/skip-auth-prefixes/lan-allowed-ips/lan-disallowed-ips)、外部控制器全家桶(external-controller*external-doh-serversecretexternal-ui*)与控制器证书段(tls)一律剥除,不进运行配置。这些键要么自带监听地址、要么直接决定「监听在哪、要不要验身份」,远端订阅若能投递即可在全网卡开出无鉴权控制器或开放代理——allow-lan: true 让内核把端口绑到所有网卡,而 skip-auth-prefixes: ["0.0.0.0/0"] 会让唯一的补偿防线 authentication 整个失效;端口与密钥只认 settings.json。覆写文件里写了会有提示,订阅侧静默剥除。确需额外入站的场景请在本机另起一个 mihomo 实例,不通过订阅投递
  • 信号处理:优雅处理 SIGINT/SIGTERM 信号
  • 异常捕获:全局 uncaughtException 和 unhandledRejection 处理

注意:外部控制器(127.0.0.1:9090)默认无鉴权,与 Clash 系工具惯例一致。它仅监听本机回环、局域网不可达;但本机其他进程(含浏览器中的网页)可访问它,请勿在不可信的多用户环境使用。

多用户环境可在 settings.json 中设置 controller_secret(写入配置后随启动生效,ui 命令会提示密钥),为控制器 API 加上 Bearer 认证;密钥由系统锁定,订阅/覆写无法伪造。

许可证

MIT License - 详见 LICENSE 文件。

相关项目

免责声明

本工具仅供学习和研究使用。使用本工具时请遵守当地法律法规。