Skip to content

Releases: crhan/proxyctl

v0.5.12

06 Jun 16:42

Choose a tag to compare

Fixed

  • proxyctl env 不再把 no_proxy_extra 中的裸 IPv6 CIDR 写入 NO_PROXY
    这避免 Python/httpx 工具把类似 fd7a:115c::/48 的条目误解析为带非法端口的
    URL;域名、IPv4 CIDR 和默认本地绕过项保持不变。

Changed

  • proxyctl trace[4/4] 实际连接 改为按链路聚合并给出明确结论。
    旧版逐条平铺活跃连接、且只取其中一条与规则预测对比,在改规则后的过渡态
    (新连接走代理、旧连接仍复用原链路并存)下会自相矛盾地误报"预测出口 X,
    实际出口 Y"。新版把相同链路的连接合并计数、累加流量,按"链路是否命中预测
    出口"分类,并区分三种结论:全部命中(与规则一致)/ 全部未命中(规则可能
    未生效或被前置规则截胡)/ 新旧并存(旧连接在建连时已定死链路,会随超时
    自然断开,刷新后即全部走预测出口)。判定改用"预测组名是否出现在链路中"的
    集合判定,消除旧版"出口"一词在告警行(取链路入口组)与详情行(取末端节点)
    指代不一致的歧义。
  • [4/4] 连接采集改为 host 精确匹配优先。 仅在拿不到 host(典型 fake-ip
    模式)时才回退按 destinationIP 匹配,避免 Cloudflare 等共享 IP 把同 IP
    其他站点的连接误算进当前域名。

v0.5.11

30 May 16:34

Choose a tag to compare

Fixed

  • proxyctl trace 的规则预测现在尊重 no-resolve 标志。
    域名经 HTTP 代理 / fake-ip 连接时,带 no-resolve 的 IP 规则(如
    IP-CIDR,100.64.0.0/10,DIRECT,no-resolve)会被引擎跳过;[2/4] 规则匹配
    不再误报命中这类规则,预测出口与 [4/4] 实际链路一致。命中其他规则时,
    会提示有哪些 no-resolve IP 规则因当前连接为域名而被跳过。

v0.5.10

30 May 10:11

Choose a tag to compare

