Files
wechat-ops/SKILL.md
T
kenyanghuiandClaude 1d04e1bf00 Add wechat-ops skill
macOS GUI automation via a screenshot → vision-locate → act → verify loop.
Coordinates are never hard-coded; every step is located live and confirmed
by re-screenshot.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-27 17:18:20 +08:00

11 KiB
Raw Blame History

name, description
name description
wechat-ops 用「截图 → 视觉识别 → 动作 → 截图验证」的闭环操作 macOS 电脑,代替人手点按钮、输文字、切窗口、走界面流程。只要用户想让你「帮我点一下」「操作我的电脑」「自动发个朋友圈/消息」「把这段文字输入到某个软件」「帮我走一遍这个界面流程」「模拟点击」「识图点击」「截图找按钮」「GUI 自动化」「RPA」,都必须使用本技能——即使用户没说要"用技能"。核心特征:坐标绝不写死落盘,每次实时看图现算、事后验证。若目标是在 Figma 画布内做设计,请改用 Figma 系列技能。

WeChat Ops

用视觉驱动的方式操作 macOS 电脑:看屏幕 → 判断点哪里 → 动手 → 再看一眼确认。

一、核心原则

1. 坐标是易耗品,绝不落盘

分辨率、窗口位置、应用版本、系统语言——任何一样变了,写死的坐标就失效。所以:

  • 技能里存的是「怎么找到它」,不是「它在哪」
    • ❌ 朋友圈入口在 (30, 297)
    • ✅ 朋友圈是左侧边栏第 5 个图标,光圈形状
  • 坐标只存在于本次任务的上下文里,任务结束即作废。
  • 如果你正想「把这次成功的坐标记下来下次直接用」——停。那是在造一个明天就会坏的缓存。该记的是语义特征和判断方法。

这条是整个技能的地基。写死坐标的方案(无论存成 JSON 还是 Markdown)都只是把脆弱的快照换了个格式。

2. 每步都要验证

视觉方案真正的价值不是"能看图",而是"点完能确认"。

每次动作后截一张图,确认结果符合预期,再做下一步。看起来慢,实际上:

  • 点错了能立刻发现并纠正,而不是一路错到底
  • 界面和预想不一致时(弹窗、加载中、位置变了)能及时改道

判断标准:如果这一步失败了你不会察觉,那这一步就该加验证。

3. 先想清楚交互方式,再动手

同一个控件,单击和长按可能完全是两回事。动手前先问:这个操作是单击、双击、长按、右键还是拖拽?

真实案例:微信朋友圈的相机图标,单击打开"选图片"文件框,长按才出纯文字发布框。没搞清楚就会点出一个文件选择器。

拿不准就先用 --dry 或在无关紧要的地方试。

二、坐标系(先读这段,否则必错)

macOS Retina 屏上,截图分辨率和点击分辨率不是一回事。

  • screencapture 输出的是物理像素(Retina 通常是 2 倍)
  • pyautogui 点击用的是逻辑像素

vision.py 已经处理了这件事:截图时自动缩放到逻辑分辨率,所以

图上量到的坐标 = 直接可用的点击坐标

这正是为什么所有操作都要走 vision.py 而不是直接 screencapture——手工换算 2 倍关系是最高频的错误来源。

三、工具:scripts/vision.py

命令 作用
shot [名字] 截当前屏,缩放到逻辑分辨率。始终刷新 cur.png
grid [名字] [间距] 截图并叠加带刻度的坐标网格,读位置不用估算
crop x1 y1 x2 y2 [名字] [倍数] 精确裁剪放大,看小图标/小字。左上角标注原点
click X Y 单击
dclick X Y 双击
longpress X Y [秒] 长按(默认 1.2 秒)
move X Y 只移动鼠标
activate 名称 按窗口/进程名激活并置前
type "文本" 输入文本,走剪贴板,支持中文长文本
key cmd+v 按键,支持 cmd+shift+f 这类组合
scroll N [X Y] 滚动。可指定鼠标落点——滚轮事件发给指针所在的视图
pos 打印屏幕尺寸和当前鼠标位置

截图统一存在 /tmp/wechat_ops/。

环境依赖:pip install pyautogui pyperclip pillow,并在「系统设置 → 隐私与安全性 → 辅助功能」里授权终端。

四、标准流程

1. 激活目标窗口          activate <名称>
2. 看清全貌              shot / grid
3. 定位目标元素          grid 读数 → crop 放大确认(两种方法对上再动手)
4. 执行动作              click / longpress / type / key
5. 截图验证              shot,确认结果符合预期
   └─ 不符合 → 回到 2 重新定位

第 3 步的「两种方法对上」很重要:网格给你绝对位置,裁剪放大给你细节确认。两者一致时基本不会点错。

五、定位技巧

网格读数(找大致位置)

python3 vision.py grid wxgrid 50

在截图上画出每 50px 的红色竖线、蓝色横线并标注刻度。直接读刻度,不靠目测。

裁剪放大(确认细节 + 精确定位)

python3 vision.py crop 0 275 70 335 icon_check 6

放大 6 倍后能看清图标形状、文字内容。输出图左上角标注了裁剪原点(如 origin=(0,275) x6),在放大图里量到的偏移除以倍数、加上原点,就是绝对坐标。

这条标注是刻意设计的:没有它,在放大图里读数极易把原点搞错。

判断元素身份

图标类元素靠形状认(光圈=朋友圈、相机=发表、铃铛=通知),不靠位置猜。文字类直接放大读。

