没有 DOM · 没有无障碍树 · 没有浏览器界面

让你的编程 Agent
看见 macOS。

Plumshot 让 AI Agent 能截取并标注原生 macOS 的窗口、菜单、Sheet 和菜单栏 —— 这些界面没有 DOM、没有无障碍树,Playwright 和浏览器工具都看不见。它就在你的 Agent 旁边本地运行:无需账号、无需 token、没有任何上传。

macOS 14 Sonoma 或更高版本屏幕录制权限Node ≥ 18100% 本地处理

MyApp — 偏好设置capture_window → annotate

你的 Agent 交回来的东西 —— 一张画好标注的 PNG,而不是一段像素坐标。

截图变成一场对话

Loop A

Agent 展示给你看

你的 Agent 抓取一个窗口,画上红框和箭头、给问题标上编号,然后交回一张标注好的 PNG —— 而不是一段像素坐标。小尺寸截图和所有标注都以 base64 PNG 内联返回,视觉 Agent 一次调用就能看到结果。

capture_window → annotate → 给人看
Loop B

你展示给 Agent 看

你自己在截图上做标记 —— 用 Plumshot、预览,什么都行 —— 你的 Agent 直接读懂这些标记。你画的圈、箭头和批注就是指令。不用截屏,不需要权限。

你来标注 → Agent 读取 PNG → Agent 执行

选你顺手的方式驱动

无头 CLI

plumshot …

适合从 shell 或非 MCP 脚本驱动。每次截取都输出 JSON:{ path, width, height, bbox }。CLI 就是签过名的 Plumshot.app 二进制。

stdio MCP 服务器

MCP 客户端默认方式
plumshot-mcp

零依赖的 stdio 服务器(server.mjs,Node ≥ 18)。最适合在 Claude Code、Codex 或 Cursor 里使用。小图以 base64 PNG 内联返回,大图返回文件路径。

Claude Code 技能 + 插件

/plugin install plumshot

安装最省事,还自带「什么时候该用 Plumshot」的使用指引。一条 marketplace 命令同时装好 MCP 服务器和技能。

没有托管 URL、不联网、无需 API key —— 和所有云端 MCP 正好相反。你的截图永远不离开你的 Mac。

4 步给你的 Agent 装上眼睛

CLI 就是签过名的应用二进制:构建一次应用,任何客户端都能接上。

  1. 构建应用

    用 Apple Development 签名构建 Plumshot scheme —— 这样屏幕录制授权在重新构建后依然有效。

    ./scripts/run_dev.sh
  2. 把 CLI 加入 PATH

    ln -sf "$PWD/scripts/plumshot" /usr/local/bin/plumshot
  3. 授予屏幕录制权限

    系统设置 ▸ 隐私与安全性 ▸ 屏幕录制 → 启用 Plumshot → 重新启动应用。annotate 不需要任何权限。

  4. 验证

    plumshot doctor
      screen recording (TCC): granted ✓
      accessibility (AX):     not granted (optional)
      bundle id:              com.plumshot.app
      binary:                 …/Plumshot.app/Contents/MacOS/Plumshot

    接入客户端前再做一次冒烟测试:截一个窗口并列出可用目标。

    plumshot capture-window --app Finder --out /tmp/cap.png
    plumshot list-targets

接进你的客户端

跳到你用的客户端。每一段的收尾仪式都一样:运行 plumshot doctor。

Claude Code

最省事的方式 —— 安装插件(MCP 服务器和技能一起装好):

/plugin marketplace add .
/plugin install plumshot

或者自己注册 MCP 服务器 —— 在仓库根目录放一个 .mcp.json

{
  "mcpServers": {
    "plumshot": {
      "command": "node",
      "args": ["mcp/plumshot-mcp/server.mjs"]
    }
  }
}

……或者用 CLI 一行搞定:

claude mcp add plumshot -- node mcp/plumshot-mcp/server.mjs

然后运行 plumshot doctor(或 doctor 工具),确认能找到 CLI、屏幕录制权限已授予。

OpenAI Codex

把服务器加进 ~/.codex/config.tomlserver.mjs 要写绝对路径

[mcp_servers.plumshot]
command = "node"
args = ["/Users/you/Documents/GitHub/Plumshot/mcp/plumshot-mcp/server.mjs"]

[mcp_servers.plumshot.env]
PLUMSHOT_APP = "/Applications/Plumshot.app"

env 一节是可选的 —— 如果你的开发构建能自动定位,删掉即可。

然后运行 plumshot doctor(或 doctor 工具),确认能找到 CLI、屏幕录制权限已授予。

Cursor

把服务器加进 .cursor/mcp.json(项目级)或 ~/.cursor/mcp.json(全局),使用绝对路径:

{
  "mcpServers": {
    "plumshot": {
      "command": "node",
      "args": ["/Users/you/Documents/GitHub/Plumshot/mcp/plumshot-mcp/server.mjs"],
      "env": { "PLUMSHOT_APP": "/Applications/Plumshot.app" }
    }
  }
}

然后运行 plumshot doctor(或 doctor 工具),确认能找到 CLI、屏幕录制权限已授予。

其他 MCP 客户端

任何 MCP 宿主都可以通过 stdio 启动服务器 —— 指向:

node mcp/plumshot-mcp/server.mjs

如果不是默认构建,在宿主的 env 配置里设置 PLUMSHOT_APP(.app 路径)或 PLUMSHOT_BIN(完整二进制路径)。

屏幕录制是唯一的门槛