Fixed

  • proxyctl check 连通性面板的 via 列现在按可见宽度对齐。
    彩色状态码和 ok / 200 / 401 这类不同长度状态不再导致 via 列左右漂移。
  • proxyctl check 连通性 via 列不再普遍显示 ? v0.5.9 引入的
    反查是在 curl 测试结束之后才查 mihomo /connections,而短连接
    curl 一退出连接就从连接表移除,几乎抓不到自己刚发的请求 —— 只有恰好
    有外部进程在持续访问同一 host(如 Claude Code 长连 api.anthropic.com
    时才会被"蹭"到显示出来。本版改为在 curl 测试进行中并发轮询
    /connections,趁连接还活着抓到真实链路;抓不到时回退到既有的外部
    连接探测;都没找到时显示 via —(em dash 友好占位)而非 via ?
  • 内置 connectivity-basic 插件不再 hardcode 个人代理组名 claude
    原先 anthropic target 写死了 expected_proxy="claude",且出口探测里
    写死了 OutboundProbe(name="claude", …),导致没有 claude 组的用户
    check 会被误判 expected claude, got … 且出口 IP 段多一行无意义
    claude。命名组校验和命名出口探测属本机特例,请在
    ~/.config/proxyctl/plugins/ 的用户插件里追加。
  • proxyctl check 出口 IP 不再出现同名 direct 行重复。 旧的去重
    key 把 url 也算进比较,内置插件的 https://myip.ipip.net 和用户
    插件的 http://myip.ipip.net 仅协议不同就漏了去重 → 同一出口显示
    两行。本版按 (name, mode) 折叠:同名同模式视为同一出口行,后加载的
    用户插件覆盖内置同名探测(本机特例优先),显示顺序保持稳定。
  • proxyctl audit 现在能识别任意命名代理组下的 DOMAIN-SUFFIX 规则。
    _load_rules 原本只把 outbound ∈ {direct, proxy, claude} 三个名字
    归类,其它命名组(如 residential-tw / jp-streaming 等)的规则被
    完全忽略 → audit 统计偏低、推荐误报。本版改为"非 direct、非
    block/reject 即视为代理类",任何命名代理组的规则都正确进入
    proxy_suffixes

Changed

  • _connectivity_line_value("proxy") 默认值从 "?" 改为 "—"(em dash),
    仅影响 check 连通性表 via反查失败时的占位字符。JSON 字段
    data.stages.connectivity[].line 在该场景下从字符串 "?" 变为 "—"
    消费方判断"是否有真实链路"建议改用 route_chain 非空,而不要 string-match
    这个占位。

v0.5.9

27 May 00:10

Choose a tag to compare

Added

  • proxyctl connections 支持位置参数关键字 + 跨字段智能匹配。
    现在可直接写 proxyctl connections codex 443,等价于
    --query codex --query 443。每个关键字独立判定命中维度:纯数字关键字
    target_port / source_port / pid 做精确比较,文本关键字对
    target_host / destination_ip / app / process / command 做大小写
    不敏感子串匹配;多关键字之间取 AND,每个关键字必须至少命中一个维度。
    JSON 输出在每条命中行新增 match_reasons: {keyword: [dimensions]} 字段,
    显示是哪个关键字命中了哪些维度(当本次调用没有任何关键字时,该字段不会
    出现在 row dict 上——消费方应按 "key may be absent" 处理)。人类视图启用
    ANSI 高亮(黄底黑字)标出命中子串,并在 0 行命中时打印关键字 + 尝试过的
    维度提示(仅在本次提供了关键字时打印;仅有 --app 等结构化过滤而无关键字
    时不会打这个提示)。
  • LocalConnection.to_dict() 的 JSON 输出新增 command 字段,把
    ps -o command= 抓到的完整命令行一并暴露,方便位置参数关键字按命令行匹配,
    也便于消费方调试。
  • proxyctl connections --verbose 在人类视图展开 socket 明细。
    默认 human 视图只渲染目的站点汇总(数量、路由、链路、持有进程计数);加上
    --verbose 后会在每个目的站点下逐条展开 socket 明细:完整进程路径、命令行、
    Mihomo rule / rule_payload / chains / upload / download / start / route_kind,
    以及本次位置参数关键字的命中维度(命中: kw=dim1+dim2)。JSON 输出不受
    此 flag 影响,明细一直在 proxy_owner_connections[] 里。
  • proxyctl connections 人类视图的上传/下载/开始时间改用人类单位。
    上传/下载字节数现在显示为 8.0 KiB / 1.5 MiB 等二进制单位,而不再是
    原始字节数;开始时间在 ISO 8601 时间戳后追加相对时长,如
    2026-05-23T17:20:27.854916+08:00 (5m20s 前),方便快速判断连接生命周期。
    解析失败时回退到原始时间戳,不掩盖原数据。
  • proxyctl connections --verbose 自动读取 traffic store 历史数据。
    开启 --verbose 后,命令会去 ~/.cache/proxyctl/traffic_events.ndjson
    (或 traffic_store_dir 指向的位置)加载 proxyctl traffic sample/watch
    采样积累的事件流,按 host 索引后挂到每条 socket 上。每个 socket 明细下方
    会展开历史块:累计上传/下载、首次/末次见到的时间(含相对时长)、
    历史连接数、出现过的进程列表。build_report 输出顶层新增 history_status
    字段记录是否加载成功、读取到几条事件,便于 JSON 消费方判断;human 视图
    在 traffic events 为空时一次性提示用户先跑 proxyctl traffic watch
  • proxyctl check 连通性面板新增实际路由显示。 proxy 模式的 URL 探测
    会从本地 Mihomo /connections 读取该站点实际命中的链路,并在人类输出中
    显示为 via <group> → <leaf>;直连探测显示 via direct,DNS/TCP 探测
    显示 via -,拿不到活跃连接时显示 via ?。JSON 输出中的每个
    connectivity row 同步新增 lineroute_chain 字段。
  • proxyctl check 内置连通性基线新增 OpenAI API 探测。
    默认站点现在包含 openaihttps://api.openai.com/v1/models),并将
    anthropic 从根路径改为 https://api.anthropic.com/v1/models,让 AI
    API 健康检查更接近真实调用路径;4xx 仍按“链路已通”处理。

Changed

  • proxyctl connections --query 语义升级(行为变化)。 之前 --query
    是把多个值在 process + target + contexts 拼成的大串上做 OR 子串匹配;
    现在与位置参数共用 AND + 跨字段独立判定逻辑。多值场景下结果可能比旧版本
    更窄(旧 OR → 新 AND),但单值场景下匹配范围反而更宽(不再依赖字段被拼接
    的顺序)。脚本里使用 --query 的用户请确认这一语义变化。
  • proxyctl check 连通性成功行统一使用 via ... 表达。
    成功命中期望代理组时,人类输出不再同时显示 线路 <leaf>via ...
    所有连通性行统一保留 via <route>。只有期望组不匹配时才追加错误说明。
  • proxyctl check 会去重内置插件与用户插件提供的完全相同探测项。
    当旧用户插件仍声明与内置插件相同的 connectivity target 或 outbound probe
    时,人类输出不再重复显示同一站点或同一出口 IP;不同 URL 或不同 mode 的
    同名自定义探测项仍会保留。

Fixed

  • proxyctl check 的 URL 连通性探测改用 HTTP/1.1,避免 Discord 一类站点
    因 HTTP/2 协商异常被误报为 timeout。
    curl 返回 HTTP code 000
    时,人类输出现在会显示 stderr 中的简短错误原因;没有 stderr 时仍显示
    timeout

v0.5.8

22 May 06:53

Choose a tag to compare

Fixed

  • proxyctl check 的出口 IP 归属地补全不再依赖被测代理线路。
    第 4 阶段会直连查询已探测到的 IP 归属地,避免 claude 出口失败时影响
    directproxy 的归属地显示。

Changed

  • 出口 IP 归属地补全现在并发执行。 proxy / claude / direct
    的归属地查询互不阻塞,单个出口查询慢或失败不会拖慢其他出口的显示。

v0.5.7

22 May 04:54

Choose a tag to compare

Changed

  • proxyctl check 现在会显示 mihomo 规则实际引用的代理组。
    claude 这类不挂在默认 proxy 组下面、但被 DOMAIN-SUFFIX,...,claude
    规则命中的业务组,会和 proxy 一起出现在代理组检查段,方便维护者从同一个
    视图确认规则、组和节点状态。
  • proxyctl check 现在会验证 Anthropic 连通性及 Claude 线路命中。
    连通性阶段新增 anthropic 检查,并在请求后通过本地 mihomo /connections
    确认链路末端为 claude
  • 出口 IP 探测现在覆盖 proxyclaudedirect 三类出口。 第 4 阶段
    会同时显示默认代理出口、Claude 规则出口和直连出口,方便确认分流是否生效。

v0.5.6

22 May 04:43

Choose a tag to compare

Added

  • 新增 proxyctl traffic 线路/软件流量统计。 snapshot 读取 Mihomo
    /connectionsupload / download 并按线路、链路、软件或路由聚合;
    sample / watch 可把连接计数器增量写入本地缓存;report --since 1h
    可按已记录增量生成历史窗口报表。watch 在人类输出模式下会每次采样实时打印
    进度行。命令复用 connections--host /
    --chain / --route / --preset / --agent 过滤。首次采样只建立基线,
    不回填此前已经产生的字节,避免把活跃连接当前计数误算成历史累计。

Fixed

  • proxyctl connections 现在能显示 macOS Network/System Extension
    接管后的 Mihomo 连接 owner 与实际代理链路。
    当 OpenAI / ChatGPT 等
    连接被本机网络扩展接管时,lsof 只能看到扩展进程而不是原始 App。
    本版在 macOS 上补充 netstat -anv 反向归因,JSON 新增
    proxy_owner_connections[],包含 socket owner、是否为系统扩展、
    Mihomo route_kind / chains / routed_via_proxy,并新增
    proxy_owner_groups[]rulePayload / host / IP 聚合目的地。如果同一
    目的组出现不同 chains 或 route kind,会输出 warning=mixed_chains
    / mixed_route_kind 和 summary 里的
    inconsistent_proxy_owner_group_count,从而能判断连接是否经过 Mihomo、
    最终是 proxy 还是 direct 路由,以及同一组线路是否一致。
  • proxyctl connections 默认输出全量目的站点,并新增多维过滤。
    无参数时不再默认限制 Codex / Claude / ChatGPT;需要 AI 视角时使用
    --preset ai。新增 --host 按 host / rulePayload / IP 过滤,--preset
    使用预设(ai / openai / anthropic / coding 等),--agent 按工具
    过滤(codex / claude / chatgpt / openclaw 等),--chain /
    --line 按 Mihomo 链路节点过滤,--route 按 route kind 过滤
    proxy / direct / reject / unknown,同时接受中文别名),
    --query / --filter 做全文过滤。不同维度之间取 AND,同一维度内多个值取 OR。
    --app Codex / --app Claude 保持向后兼容,分别匹配 App 与 CLI 两类上下文。
  • proxyctl connections 的人类输出改用目的站点汇总。 默认输出只按
    目的站点展示数量、候选 App / CLI、路由和链路;每个目的站点下会统计
    持有进程连接数,例如 com.antgroup.asp(pid=47283):8,系统扩展也按普通
    进程展示。人类输出里的上下文显示为 Claude App / Claude CLI 等可读
    名称,并使用多行布局展示候选、链路、主机和持有进程,避免长字段挤在
    同一行;--json 里的 proxy_owner_connections[] 仍保留逐条 socket 明细。

