Skill: gyaoshi/clash-verge-controller (version 1.0.0)

--- name: clash-verge-controller description: | Clash Verge 外部控制（RESTful API）技能。基于 mihomo 内核，提供完整的 API 调用指南、配置说明和代码示例。 当用户提到以下场景时触发： - Clash Verge 外部控制、RESTful API、远程管理 - 通过 API 切换节点、查看连接、管理规则 - clash-verge、clash.meta、mihomo 控制器配置 - 获取代理信息、测试延迟、重启内核等操作 --- # Clash Verge 外部控制 ##必要信息 开始前需要获取用户的clash verge外部监听地址和密钥，并确认clash verge外部监听已打开。 ## 核心原理 Clash Verge 内置 **mihomo (Clash.Meta)** 内核，通过 RESTful API 实现外部控制，支持切换节点、管理规则、监控连接等操作。 ## 配置文件设置 在 Clash 配置文件中添加： ```yaml # 外部控制 (API) 配置 external-controller: 127.0.0.1:9090 # API 访问密钥（强烈建议设置） [REDACTED_SECRET]" # CORS 跨域配置 external-controller-cors: allow-origins: - '*' allow-private-network: true ``` **配置说明：** | 配置项 | 说明 | |--------|------| | `external-controller` | API 监听地址，`127.0.0.1` 仅本地，`0.0.0.0` 允许外部访问 | | `secret` | API 密钥，开启后请求需携带 `Authorization: Bearer ${secret}` | ## 常用 API 接口 **基础调用格式：** ```bash # 无密钥 curl http://127.0.0.1:9090/{endpoint} # 有密钥 curl -H "Authorization: Bearer ${secret}" http://127.0.0.1:9090/{endpoint} ``` ### 代理操作 | 操作 | 方法 | 端点 | 说明 | |------|------|------|------| | 获取代理列表 | GET | `/proxies` | 查看所有代理和策略组 | | 切换节点 | PUT | `/proxies/{name}` | `{"name": "香港节点"}` | | 测试延迟 | GET | `/proxies/{name}/delay?url=https://www.google.com&timeout=5000` | 返回延迟(ms) | ### 策略组操作 | 操作 | 方法 | 端点 | 说明 | |------|------|------|------| | 获取策略组 | GET | `/group` | 列出所有策略组 | | 获取指定组 | GET | `/group/{name}` | 查看特定策略组详情 | | 清除自动选择 | DELETE | `/group/{name}` | 清除 auto 组 fixed 选择 | ### 配置操作 | 操作 | 方法 | 端点 | 说明 | |------|------|------|------| | 获取配置 | GET | `/configs` | 查看当前配置 | | 更新配置 | PATCH | `/configs` | `{"mixed-port": 7890}` | | 重启内核 | POST | `/restart` | 重载配置 | | 更新 GEO | POST | `/configs/geo` | `{"path": "", "payload": ""}` | ### 监控操作 | 操作 | 方法 | 端点 | 说明 | |------|------|------|------| | 实时日志 | WS | `/logs?level=info` | WebSocket 获取日志 | | 流量信息 | WS | `/traffic` | 实时流量(kbps) | | 连接列表 | GET | `/connections` | 查看所有连接 | | 关闭连接 | DELETE | `/connections` | 关闭所有连接 | | DNS 查询 | GET | `/dns/query?name=example.com&type=A` | 查询 DNS 记录 | ## 完整 API 参考 详细 API 文档（包含所有端点、参数、返回值）见： [references/api_reference.md](references/api_reference.md) ## 代码示例 ### Python ```python import requests API = "http://127.0.0.1:9090" [REDACTED_SECRET]" headers = {"Authorization": f"Bearer {SECRET}"} # 获取代理列表 proxies = requests.get(f"{API}/proxies", headers=headers).json() # 切换节点 requests.put( f"{API}/proxies/Proxy", headers=headers, json={"name": "香港节点-01"} ) # 测试延迟 result = requests.get( f"{API}/proxies/香港节点/delay", params={"url": "https://www.google.com", "timeout": 5000} ).json() print(f"延迟: {result.get('delay')}ms") ``` ### Node.js ```javascript const axios = require('axios'); const API = 'http://127.0.0.1:9090'; const [REDACTED_SECRET]'; const headers = { Authorization: `Bearer ${SECRET}` }; // 获取代理列表 const { data } = await axios.get(`${API}/proxies`, { headers }); // 切换节点 await axios.put( `${API}/proxies/Proxy`, { name: '香港节点-01' }, { headers } ); ``` ## 安全建议 1. **使用密钥**：生产环境务必设置 `secret` 2. **限制监听**：仅本地用 `127.0.0.1`，需要远程访问再改 `0.0.0.0` 3. **配合防火墙**：开启外部访问时限制 IP 4. **使用 HTTPS**：敏感网络配置 TLS ## 官方文档 - Clash Verge Rev: https://github.com/clash-verge-rev/clash-verge-rev - mihomo API 文档: https://wiki.metacubex.one/api/