六、已知陷阱(都是实测踩过的)

1. 中文输入法会吃掉组合键

pyautogui.hotkey('command', 'v') 在拼音输入法下会退化成裸字母 v,弹出一个拼音候选框,文字根本没粘进去。

解法:用 AppleScript 发组合键。vision.py 的 type 命令在 macOS 上已默认走这条路:

osascript -e 'tell application "System Events" to keystroke "v" using command down'

自己写脚本时也要注意这一点。

2. 读图命令会读到旧截图

这是最隐蔽的一类错误:图本身没错,错的是它描述的那个瞬间已经过去了。你会对着一个不存在的界面做判断,然后点空,而且毫无察觉。

实测踩过两次:click → type → crop 这样连写时,中间没有 shot,crop 读到的是动作之前的 cur.png——于是明明输入成功了,看到的却是「占位文字还在」,差点重输一遍。

vision.py 的处理:crop / grid 每次自动重新截图。宁可多截一张(几十毫秒),也不要看错。自己写脚本时照做。

3. 弹窗会挡住目标

点了一个按钮后可能弹出对话框、文件选择器、权限提示。动作后一定截图,否则下一步会点在弹窗上。

按 esc 通常能关掉误弹的框。

4. 输入前先确认焦点

点击输入框后,最好截图确认光标进去了(占位文字消失、出现光标),再输入。否则文字可能跑到搜索框之类的别处。

5. 滚动前先把鼠标移进目标区域

滚轮事件发给指针当前所在的那个视图。指针停在别处(比如左侧聊天列表),你想滚朋友圈流,滚的是聊天列表——而且界面上看起来"没反应",很容易误判成"已经到底了"。

vision.py scroll N X Y 会先移动鼠标再滚,就是为这个。

另外滚动方向要实测,别照搬直觉:本机实测 pyautogui.scroll(正数) 是让内容往上走(即翻到更旧的位置),和"正数向上"的字面意思相反。滚错方向时,你会以为已经到顶了,其实是在往下翻。

判断是否到顶:滚一大段后再反着滚回来,如果位置没变,那就是真到边界了。

6. 别在用户的真实账号里乱试

操作微信、邮箱、支付这类真实应用时,先想清楚这一步有没有副作用。

七、安全边界

以下动作先跟用户确认再执行:

  • 对外发布:发朋友圈、发消息、发邮件、提交表单
  • 破坏性:删除、覆盖、清空、退出未保存的编辑
  • 花钱:下单、支付、订阅
  • 不可逆:任何做了就回不去的操作

确认时把「将要发生什么」说清楚,而不是只问「可以吗」。

一个实用的做法:把流程走到最后一步停住,让用户看到完整状态(文案已填、设置已选),再决定要不要按下那个不可逆的按钮。

八、完整案例:微信朋友圈发布纯文字

这个案例贯穿了上面所有原则,可作模板参考。

⚠️ 下面括号里的坐标是某一次实测值,仅供理解流程,不要照抄——每次都要重新定位。

步骤 动作 定位方式
1 activate 微信 按进程名激活
2 grid 看全貌 网格读数找到侧边栏第 5 个图标(光圈形状)= 朋友圈
3 crop 放大确认形状 交叉验证坐标 (30, 297)
4 click 进入朋友圈 截图确认已进入
5 找发布按钮 裁剪右上角,认出三个图标中最右的相机
6 longpress 相机图标 ⚠️ 单击会弹文件框,长按才出纯文字框
7 click 输入区 → type "文案" 截图确认文字进去了
8 点「谁可以看」→ 选「私密」→ 确定 截图确认已变成「私密」
9 ⏸️ 停住,问用户 发布是对外动作,确认后再点「发表」

关键教训都在这条流程里:长按 vs 单击、输入后验证、可见范围要显式设置、最后一步停下来问。

附:发图文朋友圈(和纯文字的关键差别)

同一个相机图标,要图就单击,纯文字就长按:

想要 对相机图标 后果
图文 单击 弹出系统文件选择器,选完图进发布框
纯文字 长按 直接进发布框(单击只会弹文件框)

图文流程比纯文字多两步:

  1. 文件选择器里进目标目录(左侧「下载」「桌面」等),选中文件 → 点「打开」
    • 选完先裁剪确认高亮再点打开,否则可能选中的是相邻文件
  2. 发布框里多了图片缩略图,其余(输入文案、谁可以看、发表)与纯文字一致

发表之后怎么验证

微信 Mac 版的朋友圈信息流不显示自己发的私密动态——发完回到信息流看不到自己的帖子,这是正常的,别据此判断失败、更别重发。

真正可靠的验证入口:点左下角自己的头像 → 资料卡里的「朋友圈」一行 → 我的朋友圈相册,按「今天 / 昨天 / 更早」分组列出自己的全部动态。刚发的那条会出现在最上面。

(顺带一提:这个「信息流看不到」的现象反过来也能当作旁证——如果一条动态在信息流里也出现了,那它多半不是私密。)

九、和「录制回放」方案的区别

录制回放(写死坐标) 本技能(视觉驱动)
定位时机 录制时定一次 每次执行时实时定位
界面变了 静默点错 看图发现异常,改道
出错后 不知道,继续错 截图验证,立即发现
存什么 像素坐标 语义特征 + 判断方法
适合 固定不动的界面 会变、会弹窗、跨机器的真实场景

代价是慢一些、每步要截图。但对真实桌面应用来说,可靠性远比速度重要。