v0.5.5

21 May 13:15

Choose a tag to compare

Fixed

  • proxyctl check 的 selector/fallback 代理组现在显示全部子组与
    真节点成员,不再只显示 now 那一个子组。
    v0.5.3 / v0.5.4 的"精简
    显示"为了避免节点重复,把 now 之外的兄弟子组 summary 行和混在
    子组里的真节点成员(如 local-13659)都跳过了,导致典型 claude → [residential-sg, residential-us, local-13659] 这种结构里用户只能看到
    当前命中的那一个子组,连"还有哪些可选线路"都不知道。本版恢复全部
    子组 summary 可见 + 真节点成员可见,但仍只对 now 子组展开叶子
    节点列表(保留 v0.5.3 跨组去重 (详见上方) 行为),单组从 ~50 行
    精简到 5-7 行的目标不变。

Added

  • 新增 proxyctl connections 只读诊断命令。 该命令读取本机
    lsof / ss / ps 连接信息,并在 mihomo 后端下用本地
    /connections API 按 metadata.sourcePort 关联连接详情。默认过滤
    Codex / Claude / ChatGPT,--app <name> 可重复指定应用过滤,--all
    查看所有进程;--json 输出 envelope v2,包含进程、PID、fd、本地源端口、
    是否连接到 proxy_port、mihomo host/destination/rule/rulePayload/chains/
    upload/download/start,以及 unmatched 原因。非 mihomo 后端或本地 API 不可用
    时降级输出本机连接并标注 unmatched。

