AppleScript 操控 Chrome 给 AI 发消息:一个 macOS 菜单栏工具的技术复盘

AI摘要
本文介绍了一款名为GroAsk的macOS菜单栏AI启动器开发过程。作者针对频繁启动AI应用的需求,使用Swift和AppleScript开发了该工具,通过全局快捷键唤起输入框并直接向AI发送消息。文章详细说明了技术架构、Web与CLI通道实现、全局快捷键注册及开发中的难点与解决方案,属于技术实现类的知识分享。

背景

一个实际的技术需求:每天在浏览器里找 AI 标签页 50+ 次,在终端里 cd 路径启动 Claude Code 30+ 次。能不能用一个全局快捷键搞定所有 AI 的启动?

我用 Swift + AppleScript 做了个 macOS 菜单栏工具来解决这个问题。下面是完整的技术方案和踩坑记录。

最终产品叫 GroAsk,是一个 macOS 菜单栏的 AI 启动器。按 ⌥Space 全局唤起输入框,直接发消息给任意 AI。

技术方案

整体架构

纯 Swift + AppKit,没用 SwiftUI @main(菜单栏应用用 SwiftUI 生命周期有坑),没用 Electron。SPM 管理依赖。

入口是 main.swift 手动创建 NSApplication,通过 AppDelegate 注册全局快捷键。

Web AI 通道

核心思路:AppleScript 操控 Chrome 浏览器。

流程:用户输入消息 → Router.swift 判断当前通道类型 → WebManager.swift 构建 AppleScript 异步队列 → 定位或创建 Chrome 标签页 → WebScriptGenerator.swift 生成针对目标网站的 JS 注入脚本 → 填入文本并模拟发送。

踩坑点:

  • AppleScript 异步队列。 AppleScript 执行是阻塞的,多个操作串行执行容易卡 UI。用异步队列包装,确保主线程不阻塞。
  • 各 AI 网站 DOM 差异大。 ChatGPT、Claude、Gemini 的输入框、发送按钮选择器都不一样,需要为每个站点维护独立的注入脚本。DOM 结构一更新就得跟着改。
  • Chrome 标签页状态同步。 需要判断目标标签页是否已打开、是否已加载完成,处理各种边界情况。

CLI 通道

核心思路:AppleScript 操控终端应用。

TerminalBridge.swift 负责桥接。支持 Terminal.app 和 iTerm2。用户在图形界面选择项目目录后,自动拼接 cd /path && claude 命令发送到终端执行。

踩坑点:

  • 终端别名自动补全。 用户可能在 .bashrc.zshrc 里定义了 claude 的别名,需要检测并处理。
  • 路径中的特殊字符。 空格、中文、引号等都需要正确转义。

全局快捷键

通过 CGEvent.tapCreate 注册系统级事件监听,拦截 ⌥Space 组合键。需要辅助功能权限(Accessibility)。

通道配置

所有 AI 通道的定义放在 Channel.swift,配置从 config.json 生成。新增一个 AI 通道只需要加配置项 + 写注入脚本,不需要改架构。

开发效率

整个项目从零到上线两周,代码基本由 Claude Code 生成。我的角色更像产品经理:定义需求、验证结果、处理边界情况。一个人覆盖了 Swift 客户端、Cloudflare Workers 后端、静态官网、Apple 签名公证全链条。

现状

目前完全免费,macOS 专属,已迭代接近 30 个版本。


下载不到 5MB,免费使用:groask.com/zh/

AppleScript 异步队列和 Chrome 标签页状态管理这块坑不少,有做类似自动化的朋友欢迎评论区交流方案。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 2
yangweijie

记得applescript 也能实现gui ,之前让ai 实现php gui的时候,ai 写了一版 applescript 运行的gui

2天前 评论

对,AppleScript 确实有 display dialogchoose from list 这些原生 GUI 能力,做简单交互完全够用。GroAsk 最终选了纯 Swift + AppKit 做界面,主要是需要自定义的交互(输入框联想、通道切换等),AppleScript GUI 的定制空间比较有限。项目里 AppleScript 专门负责"操控 Chrome 和终端"这块自动化,各司其职。PHP GUI 用 AppleScript 跑这个思路挺有创意的,AI 找了个最短路径哈哈

1天前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!