path: references/api_reference.md
content: # Clash Verge / mihomo API 参考

完整的 RESTful API 文档，基于 mihomo (Clash.Meta) 内核。

## 认证

所有需要认证的请求携带以下请求头：

```
Authorization: Bearer ${secret}
```

`${secret}` 为配置文件中设置的密钥。

---

## 请求示例

```bash
curl -H 'Authorization: Bearer ${secret}' \
     http://127.0.0.1:9090/configs?force=true \
     -d '{"path": "", "payload": ""}' -X PUT
```

---

## 日志

### GET /logs

获取实时日志（HTTP 轮询或 WebSocket）

**参数：**
- `?level=info|warning|error|debug` - 日志级别过滤

**WebSocket：**
```bash
ws://127.0.0.1:9090/logs?level=info
```

---

## 流量信息

### GET /traffic

获取实时流量（WebSocket）

**返回：** 流量单位为 kbps

```bash
ws://127.0.0.1:9090/traffic
```

---

## 内存信息

### GET /memory

获取实时内存占用

**返回：** 内存单位为 kb

```bash
curl http://127.0.0.1:9090/memory
```

---

## 版本信息

### GET /version

获取 mihomo 版本信息

```bash
curl http://127.0.0.1:9090/version
```

---

## 缓存

### POST /cache/fakeip/flush

清除 FakeIP 缓存

```bash
curl -X POST http://127.0.0.1:9090/cache/fakeip/flush \
  -H "Authorization: Bearer ${secret}"
```

### POST /cache/dns/flush

清除 DNS 缓存

```bash
curl -X POST http://127.0.0.1:9090/cache/dns/flush \
  -H "Authorization: Bearer ${secret}"
```

---

## 运行配置

### GET /configs

获取基本配置

```bash
curl http://127.0.0.1:9090/configs
```

### PUT /configs

重新加载基本配置

**参数：**
- `?force=true` - 强制重新加载

```bash
curl -X PUT "http://127.0.0.1:9090/configs?force=true" \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"path": "", "payload": ""}'
```

### PATCH /configs

更新基本配置（部分更新）

```bash
curl -X PATCH http://127.0.0.1:9090/configs \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"mixed-port": 7890}'
```

### POST /configs/geo

更新 GEO 数据库

```bash
curl -X POST http://127.0.0.1:9090/configs/geo \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"path": "", "payload": ""}'
```

---

## 内核管理

### POST /restart

重启内核

```bash
curl -X POST http://127.0.0.1:9090/restart \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"path": "", "payload": ""}'
```

### POST /upgrade

更新内核

```bash
curl -X POST http://127.0.0.1:9090/upgrade \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"path": "", "payload": ""}'
```

### POST /upgrade/ui

更新用户界面