Plumshot 只需要一个 macOS 权限 —— 屏幕录制 —— 供各截取工具使用。不需要「辅助功能」(滚动截图的自动滚动除外),不需要完全磁盘访问,并且不发出任何网络请求

  • 截图是本地文件,是否分享由你决定 —— 不会上传任何内容。无需账号,无需 token。
  • annotate 完全不需要权限 —— 它只在你已有的 PNG 上合成图形。只有 capture_* 工具会触碰屏幕。
  • ≤ 5 MB 的图片以 base64 PNG 内联返回,更大的返回文件路径。capture_full 和 capture_scrolling 有意始终只返回路径。
  • capture-scrolling 的自动滚动还需要「辅助功能」权限 —— 用 plumshot doctor 检查,或者传 --no-auto-scroll 自己滚动。
  • 分享前先遮盖:用 blur 形状盖住敏感信息(style 设为 blackOut 可彻底遮盖)再把图交出去。

9 个 MCP 工具

所有坐标以左上角为原点、图片像素为单位。每次截取还会输出 JSON 信封:{ path, width, height, bbox }。

工具参数返回
capture_regionx, y, w, h(必填),display?(默认 0)内联 PNG + 路径
capture_windowapp(必填,子串匹配),window?(标题)内联 PNG + 路径
capture_previous_region内联 PNG + 路径 · 重复上次区域
capture_fulldisplay?(默认光标所在屏)仅路径(图较大)
capture_scrollingx, y, w, h(必填),display?(默认 0),max_seconds?(默认 30)仅路径 · 需要辅助功能权限
annotateimage(路径),shapes(数组或 {shapes:[…]}),out?内联 PNG + 路径 · 无需权限
capture_textinput?(PNG 路径)| x, y, w, h | app + window?;keep_linebreaks?(默认 true)JSON { text, chars } · 端侧 OCR
list_targetsJSON { displays, windows }
doctor权限与签名状态

标注是一份声明式形状描述

不用鼠标、不开 GUI —— 你的 Agent 用 JSON 写出箭头、方框、文字与遮盖。

shapes(左上角原点,图片像素)
{ "shapes": [
  { "type": "box",       "x": 980, "y": 60, "w": 260, "h": 96,
                         "color": "#FF3B30", "lineWidth": 3, "filled": false },
  { "type": "arrow",     "from": [880, 200], "to": [1000, 110] },
  { "type": "text",      "x": 700, "y": 210, "text": "label is clipped", "fontSize": 30 },
  { "type": "number",    "x": 1110, "y": 108, "n": 1 },
  { "type": "highlight", "x": 120, "y": 320, "w": 400, "h": 28 },
  { "type": "blur",      "x": 60, "y": 60, "w": 300, "h": 40,
                         "style": "pixelate|secureBlur|smoothBlur|blackOut" }
] }

默认值:颜色 #FF3B30(红),lineWidth 3,文字 fontSize 28,数字标记 36,模糊 pixelate。通过 --shapes -(stdin)或 --shapes file.json 传入。Retina 屏上直接用 Plumshot 输出的像素数值 —— 它们已经是设备像素。

实际该怎么说

感受收益最快的方式 —— 这些提示词与上面两个循环一一对应。

Loop A —— Agent 展示给你看

  • 截取 MyApp 的偏好设置窗口,告诉我保存按钮的文字有没有被截断。
  • 截取设置 Sheet,在坏掉的文字上画红框加箭头、标上数字 1,然后给我看。
  • 对这个列表做一次滚动截图,检查底部几行是否正常渲染。

Loop B —— 你展示给 Agent 看

  • 读一下 ~/shot.png —— 我画了箭头指出要修的地方。照着箭头做。
  • 这是我标注过的截图;1 号框指的是什么?

预热

  • 运行 plumshot doctor 和 list-targets,然后截取 MyApp 的前台窗口。

什么时候该用 Plumshot

用 Plumshot 处理

  • 原生 AppKit/SwiftUI 窗口
  • NSMenu 与菜单栏
  • Sheet、警告框与 Popover
  • 自绘视图与画布
  • 拖拽预览、红绿灯按钮间距
  • 任何没有可靠无障碍树的界面

这些场景请用别的

  • Web 界面 → Playwright / 浏览器 MCP(有 DOM、console、network)
  • 纯文字提取 → capture_text 直接读出文字(端侧 OCR) —— 比把像素喂给视觉模型更省
  • 没有显示器或屏幕录制授权的无头 CI
  • 亚像素级对比 → 先截取,再用图像工具做 diff

原生 macOS 的典型故障

拿不准就重跑 plumshot doctor —— 它是万能的「到底行不行」检查。

也为 Agent 阅读而生

服务端渲染,另附机器可读的孪生文档,Agent 可以直接抓取。

Agent 索引

/llms.txt

按 llms.txt 约定整理的精炼索引:三种接入方式、两个循环,以及「什么时候该用 Plumshot」的说明。

Markdown 孪生页

/agents.md

本页的纯 Markdown 版本 —— Agent 抓取后拿到的是可解析的配置和命令,而不是渲染过的 HTML。

Claude Code 技能(plugins/plumshot/skills/plumshot/SKILL.md)内置了同一份「什么时候该用 Plumshot」指引,你也可以把它放进 AGENTS.md.cursor/rules

让你的 Agent 直面像素。

构建一次,一分钟接好客户端,让你的 Agent 看见浏览器工具够不到的原生界面。

完全本地无需账号无需 tokenNode ≥ 18