关于 hunch
Hunch 是用于控制 macOS 原生应用、浏览器、文件及其他本机功能的 MCP 服务和 Python 库。分层控制方式优先采用后台、无需切换焦点的操作;无法通过辅助功能处理时,可使用需确认的截图备用方式。
主要功能
- 01后台控制 Mac 原生应用
- 02基于辅助功能读取和操作 UI
- 03通过 AppleScript 和系统 API 操作文件
- 04通过 Safari 扩展或 CDP 控制浏览器
- 05对高风险或抢占焦点的操作设置确认
适用场景
- 01自动处理已登录的 Mac 应用任务
- 02在不中断前台工作的情况下检查 UI
- 03在后台执行浏览器工作流
- 04通过 Python 脚本控制 Mac
MCP 相关
作为本地 stdio MCP 服务由 MCP 主机启动,提供 macOS 应用、辅助功能、文件和浏览器控制工具。相同的操作原语也可通过其 Python 库使用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Hunch
通过任何大模型操控 Mac:无需占用焦点,在后台运行,并通过 MCP 操作。
Hunch 是一个 MCP 服务,让大模型 Agent 能够直接操作你的 Mac:你安装的应用、已登录的会话和文件,而且不会接管你的屏幕。当你继续在前台工作时,Agent 可以读取后台应用的界面、点击其中的按钮、通过 AppleScript 操控 Mail 或 Music、填写网页表单,或移动文件。它适用于真正的原生应用,而不只是浏览器。
与现代大模型搭配效果最佳。 Hunch 附带详细的操作手册,作为 MCP 服务说明;能力较强的工具调用型模型(Claude Sonnet/Opus 级及以上)能够很好地遵循。较小的模型可能会选择不够理想的方式(使用屏幕截图和按键操作,而不是读取界面树并点击)。
四个层级
Hunch 始终优先使用最直接的层级。这样速度更快、可靠性更高,而且(最后一层除外)不会触碰你的屏幕:
| 层级 | 工具 | 用途 |
|---|---|---|
| OS-API | trash file_op open_file clipboard_* launch_app … | 通过直接 API 调用处理文件、剪贴板和应用生命周期 |
| AppleScript | applescript | 可脚本化的应用:Mail、Messages、Notes、Calendar、Music、Finder、Safari … |
| Web | web_open web_snapshot web_act web_login … | 通过内置扩展操控 Safari,或通过 CDP 在后台操控 Chromium/Electron |
| 辅助功能 | snapshot act | 任意原生应用的界面:读取界面树、按引用点击/选择/输入 |
对于辅助功能树确实为空的应用,还提供了一个需要确认的最后手段(screenshot + 坐标点击/按键操作)。它会抢占焦点,因此会先征求你的同意。
如需在 Safari 中进行不占用焦点的视觉操作,可通过 web_open(..., app="Safari", new_window=True) 打开一个由扩展管理的专用窗口。web_screenshot 可截取该后台窗口的图像,而 web_act 可使用返回的像素坐标进行操作,不会移动共享鼠标、键盘或前台窗口。扩展仍不可或缺:它负责管理隔离的 Safari 窗口,并分发实体屏幕截图无法执行的渲染进程本地操作。
工作原理(无服务端,无云端)
称它为“MCP 服务”还不足以体现它的本地化程度。hunch serve 是一个普通的 Python 进程,由你的 MCP 宿主(Claude Desktop、Cursor、…)作为子进程启动,并通过 stdin/stdout 上的 JSON-RPC(MCP 的 stdio 传输)与之通信。它没有 HTTP 端点、没有监听端口、没有守护进程,也没有遥测。宿主退出时,Hunch 也随之退出。
这些工具会在进程内直接调用 macOS API:通过 pyobjc 调用辅助功能框架、通过 osascript 调用 AppleScript、通过操作系统 API 处理文件/剪贴板、通过本地 WebSocket 连接 Chromium 的 DevTools 端口,以及通过经过签名的本地 Safari 扩展桥接程序。可选的 Safari 配套程序仅使用经过身份验证的环回连接,将输入的命令转发给 Apple 沙盒中的扩展。浏览流量仍由所选浏览器发出。模型能看到的内容仅限于工具经由宿主返回的内容;没有其他信息会离开这台设备。
基准测试
Hunch 在真实且已登录的 Mac 上,与其他 macOS 计算机操作 Agent 进行比较,测试项目为
mac-agent-bench——同一个大脑,不同的操作方式:
每项任务都使用相同的 claude -p,只有 MCP 适配器不同。它通过程序化检查器评估任务成功率,还会衡量干扰程度:Agent 工作时对光标和前台窗口的影响有多大。
在 5 项复杂的多步骤任务中(n=3):
| 工具 | 成功率 | 成本 | 干扰(焦点·光标) | 超时 |
|---|---|---|---|---|
| Hunch | 15/15 | $1.52 | 1·0 | 0 |
| Peekaboo | 13/15 | $14.60 | 22·16 | 2 |
| cua-driver | 15/15 | $17.70 | 22·0 | 0 |
可靠性完美,成本约低 10 倍,速度快约 5–10 倍,而且几乎从不触碰你的屏幕(15 次试验中光标移动为 0 次,焦点切换为 1 次)。完整的方法说明和逐项任务表格见
基准测试仓库。
安装
macOS 13+。从 PyPI 安装(发行包为 hunch-sdk;导入模块和 CLI 均为 hunch):
pipx install hunch-sdk # or: pip install hunch-sdk
pip install 'hunch-sdk[subscription]' # + the agent loop on Claude (provider="claude")
pip install --pre 'hunch-sdk[codex]' # + the agent loop on OpenAI Codex (provider="codex")
也可以通过 Homebrew 安装——如果你不管理 Python 环境,这是最好的选择;它会在稳定路径下附带一个隔离的 Python 环境,让 macOS 权限授权最可预测:
brew install prithviseran/hunch/hunch
然后,只需执行一次:
hunch setup # walk the macOS permission grants
hunch doctor # verify every layer; fix anything it flags
hunch connect claude-desktop # or: claude-code, cursor
重启你的 MCP 宿主,并让它“使用 hunch 来……” 。
坦诚说明权限
macOS 信任的是运行服务的应用,也就是你的 MCP 宿主(Claude Desktop、
Cursor 或你的终端),而不是“hunch”本身。hunch setup 会引导你完成设置:
- 辅助功能(必需):允许 Hunch 读取应用界面,并在不获取焦点的情况下点击。在“系统设置”→“隐私与安全性”→“辅助功能”中,为你的 MCP 宿主应用授予权限。
- 自动化(按应用授权,自动提示):Hunch 首次对某个应用执行脚本操作时,macOS 会显示一次性的 “允许控制”提示。
- 屏幕录制(可选):仅用于屏幕截图/视觉回退方案。
hunch doctor 会报告已授予的权限。注意:其中“辅助功能”一项反映的是你运行该命令所用的终端权限;服务继承的是宿主的授权。
Python SDK(库用法)
Hunch 也可以作为可导入的库使用——它提供与 MCP 工具相同、不会抢焦点的基础操作,可通过你自己的 Python 程序(定时任务、测试框架或自定义 Agent 循环)确定性地驱动,无需大模型。发行包名为 hunch-sdk;导入名为 hunch:
from hunch import Hunch
mac = Hunch() # your machine, your logged-in apps
print(mac.snapshot("Mail")) # accessibility tree, focus-free
mac.act([{"action": "click", "ref": "e12"}])
mac.web.open(url="https://github.com") # real persistent Chrome profile over CDP
mac.web.open(url="https://github.com", app="Safari") # user's Safari session via extension
print(mac.web.snapshot())
mac.files.trash(["~/Downloads/old.zip"]) # reversible delete, no Finder
mac.applescript('tell application "Music" to play')
构造参数:app(初始快照的目标)、confirm="dialog"|"off"(见下文)、check_permissions(预先检查辅助功能权限)、simultaneous(绝不触碰前台、光标或键盘)、cdp_port。
要在 Chromium/Electron CDP 会话中显示悬停菜单或工具提示,请使用最新 web_snapshot 中的 ref:
mac.web.act([{"action": "hover", "ref": "e12"}], detailed=True)
print(mac.web.snapshot()) # verify the revealed UI and get fresh refs before clicking
MCP 中的对应操作是使用相同动作的 web_act。悬停会发送渲染器本地的鼠标移动事件,不会点击、激活应用或移动 Mac 光标。除非明确的后置条件验证了所请求的字段,否则其回执为 performed_unverified。Safari 会返回不支持(详细调用会以 blocked 返回,且尝试操作数为零);原生 act 不提供悬停功能。
- 权限:对于库用法,需要辅助功能权限的是运行脚本的程序——也就是你的终端或 IDE(而 MCP 服务使用宿主应用的授权)。构造函数会检查权限,若未获授权则会抛出
AccessibilityNotGranted并提供操作说明。screenshot()还需要屏幕录制权限。 - 安全门默认开启:与 MCP 服务一样,默认启用单击一次的“继续”对话框和
~/.hunch/config.json安全门。Hunch(confirm="off")仅对此实例自动批准——用于无人值守脚本时,注意事项与auto_approve_all相同。 - 错误:方法会返回状态字符串(检查是否为
REFUSED);SDK 仅会抛出ApprovalDenied(用户拒绝了对话框)、AccessibilityNotGranted、WebNotOpen(在调用.web.open()前使用.web)、StaleRef(重新获取快照),以及HunchError(无法打开 CDP 浏览器;调用web.restart()可恢复过期实例)。 - 凭据:
mac.web.fill_login(service)/fill_secret(service, ref)会将 Keychain 中的值直接输入页面,且绝不会返回这些值;系统会强制执行域名绑定。 - 共存:SDK 和 MCP 服务共用 CDP 端口(9337)和持久化的 Hunch 浏览器配置文件——无论谁先打开,都会复用已打开的实例;但
web.restart()/web.login()会终止占用该端口的任何程序。
可运行的脚本位于 examples/。
Agent 循环(mac.agent)
实例 SDK 提供确定性的基础操作。Agent 循环让大模型掌舵:你用通俗英语交给它一项任务,它就通过这些相同的基础操作来驱动 Mac——在你的机器上,使用你已登录的应用。构造时选择一次提供商——Anthropic Claude 或 OpenAI Codex——此后所有操作都与提供商无关。这是可选的额外组件(基础安装无需包含大模型 SDK):
pip install 'hunch-sdk[subscription]' # Claude
# or, for Codex (the SDK is beta): pip install --pre 'hunch-sdk[codex]'
python -c 'import hunch; hunch.provider("claude").login()' # sign-in (browser OAuth) — no API key
from hunch import Hunch
mac = Hunch(provider="claude") # or Hunch(provider="codex")
result = mac.agent.run("reply to Sarah's latest email, but don't send it")
print(result.text) # the model's final summary
print(result.turns, result.usage)
登录
身份验证是明确的、限定提供商的功能——不会静默搜寻任何信息。你只需选择一次服务商,之后便可使用同一组不带前缀的方法:
mac = Hunch(provider="codex") # or "claude" (the default)
mac.login() # codex: ChatGPT browser sign-in · claude: Claude sign-in
mac.status() # -> AuthStatus(provider, logged_in, method, email, plan)
mac.logout()
mac.agent.run(task) # runs on the configured provider
也可以独立使用身份验证,无需 Mac 实例(例如,在引导脚本中):
import hunch
st = hunch.provider("codex").status()
if not st.logged_in:
hunch.provider("codex").login() # browser OAuth (blocks until done)
# headless/remote box instead:
# h = hunch.provider("codex").device_login()
# print(h.verification_url, h.user_code); h.wait()
| 服务商 | 登录方式 | 费用 |
|---|---|---|
claude | mac.login() / hunch.provider("claude").login() — 使用与 Claude Code 相同的浏览器 OAuth。已经在这台 Mac 上登录 Claude Code?那就完成了;Hunch 会复用该登录状态。 | 你的 Claude 套餐(无按 Token 计费) |
codex | mac.login() / codex login — 通过浏览器登录 ChatGPT/Codex。 | 你的 ChatGPT/Codex 套餐 |
两者都通过订阅/登录运行——不会开放按量计费的 API 密钥。如果没有有效登录,run() 会显示错误并提示你返回 login()——绝不会擅自猜测。
- 查看运行过程:使用
on_event(kind, data)回调——kind可以是text(推理过程)、tool({name, input})、tool_result(预览)、done(最终文本)、error。 - 延续对话:后续调用
run()会保留对话(模型仍记得 Sarah 的电子邮件地址);mac.agent.reset()会开始一项新任务。 - 自由组合不同层:在
mac.agent.run(...)前后确定性地调用mac.snapshot(...)/mac.clipboard.get()——这是云端沙箱无法在你的真实设备上做到的事。 - 参数:
run(task, model=None, max_turns=40, effort=None, on_event=None, system_suffix="")—model=None会使用该服务商自己的默认模型。AgentResult包含text、turns、stop_reason、usage、aborted。 - 安全性:循环由实例的门控配置控制。默认的
confirm="dialog"会在任何可能抢占焦点或有风险的步骤前弹出真实的“继续?”对话框——适合你守在设备旁时使用,但受门控的操作可能会因等待对话框超时而卡住无人值守的运行。对于 cron 作业,请使用Hunch(confirm="off")并接受相应风险;对于不可逆或会影响外部的操作,模型仍会通过notify_user先征求你的同意。被拒绝的门控操作会返回REFUSED结果,因此循环会调整处理方式,而不会崩溃。 - 费用:运行会占用你所用服务商套餐的使用额度——没有按 Token 计费。
max_turns用于限制运行轮数。
Codex 说明:
codex服务商会驱动 OpenAI Codex Agent,通过 MCP(一个独立的hunch serve进程)使用 Hunch 的工具,因此,对于危险动词的审批会使用 Hunch 自己的点击批准对话框,而不是宿主提供的can_use_tool回调。
其他模型:实例 SDK 的基础功能与服务商无关——你可以将 mac.snapshot() /
mac.act() 接入自己的 OpenAI/Gemini 等 Agent 工作流,将它们用作工具。
基于 Hunch 构建应用
SDK 以开发者为先:**语义统一,一切归实例所有,除非你主动选择,否则不使用任何环境级配置。**上面的 MCP 服务本身就是基于它构建的第一个应用——它的“个人”行为(~/.hunch/config.json 策略、“Hunch”品牌对话框、共享浏览器配置文件)不过是构造函数参数。
from hunch import Hunch, ConsentRequest, OAuthToken
mac = Hunch(
provider="claude", # which LLM vendor drives mac.agent ("claude" | "codex")
app_id="com.acme.mailbot", # pure namespacing — own Keychain slots, browser
# profile, and CDP port; never a behavior switch
app_name="Acme Mailbot", # what consent dialogs + notifications say
confirm=my_consent_callback, # ConsentRequest -> bool, rendered in YOUR UI
notify=my_toast_handler, # callback, or True for native macOS banners (default: off)
policy={"gates": {"shell": True}}, # instance-owned safety; the user's personal
# config can never disarm your app
auth=OAuthToken(token), # the exact Claude subscription token YOUR app manages
can_use_tool=my_approver, # optional: route every tool through your Approve/Deny UI
)
这样做的好处:
- 共存 — 使用不同
app_id的两个应用会获得互不相通的 Keychain 服务、凭据存储、浏览器配置文件和 CDP 端口。它们无法读取彼此的登录信息、将彼此登出,或终止彼此的浏览器会话。这是结构上的隔离,而非约定俗成。 - 你的品牌,你的 UX — 每个对话框、拒绝消息和通知都会显示你的
app_name;confirm=和notify=会通过你的应用处理同意确认和提醒,而不是使用 osascript 对话框和 macOS 横幅通知。故障的同意回调会默认拒绝。 - 隔离的安全策略 — 机器上的
hunch config(以及HUNCH_NO_INTERNAL_GATE)只管理个人 MCP 服务,不会影响你的实例。 - 明确的身份验证 — 使用
provider="claude"和auth=hunch.OAuthToken(...)时,会严格使用指定的订阅令牌(repr 会进行脱敏),因此你的应用绝不会在用户不知情的情况下使用最终用户自己的 Claude 登录信息。(codex提供方通过mac.login()/codex login进行身份验证。)
程序化凭据管理使用相同的命名空间:hunch.creds.set_credential(name, user, pw, namespace=your_app_id) 等。可运行的示例见
examples/embedded_app.py。
凭据:Agent 使用它们,但永远看不到它们
hunch creds add github --domain github.com
hunch creds list
凭据值会直接写入 macOS Keychain。Agent 只需调用 web_fill_login("github"),并提供服务名称即可登录;Hunch 会从 Keychain 读取机密,并通过 CDP 将其输入网页。该值绝不会进入模型上下文、模型日志或模型提供方的服务器。
域名绑定:使用 --domain github.com 添加的凭据只会输入到 github.com 及其子域名。如果被误导或遭提示词注入的 Agent 进入了仿冒页面,填充操作会被拒绝。请为每项凭据绑定域名;空白(适用于任何网站)仅为兼容性保留。
如果没有已存储的凭据,Agent 会改用 web_login,打开一个带标记的浏览器窗口,由你亲自登录;之后会话会保存在 Hunch 专用的浏览器配置文件中。
确认关卡
MCP 宿主的工具审批是主要权限层。Hunch 增加了一个了解内容的第二道关卡:一键式 macOS 对话框,用于处理灾难性操作:
| 关卡 | 触发条件 |
|---|---|
gates.focus_steal | 接管键盘/光标的操作(key、click_xy、未指定引用的输入) |
gates.app_to_front | 将应用置于前台(切换焦点,即使处于全屏状态) |
gates.shell | 含有 do shell script 的 AppleScript |
gates.destructive_applescript | 删除/发送/清空废纸篓/关机/…… |
一次审批涵盖后续操作:点击“继续”(在 request_focus、受关卡限制的 act 或应用置于前台对话框中)后,会在约 15 秒内授权其所提示的切换:不会再弹出第二个对话框,也会抑制焦点切换通知。切换要么询问过,要么通知过,绝不会两者兼有,也绝不会静默发生(关闭 gates.app_to_front 后,切换会改为发送通知)。
默认全部开启。对于 MCP 服务,可通过 hunch config show/hunch config set gates.shell off 调整;更改会立即生效,即使服务正在运行也一样。auto_approve_all 会关闭所有关卡,并要求你确认已了解相关风险。
对于 SDK 实例,关卡由实例管理:Hunch() 默认开启所有关卡,且不会读取配置文件——传入 policy={"gates": {...}}、callable(category) -> bool,或 policy="personal",即可为自己的脚本启用实时读取配置文件的行为。
Hunch 还会禁止 Agent 通过文件工具编辑 ~/.hunch/ 下的任何内容(其自身的策略和凭据元数据);权限更改须由人在终端中进行。
环境变量
| 变量 | 作用 |
|---|---|
HUNCH_NO_INTERNAL_GATE=1 | 禁用所有内部对话框(适用于有自有审批体验的宿主应用) |
HUNCH_FORCE_SANDBOX=1 | Web 层使用一次性、未登录的浏览器配置文件 |
HUNCH_NOTIFY_FOCUS=0 | 静默“Hunch 正在切换应用”通知(仅当切换未触发对话框时才会发送) |
面向用户的桌面通知默认关闭。如需为个人 MCP 服务启用,可运行 hunch config set notifications.user_attention on。SDK 应用可传入 notify=True 以显示原生 macOS 横幅通知,或传入 notify(message, title) 回调以接入自有 UI;默认禁用。
常见问题
每次读取树结构都返回“(no window for …)”,且 AppleScript 报错“-25211 not allowed assistive access”。 一个可能的原因是,托管 Hunch 的应用缺少 辅助功能 权限。 没有此权限时,AX API 会静默返回空结果,因此即使应用已打开,也会看起来没有窗口。 请向宿主应用授予权限(见下一个问题);如果它已列在权限列表中,请将其关闭后再重新开启: macOS 会在应用更新时静默撤销权限。之后重启宿主应用。
应该向哪个应用授予权限? 启动 hunch serve 的应用:Claude Desktop、
Cursor 或你的终端应用(用于 Claude Code)。权限与该应用的身份绑定,而不是与
“hunch”本身绑定。这也是 hunch doctor 可能会产生误导的原因:它报告的是运行该命令的终端所拥有的权限,这些权限可能与 MCP 宿主应用的不同。
只有 screenshot 失败;其他功能都正常。 这是 屏幕录制 权限的问题,只有截图/视觉回退方案需要此权限。请在“系统设置”→
“隐私与安全性”→“屏幕录制”中向宿主应用授予权限,或者直接让 Agent 使用不需要此权限的 snapshot。
昨天还能用,今天却不行了。 宿主应用(或 macOS)更新后很可能重置了权限。请在“辅助功能”(以及使用屏幕录制时的“屏幕录制”)中关闭宿主应用的权限后再重新开启,然后重启宿主应用。
某个应用读取到的树结构为空,或只显示侧边栏。 覆盖范围取决于操作、进程、权限和窗口状态。snapshot 不会重启应用。使用
app_target 检查确切的进程/窗口,然后使用 app_capabilities 检查受限的恢复选项。app_recover 可以执行已获授权的辅助功能或调试恢复操作。
请验证操作结果;树结构为空并不能证明应用没有 AX。
无法连接 Web 层。 Chrome 136+ 会阻止在默认配置文件上使用 CDP 调试端口,因此
Hunch 会驱动自己的 Chrome(数据目录与日常使用的 Chrome 分开,位于 ~/.hunch/chrome-cdp),而不是你日常使用的 Chrome。
通过 hunch setup 或 web_login 将该配置文件登录到 Google 账号一次,Chrome Sync
便会同步你的登录信息;之后它就会一直保持登录状态。
对于 Safari,首次运行 hunch serve 时会安装已签名的伴侣应用,并提示你一次,在 Safari →“设置”→“扩展”中启用
Hunch 并授予网站访问权限。选择访问所有网站可减少提示;Hunch 仍会将每个操作绑定到确切的标签页、URL、来源和文档代次。Hunch 无法自行授予这些由 Apple 管理的权限。hunch setup
和 hunch doctor 也会完成相同的步骤。
我的宿主应用显示的服务说明被截断了。 这只是显示问题:某些宿主应用的界面会在服务器信息显示中缩短操作指南;模型收到的内容是完整的。
安全
请阅读 SECURITY.md:其中介绍了威胁模型(主要是提示词注入)、各项防护措施的覆盖范围与局限,以及漏洞报告方式。
项目状态
Hunch 目前作为个人开源项目维护。它可以控制 Mac 上的真实应用、文件、浏览器会话和凭据,因此请审查源代码、保持启用审批,并使用最小权限凭据。本软件按 “原样” 提供,不附带任何保证或条件,并遵循 Apache License 2.0。
许可证
Apache-2.0;请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。