v0.5.4

21 May 10:36

Choose a tag to compare

Fixed

  • doctor 在 Linux + proxy 模式下不再误报 dns_ok 失败。 旧逻辑
    _dns_points_to_loopback() 简单粗暴读 /etc/resolv.conf 看是否含
    127.0.0.1,但 Ubuntu / Debian 标准是 systemd-resolved 在 127.0.0.53:53
    起 stub resolver,永远不会匹配 → 永远判 ✗ → doctor 给出 next: proxyctl fix
    的错误建议,且 fix 的 plan 显示 macOS 风格的 networksetup 步骤(实际
    cmd_fix Linux 路径根本不跑这些)。本版 doctor 改用 mode-aware
    _dns_check_ok(mode):proxy 模式直接返回 True(流量走 HTTP/SOCKS 代理,
    mihomo 不在 :53 监听,系统 DNS 用 systemd-resolved/DHCP 默认即可),
    tun / mixed / 未知模式保留旧的回环判定。doctor 人类输出 dns_ok 描述行
    按 mode 切换:(proxy 模式无需 DNS 劫持)(系统 DNS 含 127.0.0.1)

  • fix --dry-run 在 Linux 不再输出 macOS 风格的 DNS 改写步骤。
    _plan_fix 按平台分支:Linux 只输出 1 步 http_put(Clash API 热重载),
    cmd_fix 实际 Linux 路径对齐;macOS 保留三步(DNS reset + cache
    flush + reload)。之前 Linux 用户 dry-run 会被 plan 误导以为 fix 要改
    系统 DNS。

Compatibility

  • data.dns_ok 字段类型不变(仍是 bool);但 proxy 模式下该字段含义
    从"系统 DNS 是否含 127.0.0.1"变为"DNS 配置对当前 mode 是否健康"。
    agent 消费 data.dns_ok 的逻辑无需调整。
  • data.plan[].action 枚举不变;Linux 平台 fix plan 步数从 3 降到 1。