```bash
curl -X POST http://127.0.0.1:9090/upgrade/ui \
  -H "Authorization: Bearer ${secret}"
```

### POST /upgrade/geo

更新 GEO 数据库

```bash
curl -X POST http://127.0.0.1:9090/upgrade/geo \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"path": "", "payload": ""}'
```

---

## 策略组

### GET /group

获取所有策略组信息

```bash
curl http://127.0.0.1:9090/group
```

### GET /group/{group_name}

获取指定策略组信息

```bash
curl http://127.0.0.1:9090/group/Proxy
```

### DELETE /group/{group_name}

清除自动策略组的 fixed 选择

```bash
curl -X DELETE http://127.0.0.1:9090/group/Auto%20Group \
  -H "Authorization: Bearer ${secret}"
```

### GET /group/{group_name}/delay

对策略组内节点进行延迟测试

**参数：**
- `?url=xxx` - 测试 URL
- `?timeout=5000` - 超时时间(毫秒)

```bash
curl "http://127.0.0.1:9090/group/Proxy/delay?url=https://www.google.com&timeout=5000"
```

---

## 代理

### GET /proxies

获取所有代理信息

```bash
curl http://127.0.0.1:9090/proxies
```

### GET /proxies/{name}

获取指定代理信息

```bash
curl http://127.0.0.1:9090/proxies/%E9%A6%96%E6%B8%B8%E8%8A%82%E7%82%B9
```

### PUT /proxies/{name}

选择代理

```bash
curl -X PUT http://127.0.0.1:9090/proxies/Proxy \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"name": "香港节点"}'
```

### GET /proxies/{name}/delay

测试代理延迟

```bash
curl "http://127.0.0.1:9090/proxies/%E9%A6%96%E6%B8%B8/delay?url=https://www.google.com&timeout=5000"
```

---

## 代理集合

### GET /providers/proxies

获取所有代理集合信息

```bash
curl http://127.0.0.1:9090/providers/proxies
```

### GET /providers/proxies/{name}

获取指定代理集合信息

```bash
curl http://127.0.0.1:9090/providers/proxies/provider-name
```

### PUT /providers/proxies/{name}

更新代理集合

```bash
curl -X PUT http://127.0.0.1:9090/providers/proxies/provider-name \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"path": "", "payload": ""}'
```

### GET /providers/proxies/{name}/healthcheck

触发代理集合健康检查

```bash
curl http://127.0.0.1:9090/providers/proxies/provider-name/healthcheck
```

### GET /providers/proxies/{name}/{proxy}/healthcheck

测试代理集合内指定代理延迟

```bash
curl "http://127.0.0.1:9090/providers/proxies/provider-name/proxy-name/healthcheck?url=https://www.google.com&timeout=5000"
```

---

## 规则

### GET /rules

获取所有规则信息

```bash
curl http://127.0.0.1:9090/rules
```

### PATCH /rules/disable

禁用/启用规则

**请求数据：**
```json
{"0": false, "1": true}
```
key 为规则索引，value 为是否禁用（临时操作，重启后失效）

```bash
curl -X PATCH http://127.0.0.1:9090/rules/disable \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"0": false, "1": true}'
```

---

## 规则集合

### GET /providers/rules

获取所有规则集合信息

```bash
curl http://127.0.0.1:9090/providers/rules
```

### PUT /providers/rules/{name}

更新规则集合

```bash
curl -X PUT http://127.0.0.1:9090/providers/rules/ruleset-name \
  -H "Authorization: Bearer ${secret}" \
  -H "Content-Type: application/json" \
  -d '{"path": "", "payload": ""}'
```

---

## 连接

### GET /connections

获取连接信息

**参数：**
- `?interval=1000` - 刷新间隔(毫秒)

**WebSocket：**
```bash
ws://127.0.0.1:9090/connections?interval=1000
```

```bash
curl "http://127.0.0.1:9090/connections?interval=1000"
```

