lov-clash-tun-doctor · diff
v0.6.1 to v0.6.2
30 added, 12 removed. Audit A to A.
---
name: lov-clash-tun-doctor
description: >
- Diagnose and repair application connectivity failures caused by Clash Verge
- Rev TUN routing, rule precedence, stale runtime state, proxy timeouts, or
- unusable IPv6 paths. Trigger for symptoms such as WeChat images failing to
- send, Moments images loading slowly, an app hanging after TUN is enabled, or
- requests unexpectedly matching DIRECT/proxy rules. Also trigger when the user
- mentions "Clash TUN 排障", "微信图片发不出去", "朋友圈图片加载慢",
- "修复微信 TUN 网络", or "diagnose Clash TUN app connectivity".
+ 诊断并可回滚地修复 Clash Verge Rev TUN 导致的应用联网故障:微信图片发不出、朋友圈加载慢、开 TUN 后卡住、规则误走 DIRECT/代理、代理超时、IPv6 失效。
+ Use when the user mentions "Clash TUN 排障", "微信图片发不出去", "diagnose Clash TUN app connectivity".
license: MIT
compatibility: >
Requires macOS with Clash Verge Rev (Mihomo core in sidecar or service mode)
and Python 3.8+ standard library. Other platforms need explicit --data-dir
and --socket values.
metadata:
author: contributors
- version: "0.6.1"
- tags: clash mihomo tun network diagnostics wechat macos
+ version: "0.6.2"
+ tags:
+ - clash
+ - mihomo
+ - tun
+ - network
+ - diagnostics
+ - wechat
+ - macos
---
# Clash 网络医生 · Clash Network Doctor
Evidence-first diagnosis and reversible repair for application networking
failures behind Clash Verge Rev TUN mode.
- ## When to Use
+ ## Triggers
+ ### Activate when
+
+ - “微信图片发不出去”“朋友圈图片加载慢”“修复微信 TUN 网络”“Clash TUN 排障”
+ - "Help me diagnose Clash TUN app connectivity: the app works without TUN but
+ hangs with it."
- An application works without TUN but fails, stalls, or loses media with TUN.
- WeChat text works while image uploads or Moments images fail.
- A rule change makes the symptom worse or the app remains stuck on Loading.
- The subscription says `ipv6: false`, but runtime traffic still uses IPv6.
- Clash logs contain `no route to host`, `context deadline exceeded`, or an
unexpected rule/strategy for the affected process.
- A blocked site such as `chatgpt.com` fails through one proxy node while other
sites work through the same node.
- Do not use this skill for generic subscription acquisition, node purchasing,
- or bypassing organizational network policy.
+ ### Do not activate when
+
+ - Generic subscription acquisition, node purchasing, or bypassing
+ organizational network policy.
+ - Chaining an IPRoyal static residential exit behind RayLink: use
+ `lov-iproyal-raylink`.
+ - A website URL blocked inside WeChat (a weixin110 appeal): that is a Tencent
+ policy decision, not TUN routing.
+
+ ## Skill Group Composition
+
+ Read `references/skill-composition.md` before routing to or extending an
+ adjacent Skill.
## Workflow (MANDATORY)
### Step 0: Resolve the skill and Clash data directories
Resolve `SKILL_DIR` from the installed skill context. For manual execution:
```bash
export SKILL_DIR="/path/to/lov-clash-tun-doctor"
```
The CLI resolves the Clash Verge Rev data directory in this order:
1. `--data-dir`
2. `SKILL_CLASH_TUN_DOCTOR_DATA_DIR`
3. macOS Clash Verge Rev default under `~/Library/Application Support/`
Never hard-code a user's home directory.
### Step 1: Diagnose before proposing a rule
Run the read-only command first:
```bash
python3 "$SKILL_DIR/scripts/clash_tun_doctor.py" diagnose --app wechat
```
Report concrete evidence from all available layers:
- App-level `config.yaml` overrides.
- Generated `clash-verge.yaml` top-level and DNS IPv6 values.
- Runtime `/configs`, `/rules`, and `/connections` through Mihomo's Unix socket.
- Recent core-log failures for the target application.
Core logs follow the running mode. In owner-scoped service mode (socket under
`clash-verge-service/users/<uid>/`) Mihomo writes to
`/Library/Application Support/clash-verge-service/users/<uid>/logs/service_latest.log`
(`/var/lib/clash-verge-service/...` on Linux), which is root-only; data-dir logs
then belong to an earlier mode and are ignored. Otherwise the newest of
`<data-dir>/logs/sidecar`, `<data-dir>/service-logs/service`, and
`<data-dir>/logs/service` is used. When no log is readable, diagnosis prints
`Recent logs: UNAVAILABLE` with every location and reason (JSON counts are
`null`); never read that as "no errors". Collect log evidence instead with:
```bash
python3 "$SKILL_DIR/scripts/clash_tun_doctor.py" diagnose --app wechat --live-logs 15
```
Reproduce the failure during the window: `--live-logs` samples Mihomo's live
`/logs` stream through the controller socket and needs no root.
The runtime socket is auto-detected in this order, and the first one whose
controller answers wins:
1. `--socket`, when given (no fallback).
2. `-ext-ctl-unix` of the running Mihomo core process.
3. `external-controller-unix` in the generated `clash-verge.yaml`.
4. Service mode: `/var/run/clash-verge-service/users/<uid>/verge-mihomo.sock`.
5. Sidecar default `/tmp/verge/verge-mihomo.sock`, then `<data-dir>/mihomo.sock`.
`diagnose` and `direct-list` exit non-zero and list every candidate with its
failure reason when none answers. Never report runtime IPv6, rules, or
connections as healthy without a reachable socket.
Treat screenshots and runtime state as truth. A rule saying `DIRECT` does not
prove the connection succeeded.
### Step 2: Choose the narrowest repair
Use `references/troubleshooting.md` to map evidence to a repair. For the proven
WeChat pattern, use the built-in repair:
```bash
python3 "$SKILL_DIR/scripts/clash_tun_doctor.py" fix-wechat
```
This is a dry run. It previews:
- Direct rules for the WeChat processes and media domains.
- Disabling the app-level IPv6 override that can supersede subscription and
extension settings.
- The exact files that would be backed up and changed.
Do not route the whole application through a proxy merely because direct media
failed. First check proxy health and IPv6 errors; a proxy timeout can turn one
failed image into a fully stuck application.
For a browser site or application with multiple dependency hosts, generate one
evidence-backed DIRECT list instead of adding domains one by one:
```bash
python3 "$SKILL_DIR/scripts/clash_tun_doctor.py" direct-list \
--app miracleplus \
--host apply.miracleplus.com \
--output ./miracleplus-direct.yaml
```
The command reads active connections and recent rotated service logs, deduplicates
hostnames, and includes only:
- Hosts explicitly supplied with `--host`.
- Hosts previously observed through a non-DIRECT route.
- Hosts already maintained as explicit DIRECT rules.
Hosts observed only through a healthy DIRECT route are reported as ignored
instead of bloating the explicit list.
### Step 3: Apply only with user authorization
For a DIRECT list, preview first, then persist and hot-load it:
```bash
python3 "$SKILL_DIR/scripts/clash_tun_doctor.py" direct-list \
--app miracleplus \
--host apply.miracleplus.com \
--apply
```
This path must merge with existing `prepend` rules, create a timestamped backup,
update the generated config, hot-load Mihomo through its Unix socket, and verify
the runtime. Keep Clash Verge running throughout this rule-only flow.
The hot-load is `PUT /configs?force=true` with a 60-second timeout:
- Owner-scoped service mode (socket under `clash-verge-service/users/<uid>/`)
sends the generated config as `payload`, with `external-controller-unix`
pinned to the live socket. Its core's home is the root-owned `runtime`
directory, so Mihomo refuses every user-writable config path with
`HTTP 400: path is not subpath of home directory or SAFE_PATHS`.
- Other modes load `clash-verge.yaml` by `path`; a path refused for
`SAFE_PATHS` is retried once as a payload.
- Never copy configs into the runtime directory, use `sudo`, or restart the
core to make a path reload work.
If Mihomo refuses or never answers the reload, the command restores the
original files, exits 2, and prints Mihomo's raw error in `reason` and
`reload_attempts[].error`. Quote that error instead of guessing a cause. After
`no HTTP response: timed out` the core may still finish loading the config, so
rerun `diagnose` to read the live rules before retrying.
After an accepted reload, the command re-detects the controller socket in the
Step 1 order, requires every listed host as an exact `DOMAIN -> DIRECT` rule in
`/rules`, and requires every user choice to survive: each Selector's proxy and
each pinned (`fixed` non-empty) URLTest/Fallback group. Unpinned URLTest and
Fallback groups re-pick on every reload and are not compared. Any failure sets
`ok: false` and lists the problem in `verification.issues`; the files stay
saved, so report the backup path and offer `rollback --apply` instead of
claiming success.
Connections opened before the reload keep their old chain until they close.
Judge the new rules only by connections that appear afterwards (`/connections`
ids absent before the reload), or restart the affected application first.
For the specialized WeChat IPv6 repair, run:
```bash
python3 "$SKILL_DIR/scripts/clash_tun_doctor.py" fix-wechat --apply
```
The command must:
1. Stop Clash Verge before editing its generated global settings.
2. Create a timestamped backup and manifest.
3. Set the global IPv6 override to `false`.
4. Prepend persistent WeChat `DIRECT` rules in the current profile's rule file.
5. Restart Clash Verge and verify final/runtime state.
If verification fails, report the backup path and do not claim success.
### Step 4: Restart the affected application and verify the user path
Close stale connections or restart the affected application. Re-run diagnosis:
```bash
python3 "$SKILL_DIR/scripts/clash_tun_doctor.py" diagnose --app wechat --json
```
For the WeChat IPv6 failure, success requires all of the following:
- Runtime `ipv6` is `false`.
- WeChat rules resolve to `DIRECT`.
- New WeChat destinations are IPv4.
- New logs no longer show WeChat `no route to host` errors.
- The user can send an image and load Moments images.
### Step 5: Roll back when needed
```bash
python3 "$SKILL_DIR/scripts/clash_tun_doctor.py" rollback --apply
```
Rollback restores the newest backup by default. Never delete backups
automatically.
## CLI Reference
| Command / option | Default | Description |
|---|---|---|
| `diagnose` | — | Read configuration, runtime state, connections, and logs. |
| `direct-list` | — | Discover, export, or apply an evidence-backed DIRECT host list. |
| `fix-wechat` | dry run | Preview or apply the proven WeChat repair. |
| `rollback` | dry run | Preview or restore the latest repair backup. |
| `--data-dir PATH` | auto | Clash Verge Rev application data directory. |
| `--socket PATH` | auto | Mihomo controller Unix socket; see the detection order in Step 1. |
| `--app NAME` | `wechat` | Application filter used by diagnosis. |
| `--host HOST` | — | Seed an exact host in a DIRECT list; repeatable. |
| `--output PATH` | — | Save a Mihomo classical rule-provider YAML list. |
| `--live-logs SECONDS` | off | Diagnose from Mihomo's live `/logs` stream instead of log files. |
| `--log-limit N` | `4000` | Recent lines inspected in each rotated core log. |
| `--apply` | false | Authorize filesystem changes and restart/restore actions. |
| `--no-reload` | false | Persist a DIRECT list without runtime hot-load. |
| `--no-restart` | false | Apply changes without restarting Clash Verge. |
| `--json` | false | Emit machine-readable diagnosis output. |
## Dependencies
Python 3.8+ standard library only.
## Runtime context (shared)
运行前读取本 Skill 包的 `skill.yaml`,由宿主提供 `skill-runtime/v1` 上下文。字段解析顺序为:当前请求、项目上下文、个人 Preferences、品牌 Profile、通用默认值。
- 只使用 Manifest 声明的字段;Profile 保存公开品牌事实,Preferences 保存个人工作偏好。
- `required: true` 字段缺失时,按 Manifest 的问题配置向用户提出一个聚焦问题;用户明确同意后再保存回答。
- 报错提供可复制的 `context_id`、字段路径与来源,诊断内容避开秘密、完整私人路径和原始配置。
## 通用反馈闭环
用户在 Skill 驱动任务中提出修改意见时,继续当前产物前必须执行:
1. 先判断意见是 `task-specific`(仅本次)还是 `reusable`(可跨任务复用)。
2. `task-specific` 只修改当前任务,不改 Skill。
3. `reusable` 先确定作用域:领域规则先更新对应 canonical Skill;适用于所有 Skill 的规则先更新共享规范。
4. 完成规则更新、版本、lint 与分发核验后,再把修改应用到当前任务。
5. `reusable` 修改会使此前的“确认”“继续”“发吧”失效;完成当前产物修改和回读后必须停下,等待用户下一步指示,不自动进入发布、提交或其他外部写入。