v0.5.3

20 May 01:05

Choose a tag to compare

Fixed

  • proxy_group.mostly_dead 规则不再对 selector-of-selectors 误报。
    v0.5.0 规则按"直接成员 delay==0"计数,对 mihomo 主流订阅结构
    (GLOBAL → 一堆分流子组 + DIRECT/REJECT,其中分流子组通常无 latency
    history)会把"没测过延迟的子组"算成 dead,触发假阳 warn。本版改为
    穿透 selector / URLTest / Fallback / LoadBalance / Smart 子组到真叶子
    节点(去重)后统计;伪节点(DIRECT/REJECT/Pass/Compatible)排除;
    循环引用安全。evidence.total_count 现在反映叶子节点数。
  • autostart.version_mismatch 不再对同一 binary 自比误报。 0.5.2 修了
    cli.get_engine_versionv 前缀 strip,但 autostart.inspect_runtime
    里独立解析的 autostart_version 字段没同步 strip,导致即使 plist 与 PATH
    指向同一个 mihomo 二进制,v1.19.25 != 1.19.25 字面比较仍触发 advisory。
    同时显示文案出现 vv1.19.25 双前缀。本版两处统一 strip + 同 binary 路径
    直接跳过版本对比(同一文件无版本差异)。
  • autostart_version evidence 字段不再带 v 前缀,与 path_version
    对齐,agent 可稳定比较。

Added

  • proxyctl bench 跨组去重重复线路 + 穿透 selector 子组到叶子。
    之前 bench 只在直接成员层去重,对 GLOBAL → 13 个分流子组的结构会把
    子组当节点测(返回组的 now 节点延迟);多个组共享同一子组时叶子被重复
    探测 N 次。本版用同款 _collect_leaves 穿透;伪节点(DIRECT/REJECT)
    排除;跨组全局去重。

    • 人类模式:测速行加 (去重省 N 次) 提示
    • --json summary 新增 raw_count(去重前各组叶子和)+
      dedup_saved(省下的次数)字段
    • 实测 proxyctl bench GLOBAL "💬 OpenAi" 从 48+ 次探测降到 24 次
  • proxyctl check 集成 proxy_group.mostly_dead 判定。doctor 早就
    会报"GLOBAL 组 15/15 节点全挂",但 check 之前只展示组明细、不参与
    fail 判定,agent 看 check --json 拿到 ok=true 却感觉不对。本版 check
    在 [2/4] 代理组阶段后调用与 doctor 同款的 suggest_rules.proxy_group_rules
    规则,任何组 ≥70% 节点 delay==0 即:

    • 人类模式打印红色 ✗ GROUP: dead/total 节点不可达 (pct%)
    • exit code 变 1
    • data.stages.dead_groups[] 输出每组结构化事实
    • envelope.hints 聚合 proxy groups mostly dead: GLOBAL(15/15) — try \proxyctl bench``

Added — Agent 提示

  • agent-guide 新增 Config Tracking + 新 explain topic
    config-tracking
    :建议 agent 在用户机器首次见到 ~/.config/proxyctl/
    .git 时提示用户初始化 git 仓库追踪配置变化,含推荐 .gitignore
    排除 secret 与高频抖动文件(subscription-source.env /
    subscription.json / .lock.* / .ipgeo-* / *.bak)。proxyctl 自己
    不做版本控制,跟"不拉订阅"是同一类边界——版本控制是用户/agent 职责。

Changed

  • proxyctl check exit code 在组挂时变 1(之前永远 0)。--json
    输出 envelope.ok=falsedata.stages.dead_groups[] 字段新增。
    agent 已消费 data.stages.* 的需注意此 stage 新增。

  • proxyctl check [2/4] 代理组输出大幅精简。 之前 selector 会把
    顶层成员行 + 每个子组的全部节点都列一遍,多个组共享同一子组时节点
    列表打 N 遍(n=组数)。本版:

    • selector / fallback 当 now 指向子组时,跳过顶层成员行(避免与子组
      重叠的节点列表重复打印)
    • 只展开 now 指向的那一个子组(其他子组不展开)
    • 跨组去重:已展示过节点列表的子组再次出现时只打摘要行 + (详见上方)
    • 实测用户机器从 ~50 行降到 11 行

    仅人类模式输出变化;--jsondata.stages.groups[] 结构不变。