### DELETE /connections

关闭所有连接

```bash
curl -X DELETE http://127.0.0.1:9090/connections \
  -H "Authorization: Bearer ${secret}"
```

### DELETE /connections/{id}

关闭指定连接

```bash
curl -X DELETE http://127.0.0.1:9090/connections/conn-id \
  -H "Authorization: Bearer ${secret}"
```

---

## DNS 查询

### GET /dns/query

查询指定域名的 DNS 数据

**参数：**
- `?name=example.com` - 查询的域名
- `?type=A|AAAA|CNAME|MX|...` - 记录类型

```bash
curl "http://127.0.0.1:9090/dns/query?name=example.com&type=A"
```

---

## DEBUG 接口

> ⚠️ 需要内核启动时日志级别为 debug

### PUT /debug/gc

主动触发垃圾回收

```bash
curl -X PUT http://127.0.0.1:9090/debug/gc \
  -H "Authorization: Bearer ${secret}"
```

### GET /debug/pprof

性能分析（需安装 Graphviz 查看图形化）

```bash
# 查看 heap 信息
go tool pprof -http=:8080 http://127.0.0.1:9090/debug/pprof/heap

# 查看 allocs 信息
go tool pprof -http=:8080 http://127.0.0.1:9090/debug/pprof/allocs

# 下载原始数据
curl -o heap.prof "http://127.0.0.1:9090/debug/pprof/heap?raw=true"
```

---

## 响应格式

### 成功响应

```json
{
  "name": "香港节点",
  "type": "ss",
  "history": [...]
}
```

### 延迟测试响应

```json
{
  "delay": 120,
  "loss": 0
}
```

### 连接列表响应

```json
{
  "connections": [
    {
      "id": "conn-uuid",
      "metadata": {
        "network": "tcp",
        "type": "HTTP",
        "sourceIP": "192.168.1.100",
        "destinationIP": "8.8.8.8",
        "destinationPort": 80,
        "host": "example.com"
      },
      "upload": 1024,
      "download": 2048,
      "start": "2024-01-01T00:00:00Z"
    }
  ]
}
```

---

## 错误处理

常见错误码：

| 状态码 | 说明 |
|--------|------|
| 400 | 请求参数错误 |
| 401 | 未授权（缺少或错误的 secret） |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |


path: scripts/clash_api_client.py
content: #!/usr/bin/env python3
"""
Clash Verge API 客户端示例
用于通过 RESTful API 控制 Clash Verge (mihomo 内核)
"""

import requests
import json
import sys
from typing import Optional, Dict, Any


