一、我做了一个新的 Skill:MacOS Desktop Control
简单来说,这个 Skill 的目标是让 AI Agent 在 macOS 上干点“实在活儿”:打开应用、识别屏幕内容、点击按钮、输入文字、拖拽元素,甚至是读取窗口状态。整个过程追求稳定、可控,同时兼顾 macOS 系统的独特特性。
这份 Skill 已经发布在 ClawHub(官方 Skill 平台),搜索“MacOS Desktop Control”即可找到并体验。
二、聊聊为什么要写这个 Skill
市面上虽然已有一些桌面控制方案,但在实际使用中,几个具体痛点非常突出:
- MacOS 兼容性没到位。 很多现成的 Skill 都忽略了 macOS 的特性。最典型的就是 Retina 屏——截图使用像素坐标,鼠标点击使用逻辑坐标,若不处理好这个映射,Agent 就会“看得准,点不准”。
- 中文输入和识别是盲区。 比如你想让它输入“你好”,很多 Skill 会默认逐个英文字母敲进去,结果就是一堆乱码,严重降低效率。
- 没用好 macOS 的独门绝技。 像 AppleScript 这种顺手又好用的工具,用来打开 App、读取窗口标题效率极高;Apple 自带的 Vision 框架做文字识别也很优秀。这些“近水楼台”的资源,放着不用太可惜了。
这几个问题凑在一起,就成了开发这个新 Skill 的直接动机,也决定了它在 MacOS 桌面自动化领域的独特价值。
三、一个清晰的操作流水线
整个流程可以拆解为一条清晰的动作链:先用 AppleScript 激活目标应用或读取窗口状态,接着初始化坐标映射,然后截取屏幕,再用 OCR、OpenCV 或 AI 图像识别来定位目标,最后由鼠标或键盘执行动作,并验证结果。每一步环环相扣,稳定可靠,有效避免了传统自动化方案中的常见偏差。
四、这个 Skill 能做什么?
光说理论可能有些抽象,我们来看两个直观的例子。
1. 点击侧边栏会话按钮
执行效果
- OpenClaw 成功识别到了会话栏,并按预期点击打开了会话,整个响应极为迅速。
执行流程
- 整个流程完全由 Skill 的能力驱动,一气呵成,无需人工干预。
2. 新建备忘录并输入“我是KD”
执行效果
- 直接打开备忘录、新建笔记并输入文本,整个过程非常快,因为所有操作都在本地完成,不依赖网络延迟。
执行流程
- AppleScript 负责把备忘录切换到前台,键盘控制负责快捷键和输入内容,协同配合高效。
五、目录结构
项目的目录结构非常规整,核心代码都放在 scripts/ 目录下:
capture_screen.py:截取屏幕,用 pyautogui 获取全屏截图,并缩放到与点击坐标一致的逻辑分辨率。calibration.py:核心校准模块,比较屏幕像素分辨率与逻辑分辨率,计算缩放因子并保存到calibration.json。init_coordinate_mapping.py:初始化坐标映射脚本,主动运行一次校准并保存结果。crop_image.py:从已有截图中裁剪指定矩形区域。locate_image_opencv.py:使用 OpenCV 模板匹配定位图片/按钮,返回中心坐标。locate_text_ocr.py:使用 Apple Vision OCR 定位文字,返回中心坐标。applescript_app.py:通过 AppleScript 控制应用(打开、激活、检查运行状态、获取前台应用)。applescript_window.py:通过 AppleScript 管理窗口(获取标题、统计数量、列出窗口列表)。keyboard.py:键盘控制(粘贴、按键、组合键、按住/释放)。mouse.py:鼠标控制(单击、右键、双击、移动、拖拽、读取位置)。
六、一些关键技术点
1. Retina 坐标映射
在 macOS 桌面自动化中,一个很容易踩坑的问题就是:截图坐标和鼠标点击坐标不一定是同一套坐标系。
原因在于 Retina 屏幕通常有两套尺寸概念:逻辑坐标(point)和物理像素坐标(pixel)。鼠标控制工具习惯使用前者,而截图结果用的是后者。
举个例子,一块 Retina 屏幕在自动化工具里看起来可能是 1512 × 982,但实际截图尺寸却是 3024 × 1964。也就是说,逻辑宽高是 1512 × 982,截图宽高是 3024 × 1964,缩放比例是 2.0 × 2.0。
如果不处理这个映射,视觉识别返回的坐标拿去直接用,点歪是必然的。
这个 Skill 的做法是,在执行操作前先跑一次坐标初始化脚本,通过 pyautogui.size() 获取逻辑尺寸,再通过 pyautogui.screenshot() 获取像素尺寸,然后计算:
scale_x = shot_w / screen_wscale_y = shot_h / screen_h
结果保存到本地 JSON 文件里,换算关系也很直观:像素坐标转逻辑坐标是 point = pixel / scale,反过来就是 pixel = point * scale。
不过这个 Skill 进一步做了一层简化:默认把整个工作流统一到逻辑坐标系里。截图后主动把图像 resize 到逻辑分辨率,这样 OCR、模板匹配、鼠标点击都基于同一套坐标。后续流程更稳定,也更不容易出错,显著提升 MacOS 桌面自动化的精度。
2. 视觉实现
这个 Skill 的视觉层主要做两件事:看见屏幕上有什么,以及把目标元素定位成可点击的坐标。它没有走复杂的 UI 自动化树,而是采用了更通用的“截图 + 视觉定位”方案。很多自绘界面、聊天窗口、按钮图标、非标准控件,用这个方案反而更稳。
整个视觉实现分成三类:
第一类:OCR 文本定位
当目标是一个有文字的按钮,比如“确定”“发送”“会话”,最直接的方案就是 OCR。
这个 Skill 用的是 Apple Vision,通过 PyObjC 调用 macOS 原生文本识别能力,而不是依赖 Tesseract。这样做的好处是:macOS 原生支持,依赖更轻;中文识别友好;与系统图像栈兼容性更好。
实现上,会先对截图做一次放大,默认放大 3 倍再送进 Vision OCR,这能显著提升小字号文本的识别率。识别时同时启用了 'zh-Hans'、'zh-Hant'、'en-US' 多语言支持。
识别到文本后,会遍历结果,寻找与目标文本最接近的候选,并输出中心点坐标、边界框、识别置信度等信息。这种方法特别适合处理中文按钮、菜单项、标签栏以及聊天列表中的文字入口,在 MacOS 桌面自动化中非常实用。
第二类:OpenCV 模板匹配
如果目标不是文字,而是某个固定图标(比如关闭按钮、头像入口),走模板匹配会更合适。
这个 Skill 使用 OpenCV 的 matchTemplate,通过 cv2.TM_CCOEFF_NORMED 方法匹配,并用阈值判断是否命中。命中后同样输出中心点坐标和边界框。
它最擅长处理图标按钮、固定样式的 UI 元素,以及那些 OCR 不稳定但视觉样式很稳定的目标。
第三类:AI 语义理解
精确匹配(OCR、模板匹配)覆盖不了的目标,可以交给 AI 图像理解来处理。这类目标通常形态不固定、没有现成模板、需要结合画面上下文,或者只能用语义词汇描述。
比如画面中有多个可点击区域,需要判断哪个是当前目标;或者目标没有固定文字或图标模板,但可以用语义描述;再比如需要理解画面中各元素之间的关系。操作流程与上两种方式一致:截图 → crop 限定区域 → AI 识别 → 坐标映射 → 动作执行。本 Skill 负责截图和坐标转换,识别结果由调用者解读并决定后续动作。
为什么这种视觉方案很实用?因为很多现代桌面应用——尤其是 Electron、游戏化界面、聊天类界面——不一定能从系统无障碍树里稳定拿到目标控件。这时“先截图,再识别,再点击”反而更通用,也更能适应不同应用的差异性。
三种视觉手段的分工很清晰:OCR 找文字标签,毫秒级且精确;OpenCV 找固定图标/模板,也是毫秒级;AI 理解则处理形态不固定、需要上下文的目标,秒级,适合做决策层。这种分层设计让 MacOS 桌面自动化技能更加强大灵活。
3. AppleScript 应用
在这个 Skill 里,AppleScript 的定位很克制,也足够明确:它只负责语义明确的应用级控制,不负责深度 UI 点按。换句话说,它不是拿来点按钮的,而是做这些更稳定的事:打开应用、激活应用、判断应用是否在运行、获取当前前台应用、读取窗口标题、统计窗口数量、列出窗口标题。
比如激活一个应用时,脚本会执行 tell application "Google Chrome" to activate,为了确保应用真正到前台,还会结合 System Events 来置前。窗口信息读取也是类似思路,通过 AppleScript 获取前台窗口的标题。
为什么不直接用 AppleScript 做整个 UI 自动化?
因为 AppleScript UI scripting 虽然理论上能操作按钮、菜单、输入框,但在现实里经常遇到这些问题:不同应用的无障碍层级差异很大,自绘界面拿不到稳定控件,脚本容易因 UI 结构变化而失效,可移植性和鲁棒性都一般。
所以这个 Skill 刻意划了一条边界:AppleScript 负责应用和窗口层面的“语义控制”,视觉识别加鼠标键盘负责界面层面的“视觉操作”。这是一个很实用的工程折中,兼顾了稳定性和灵活性。
AppleScript 擅长的是“我知道我要操作哪个 app”,比如把 Chrome 切到前台,看当前哪个应用最前面,或者读一下当前窗口标题。而视觉和输入模拟擅长的是“我知道屏幕上哪个地方该点”,比如找到“确定”按钮、找到聊天列表入口、找到输入框并粘贴文字。
它们组合起来的典型流程就是:AppleScript 激活目标应用 → 获取基础窗口状态 → 截图 → OCR 或模板匹配定位目标 → 鼠标点击 / 键盘输入执行操作。这种分层方式,比单纯依赖 AppleScript UI scripting 要稳得多,也更容易写成可复用的通用 Skill,是 MacOS 桌面自动化的最佳实践之一。
七、写在最后
这个 Skill 已经准备好投入使用。如果你在使用过程中有任何想法或发现了可以改进的地方,非常欢迎交流反馈。这套方案会在实践中不断完善,致力于成为 MacOS 桌面自动化领域的高效工具。
