mihomo-cli 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +16 -10
- package/dist/index.js +824 -604
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.2.0] - 2026-07-19
|
|
4
|
+
|
|
5
|
+
### 修复
|
|
6
|
+
|
|
7
|
+
- **测速隔离实例被主进程管理误杀/误判** - `getMihomoPids`(原 `getAllMihomoPids`)此前用 `pgrep -f <内核路径>` 匹配,会连带命中 `sub test`/`sub clean` 启动的、跑同一内核但 `-f` 指向 `test/runtime/config.yaml` 的隔离实例。导致主实例运行时另开终端测速,`stop`/`start` 会误杀测速实例、或把它误判为残留而拒绝启动。改用「内核路径 + 主 configFile」双段正则精确匹配主实例(三种启动方式命令行均含这两段),隔离实例与仅用编辑器打开配置的进程都不再命中
|
|
8
|
+
- **未捕获异常时测速实例泄漏** - `uncaughtException` / `unhandledRejection` / `main().catch` 退出前未执行清理,测速期间崩溃会残留端口 27890 的实例。现三处退出前均调用 `runCleanup()`(此前仅 SIGINT/SIGTERM 有)
|
|
9
|
+
- **TUN 启动脚本路径未安全转义** - 生成的 sudo bash 脚本用双引号直接拼接内核/配置路径,`MIHOMO_CLI_DIR` 含 `"`/`$`/反引号时存在本地注入面。改用单引号字面量转义(`shellQuote`,与 daemon 脚本同一范式)
|
|
10
|
+
- **带 `no-resolve` 的规则在启动时被误删** - `validateConfig` 校验规则时取逗号分隔的末段当目标,`IP-CIDR,1.1.1.1/32,DIRECT,no-resolve` 这类带 `no-resolve` 修饰后缀的规则,其末段是修饰词而非目标,会被当作"引用不存在目标"静默移除(机场订阅中很常见)。现提取 `getRuleTarget()`:末段为 `no-resolve` 时取倒数第二段;`clean` 的规则清理同步改用
|
|
11
|
+
- **`clean` 误删带 `include-all`/`use` 的分组** - `cleanDeadProxies` 只按 `proxies` 清空判定删组,未像 `validateConfig` 那样检查其他节点来源;`{include-all: true, proxies: []}` 这类分组(或引用节点恰好全死但有 `include-all` 兜底)会被从订阅文件里持久删除。补上一致的 `hasOtherSource` 检查
|
|
12
|
+
- **Mixed 模式未清理订阅残留的 `tun` 字段** - 订阅/覆写自带 `tun.enable: true` 时,`start`(Mixed)会以 TUN 静默启动,保活(限定 Mixed)也可能带 tun 配置被 launchd 拉起。现 Mixed 模式显式丢弃订阅侧的 tun 字段(TUN 模式仍由系统 `TUN_CONFIG` 强制覆盖)
|
|
13
|
+
- **`sub add` 同名订阅被静默覆盖** - 两次不带名称的 `sub add` 会让第二个直接替换 `default`,原订阅 URL 无提示丢失。现同名即报错,提示换名或先删除
|
|
14
|
+
- **内核下载可能选中 compatible 版**(Intel Mac)- `-compatible` 变体同样满足"版本号尾缀"判定且字母序靠前,会被优先当作标准版下载(性能低于标准版)。现显式排除,仅在无标准版时回退
|
|
15
|
+
- **订阅名路径穿越**(低危)- 原始配置路径直接拼接订阅名,手改 `settings.json` 塞入 `../` 可让读/写/删越出 subscriptions 目录。现统一校验名称合法性;`sub remove` 对非法名跳过文件清理、仍可正常从列表移除
|
|
16
|
+
|
|
17
|
+
### 变更
|
|
18
|
+
|
|
19
|
+
- **新增 `runtime.ts` 运行时门面** - 收敛「普通进程(pidFile) vs 保活(launchd 托管)」双轨差异:运行模式判定、运行状态/PID、启停重启统一为三个函数。命令层(`start`/`status`/`sub use`/`ow`/`clean`)不再各自 `if (isDaemonEnabled())` 分支,消除重复与不一致(此前 `clean` 两分支输出已分叉)
|
|
20
|
+
- **命令路由改为注册表驱动** - 新增 `commands/registry.ts`,以数据表描述命令的名称/别名/handler/argv 改写;`index.ts` 从表分发(消除 ~110 行手写 switch,模块加载时校验别名无冲突)。帮助文本的命令清单由各命令的 `usage` 生成(单一真相源),修复此前手写 `help` 与实际命令脱节的问题,并补上「快捷命令」映射说明
|
|
21
|
+
- **保活模式日志不再无限增长** - daemon 常驻时不经 `process.start`,日志轮转/归档清理从不触发。现 `restartDaemon` 检测日志超 10MB 时跳过热重载、改走 sudo kickstart 路径顺便 copy-truncate 轮转(daemon 日志为 root 属主,用户态无法 truncate;运行中 rename 会让 launchd 的日志 fd 继续写进归档文件,只能 copy-truncate),并顺带清理 7 天前归档
|
|
22
|
+
- **`sub update` 后提示重启生效** - 运行中的实例仍使用旧配置,更新完成后提示执行 `mihomo start`
|
|
23
|
+
- **`kernel` 命令输出精简** - 不再每次打印整段镜像用法;仅直连失败时才提示 `--mirror`/`--mirror-all` 与可用镜像列表
|
|
24
|
+
|
|
25
|
+
### 内部
|
|
26
|
+
|
|
27
|
+
- 提取共用工具消除重复:`escapeRegExp`、`shellQuote`(utils)、`dumpYaml`(config,合并 4 处相同 YAML 序列化选项)
|
|
28
|
+
- `external-controller` 地址统一为常量 `CONTROLLER_ADDR`(constants),供配置生成、测速探测、热重载共用;删除 daemon 中因地址恒定而永不触发的运行时端口解析
|
|
29
|
+
- `HttpClient.get<T>()` 泛型化,json 模式直接返回目标类型,去掉调用点的 `as unknown as` 强转
|
|
30
|
+
- 覆写文件名判定提取为 `isOverwriteFilename`(overwrite),reset 复用
|
|
31
|
+
- 归档日志时间戳从 UTC 改为本地时间(与 `logs` 列表展示的 mtime 时区一致),提取 `formatLocalTimestamp`(utils)
|
|
32
|
+
- 常量收敛:`CONTROLLER_BASE_URL` 入 constants(daemon 热重载与测速探测共用,删除重复的地址构造);`DAEMON_BOOT_WAIT_MS` 合并两处重复的 launchd 等待定义;`cleanupOldLogs` 导出供 daemon 复用
|
|
33
|
+
- 文档同步:CLAUDE.md 架构表补上 `lifecycle.ts`;`allow-lan` 强制 false 标注为有意安全默认(防覆写误开入站代理);README 安全章节说明 controller 仅监听回环、无鉴权的适用边界
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## [3.1.0] - 2026-07-19
|
|
38
|
+
|
|
39
|
+
### 修复
|
|
40
|
+
|
|
41
|
+
- **保活模式下经局域网跳板的代理连不通**(v3.0.0 引入的严重 bug)- 用户级 LaunchAgent 启动的内核受 macOS 15+ 本地网络隐私(TCC)限制,访问**局域网其他设备**被静默拦截(报 `no route to host`),导致经局域网 socks5 跳板转发的内网流量在 `daemon on` 后全部失效、`daemon off` 后立刻恢复。手动在系统设置授权对裸命令行二进制无效。改为 **root 级 LaunchDaemon** 彻底解决(系统上下文不受该限制)
|
|
42
|
+
|
|
43
|
+
### 变更
|
|
44
|
+
|
|
45
|
+
- **保活迁移到系统级 LaunchDaemon** - plist 位于 `/Library/LaunchDaemons/`(`root:wheel`),以 root 运行;`daemon on` / `daemon off` 需输入一次管理员密码(复用 TUN 模式的交互式 sudo 范式,一次密码完成全部操作)
|
|
46
|
+
- **配置变更优先热重载(免密)** - `sub use` / `ow on|off` / `clean` 等触发的重启优先经 external-controller `PUT /configs` 热重载(走 localhost、无需 sudo),失败才回退到需密码的 `launchctl kickstart`
|
|
47
|
+
- **`daemon status` / `status` 免密** - 保活状态查询改用 `pgrep` + root 属主过滤判定运行状态,不再调用需 sudo 的 `launchctl print`
|
|
48
|
+
- **关闭保活时归还文件属主** - `daemon off` 会把 root 守护进程创建的日志、数据文件 `chown` 回当前用户,避免后续非保活模式 `start` 因 root 属主日志无法写入而失败
|
|
49
|
+
- `daemon on/off` 在非交互终端(无 TTY,如 CI)会明确报错而非挂起
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
3
53
|
## [3.0.0] - 2026-07-19
|
|
4
54
|
|
|
5
55
|
### 新增
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
- 📝 **覆写配置** - 在订阅基础上进行自定义覆写,支持强制覆盖、数组合并
|
|
12
12
|
- 🔄 **智能重启** - `sub use` 切换订阅、`ow on/off` 切换覆写后自动重启
|
|
13
13
|
- 🚀 **进程管理** - 启动/停止/切换模式,自动清理残留进程
|
|
14
|
-
- 🛡️ **进程保活** - 基于 launchd
|
|
14
|
+
- 🛡️ **进程保活** - 基于 launchd(root),崩溃/开机自动拉起,代理后台常驻(`daemon on`)
|
|
15
15
|
- 🔄 **双模式支持** - Mixed 模式和 TUN 透明代理模式
|
|
16
16
|
- 📊 **状态监控** - 查看运行状态、内存占用
|
|
17
17
|
- 📝 **日志管理** - 实时日志 + 历史日志归档(自动轮转,保留7天)
|
|
@@ -97,7 +97,7 @@ mihomo ui yacd # YACD
|
|
|
97
97
|
| ----------------------------- | -------------------------------------- |
|
|
98
98
|
| `mihomo sub` | 列出所有订阅(含流量、到期时间) |
|
|
99
99
|
| `mihomo sub use <name>` | 切换当前订阅(支持模糊匹配,自动重启) |
|
|
100
|
-
| `mihomo sub add <url> [name]` | 添加订阅并自动切换(支持逗号分隔多 URL
|
|
100
|
+
| `mihomo sub add <url> [name]` | 添加订阅并自动切换(支持逗号分隔多 URL 合并,名称不可重复) |
|
|
101
101
|
| `mihomo sub update` | 更新所有订阅 |
|
|
102
102
|
| `mihomo sub update <name>` | 更新指定订阅(支持模糊匹配) |
|
|
103
103
|
| `mihomo sub remove <name>` | 删除订阅(支持模糊匹配) |
|
|
@@ -120,7 +120,7 @@ mihomo ui yacd # YACD
|
|
|
120
120
|
| 命令 | 说明 |
|
|
121
121
|
| --------------------------------- | ------------------------------------------------------------------- |
|
|
122
122
|
| `mihomo kernel [--mirror [镜像]]` | 更新内核(默认直连,`--mirror` 使用镜像) |
|
|
123
|
-
| `mihomo daemon [on\|off\|status]` | 进程保活:开机自启 + 崩溃自动重启(仅 Mixed
|
|
123
|
+
| `mihomo daemon [on\|off\|status]` | 进程保活:开机自启 + 崩溃自动重启(仅 Mixed 模式,on/off 需管理员密码) |
|
|
124
124
|
| `mihomo update` | 更新 mihomo-cli (npm install -g) |
|
|
125
125
|
| `mihomo ui [zash\|dash\|yacd]` | 打开 Web UI |
|
|
126
126
|
| `mihomo dir` | 显示数据目录位置 |
|
|
@@ -150,6 +150,7 @@ mihomo ui yacd # YACD
|
|
|
150
150
|
| `mihomo use <name>` | `mihomo sub use <name>` |
|
|
151
151
|
| `mihomo on` / `off` | `mihomo ow on` / `ow off` |
|
|
152
152
|
| `mihomo open <target>` | `mihomo dir open <target>` |
|
|
153
|
+
| `mihomo upd` / `upgrade` | `mihomo update` |
|
|
153
154
|
|
|
154
155
|
## 模式说明
|
|
155
156
|
|
|
@@ -170,24 +171,26 @@ mihomo ui yacd # YACD
|
|
|
170
171
|
默认情况下,mihomo 内核在后台独立运行,但如果内核崩溃、被系统 kill(如内存不足)、或重启/重新登录后,代理就会失效且不会自动恢复。进程保活用 macOS 原生的 **launchd** 解决这个问题。
|
|
171
172
|
|
|
172
173
|
```bash
|
|
173
|
-
mihomo daemon on #
|
|
174
|
-
mihomo daemon off #
|
|
175
|
-
mihomo daemon status #
|
|
174
|
+
mihomo daemon on # 开启保活(需管理员密码)
|
|
175
|
+
mihomo daemon off # 关闭保活并停止代理(需管理员密码)
|
|
176
|
+
mihomo daemon status # 查看保活状态(无需密码)
|
|
176
177
|
```
|
|
177
178
|
|
|
178
179
|
### 原理
|
|
179
180
|
|
|
180
|
-
-
|
|
181
|
+
- 基于系统级 **LaunchDaemon**(`/Library/LaunchDaemons/`,以 root 运行),`daemon on/off` 需输入一次管理员密码
|
|
181
182
|
- **`KeepAlive`** - 内核崩溃或被杀后由 launchd 自动拉起(约 10 秒节流后重启)
|
|
182
|
-
- **`RunAtLoad`** -
|
|
183
|
+
- **`RunAtLoad`** - 开机后自动启动,无需手动 `start`
|
|
183
184
|
- 常驻的是系统 launchd 进程本身,**不额外占用系统资源、无轮询**
|
|
184
185
|
|
|
186
|
+
> **为什么用 root 级 LaunchDaemon**:早期版本用用户级 LaunchAgent(免密),但 macOS 15+ 的本地网络隐私限制会静默拦截其对**局域网其他设备**的访问(经局域网跳板的代理会连不通,报 `no route to host`)。系统级 root 守护进程不受此限制,是唯一可靠方案。
|
|
187
|
+
|
|
185
188
|
### 注意事项
|
|
186
189
|
|
|
187
190
|
- **仅支持 Mixed 模式**。保活开启时执行 `start tun` 会被拦截,需先 `daemon off`
|
|
188
191
|
- 保活开启后,`mihomo stop` 不再直接停止(会被自动拉起),请用 `mihomo daemon off`
|
|
189
|
-
-
|
|
190
|
-
- 保活模式下日志持续追加到 `mihomo.log
|
|
192
|
+
- 切换订阅、覆写开关、清理节点后的重启**优先走内核热重载(免密)**,失败才回退到需密码的 `launchctl kickstart`
|
|
193
|
+
- 保活模式下日志持续追加到 `mihomo.log`;超过 10MB 时,下次配置变更触发的重启会走 kickstart(需密码)并顺便轮转归档,不再无限增长
|
|
191
194
|
|
|
192
195
|
## 内核更新镜像
|
|
193
196
|
|
|
@@ -330,9 +333,12 @@ sudo pkill -9 mihomo
|
|
|
330
333
|
|
|
331
334
|
- **URL 脱敏**:订阅 URL 中的 token、key、password 等敏感参数自动替换为 `***`
|
|
332
335
|
- **文件权限**:配置文件使用 `0o600` 权限(仅所有者可读可写),目录使用 `0o700` 权限
|
|
336
|
+
- **入站锁定**:`allow-lan` 强制为 `false`,局域网设备无法连入代理端口(不可通过覆写开启)
|
|
333
337
|
- **信号处理**:优雅处理 SIGINT/SIGTERM 信号
|
|
334
338
|
- **异常捕获**:全局 uncaughtException 和 unhandledRejection 处理
|
|
335
339
|
|
|
340
|
+
> **注意**:外部控制器(`127.0.0.1:9090`)无鉴权,与 Clash 系工具惯例一致。它仅监听本机回环、局域网不可达;但本机其他进程(含浏览器中的网页)可访问它,请勿在不可信的多用户环境使用。
|
|
341
|
+
|
|
336
342
|
## 许可证
|
|
337
343
|
|
|
338
344
|
MIT License - 详见 [LICENSE](LICENSE) 文件。
|