class ClashController:
    """Clash Verge API 控制器"""
    
    def __init__(self, host: str = "127.0.0.1", port: int = 9090, [REDACTED_SECRET] = None):
        self.base_url = f"http://{host}:{port}"
        self.headers = {}
        if [REDACTED_SECRET]"Authorization"] = f"Bearer {secret}"
    
    def get_proxies(self) -> Dict[str, Any]:
        """获取所有代理"""
        resp = requests.get(f"{self.base_url}/proxies", headers=self.headers)
        resp.raise_for_status()
        return resp.json()
    
    def get_proxy(self, name: str) -> Dict[str, Any]:
        """获取指定代理信息"""
        resp = requests.get(f"{self.base_url}/proxies/{requests.utils.quote(name)}", headers=self.headers)
        resp.raise_for_status()
        return resp.json()
    
    def set_proxy(self, group_name: str, proxy_name: str) -> Dict[str, Any]:
        """切换代理节点"""
        resp = requests.put(
            f"{self.base_url}/proxies/{requests.utils.quote(group_name)}",
            headers=self.headers,
            json={"name": proxy_name}
        )
        resp.raise_for_status()
        return resp.json()
    
    def test_delay(self, proxy_name: str, url: str = "https://www.google.com", timeout: int = 5000) -> Dict[str, Any]:
        """测试代理延迟"""
        resp = requests.get(
            f"{self.base_url}/proxies/{requests.utils.quote(proxy_name)}/delay",
            params={"url": url, "timeout": timeout},
            headers=self.headers
        )
        resp.raise_for_status()
        return resp.json()
    
    def get_groups(self) -> Dict[str, Any]:
        """获取策略组"""
        resp = requests.get(f"{self.base_url}/group", headers=self.headers)
        resp.raise_for_status()
        return resp.json()
    
    def get_group(self, group_name: str) -> Dict[str, Any]:
        """获取指定策略组"""
        resp = requests.get(f"{self.base_url}/group/{requests.utils.quote(group_name)}", headers=self.headers)
        resp.raise_for_status()
        return resp.json()
    
    def get_connections(self) -> Dict[str, Any]:
        """获取连接列表"""
        resp = requests.get(f"{self.base_url}/connections", headers=self.headers)
        resp.raise_for_status()
        return resp.json()
    
    def close_all_connections(self) -> None:
        """关闭所有连接"""
        resp = requests.delete(f"{self.base_url}/connections", headers=self.headers)
        resp.raise_for_status()
    
    def get_traffic(self) -> Dict[str, Any]:
        """获取流量信息"""
        resp = requests.get(f"{self.base_url}/traffic", headers=self.headers)
        resp.raise_for_status()
        return resp.json()
    
    def get_config(self) -> Dict[str, Any]:
        """获取配置"""
        resp = requests.get(f"{self.base_url}/configs", headers=self.headers)
        resp.raise_for_status()
        return resp.json()
    
    def update_config(self, config: Dict[str, Any]) -> Dict[str, Any]:
        """更新配置"""
        resp = requests.patch(
            f"{self.base_url}/configs",
            headers=self.headers,
            json=config
        )
        resp.raise_for_status()
        return resp.json()
    
    def restart(self) -> None:
        """重启内核"""
        resp = requests.post(f"{self.base_url}/restart", headers=self.headers)
        resp.raise_for_status()
    
    def get_version(self) -> Dict[str, Any]:
        """获取版本"""
        resp = requests.get(f"{self.base_url}/version", headers=self.headers)
        resp.raise_for_status()
        return resp.json()
    
    def flush_dns(self) -> None:
        """清除 DNS 缓存"""
        resp = requests.post(f"{self.base_url}/cache/dns/flush", headers=self.headers)
        resp.raise_for_status()
    
    def flush_fakeip(self) -> None:
        """清除 FakeIP 缓存"""
        resp = requests.post(f"{self.base_url}/cache/fakeip/flush", headers=self.headers)
        resp.raise_for_status()


def main():
    """命令行使用示例"""
    import argparse
    
    parser = argparse.ArgumentParser(description="Clash Verge API 客户端")
    parser.add_argument("--host", default="127.0.0.1", help="API 主机地址")
    parser.add_argument("--port", type=int, default=9090, help="API 端口")
    parser.add_argument("--secret", help="API 密钥")
    parser.add_argument("--action", choices=["list", "version", "traffic", "restart"], 
                        default="version", help="操作")
    parser.add_argument("--group", help="策略组名称")
    parser.add_argument("--proxy", help="代理名称")
    
    args = parser.parse_args()
    client = ClashController(args.host, args.port, args.secret)
    
    try:
        if args.action == "version":
            info = client.get_version()
            print(json.dumps(info, indent=2, ensure_ascii=False))
        
        elif args.action == "list":
            proxies = client.get_proxies()
            print(json.dumps(proxies, indent=2, ensure_ascii=False))
        
        elif args.action == "traffic":
            traffic = client.get_traffic()
            print(json.dumps(traffic, indent=2, ensure_ascii=False))
        
        elif args.action == "restart":
            client.restart()
            print("内核已重启")
    
    except requests.exceptions.RequestException as e:
        print(f"错误: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)