让你的 AI Agent 在屏幕上绘制醒目的箭头、方框和文字
英文标题:🔶 Let your AI agents paint big arrows, boxes and text on your screen
bigarrow 是一款开源 MIT 许可的 macOS CLI 工具及 Agent skill,可让 AI Agent 在屏幕上以箭头、方框、圆环和提示文字指向需要用户操作的界面元素。它不会点击、输入或截屏,也不会抢占焦点;绘制本身无需 Screen Recording 或 Accessibility 权限,并支持多显示器、全屏应用、Stage Manager 和 Spaces。开发者可通过元素标签、窗口、坐标、矩形区域、鼠标位置或 Peekaboo 快照定位目标,并利用 JSON 输出和退出码将其接入 Claude Code、Codex 等 Agent 工作流。该项目强调将 2FA、权限授权、支付确认等必须由人完成的操作清晰地交还给用户,同时提供自动消失、语音提醒、跟随目标和点击结束等控制能力。
3.2 KB
310.3 KB
468.6 KB
118.5 KB
139.1 KB
149.3 KB
138.7 KB
176.8 KB
143.7 KB
164.5 KB
160.5 KB
368.3 KB
1.3 MB
935.6 KB
138.1 KB
中文
让你的 AI Agent 在屏幕上绘制醒目的箭头、方框和文字
big-arrow-on-the-screen(bigarrow):一个小巧的 macOS CLI 和一项 Agent skill。可点击穿透,绝不抢占焦点,会自行消失。MIT 许可。
你的 AI Agent 可以重构 monorepo、编写迁移脚本并解释单子,但当它需要你点击一个按钮时,却只能在你根本没在看的终端里输出 “请在对话框中点击 Allow”。
bigarrow给了它一根手指。
bigarrow point --element "Allow" --app "System Settings" --text "Franz, click Allow"
一个醒目、友好的箭头和提示牌会浮现在所有内容之上,指向目标,然后自行消失。它可点击穿透,绝不抢占焦点,适用于每一块显示器和每个 Space,绘制时完全不需要任何权限。它只是一个小型 Swift 二进制文件:没有守护进程、没有菜单栏图标、没有账户、没有遥测,而且我们检查了两遍,里面没有 AI。它就是一支箭头。
这东西实际有什么用?
问得好。箭头大约从旧石器时代起就存在了。变化在于:软件 Agent 如今会在你的 Mac 上完成实际工作,而它们不断撞上同一堵墙,那部分只能由人来完成。
- “点击 Allow。” macOS 权限提示、OAuth 同意页面、“使用什么应用打开?”对话框。Agent 能找到按钮,但不应当或无法替你按下。现在它可以指给你看。
- “轮到你了。” 2FA 验证码、CAPTCHA、Passkey、支付确认、签名、法律条款复选框。这些是 Agent 绝不该自行代为点击的内容。它指向目标,你来决定,然后它继续工作。
- “是这个窗口,不是那个。” 你开了 14 个 Chrome 窗口。Agent 知道它说的是哪一个:
--window "Google Chrome:Pull request"。它甚至能选中正确的标签页:--app "Google Chrome:Pull request"。 - “我需要你,而你正在煮咖啡。”
--say会朗读提示牌上的文字。你的 Mac 会直接把你叫回桌前。 - 引导式设置和上手流程。 一步一步带领用户完成设置面板操作:
start,等待用户操作,stop,再进入下一步。就像产品导览,只是没有产品。 - 远程协助。 “不,是_另一个_齿轮图标。”与其描述,不如直接指给对方看。
- 演示、录屏、文档。 录制时突出重点,或者通过
--png直接将箭头渲染进 PNG,用于文档。 - 调试坐标。 不确定 Accessibility、截图或 Peekaboo 坐标是否正确?指向它们,然后看一眼。
--dry-run --json会告诉你它_本来会_指向哪里,而不会实际绘制。
我们都经历过的场景
使用中性的演示对话框布景,并在干净的 CI runner 上以真实的 bigarrow 录制(BACKDROP_ARGS=--cover scripts/funny-scenes.sh)。对话框是假的,感受是真的。
|
---|---
| 
--color green | --shape zigzag --color orange
| 
--color purple | --close-button,因为最终决定权属于人类
| 
三次 start,一个按钮,零歧义 | --style box --corners sharp,外加一堂关于 macOS 权限的课
|
--shape spiral:围绕提示牌转一圈,然后指向按钮 |
它不是什么:给人类使用的屏幕标注工具、点击机器人或截图工具。它绝不点击、输入或捕获任何内容。它只负责指向。这是刻意的。
brew install franzenzenhofer/tap/bigarrow
bigarrow install-skill # 为 Claude Code (~/.claude/skills) 和 Codex (~/.agents/skills) 安装 skill
从源码构建:swift build -c release(Xcode 16 或更高版本、macOS 14 或更高版本),二进制文件位于 .build/release/bigarrow。
Agent 所需的三个命令
bigarrow point --element "Allow" --app "System Settings" --text "Franz, click Allow" # 按标签定位
bigarrow point --at 760,500 --text "Franz, click HERE" # 按坐标定位
bigarrow start --window "Safari:Inbox" --text "This window" && bigarrow stop # 直到停止
每一支箭头都会自行结束。无需有人在 Agent 忘记清理时收拾残局:
|
---|---
时间限制 | bigarrow point ... --duration 10(默认 8 秒;start 为 300 秒;--duration 0 = 不限时)
启动和停止 | bigarrow start ... 会立即返回;bigarrow stop(或 stop --all)会将其移除
Agent 离开 | 绘制箭头的 Agent 进程退出时,箭头会结束(CLAUDE_PID 或 BIGARROW_OWNER_PID)
人类作答 | 将 bigarrow stop --hook 作为 Claude Code 的 UserPromptSubmit hook,可清除该会话的箭头
人类关闭它 | --close-button 会在提示牌上添加一个可点击的 X(需主动启用)
目标指定方式包括:--at X,Y、--rect X,Y,W,H、--mouse、--window App[:title]、--element Label --app App、--peekaboo ID --snapshot see.json(来自 Peekaboo 的 see --json)。坐标采用全局左上角逻辑点,这也是 Accessibility、CGWindowList 和 Peekaboo 报告的坐标空间。--display N 会使 --at 和 --rect 相对于某一块显示器。
一支箭头会绑定到它所指向的应用。--app App[:window or tab title](或 --window)会先将该应用、窗口或 Chrome/Safari 标签页带到前台,因为指向隐藏在终端背后的窗口是一种特别无用的帮助;而当其他应用遮住目标时,箭头会隐藏,并在目标重新出现时回来。--no-raise 不会改动你的窗口。bigarrow elements --app X 会列出 --element 可匹配的项目。bigarrow doctor 会显示权限、持有权限的应用以及你的显示器信息。
每个命令均支持 --json。退出码:0 表示成功,2 表示输入错误,3 表示未找到目标,4 表示缺少权限。Agent 喜欢退出码。人类可以容忍它们。
这是一支箭头,因此我们在它的外观上花了不合理多的时间。
在干净测试机器上的真实截图:六种外观,分别置于白色、macOS 灰色、深色、黑色、红色和繁忙网页背景上:
--shape bend|straight|zigzag|spiral(当事情_真的_很紧急时可用 zigzag;spiral 会先围绕提示牌转一圈再指向目标,适用于必须让人无法错过的场景)--style arrow|ring|box;圆环和方框仅绘制边框,因此你依然能看到其下方内容--size S|M|L、--corners round|sharp--color red|orange|yellow|green|teal|blue|purple|pink|black|white|#RRGGBB--border shadow|white-black|black:默认是带投影的白色边框(在浅色箭头上则为深色);white-black会以白色边框外侧的一圈细黑边替代阴影;black则仅为细黑色轮廓- 每种颜色都可由你指定:
--border-color、--text-color、--edge-color,以及用于 X 的--close-color和--close-x-color。未指定时,每项会自行选择易读颜色 --close-button会在提示牌右端内部放置一个 X(白色圆形,X 为箭头颜色),不会遮住文字,也不会离开屏幕--follow可随窗口或元素移动,--until-click会在点击目标时结束,--say会朗读提示牌内容- 多支箭头同时出现时,会让各自的提示牌互不遮挡
箭杆从提示牌中通过一个外扩连接处延伸出来,绝不会撞上圆角。scripts/gallery.py 会离屏渲染所有组合,并放大检查每个连接处(连接处),因为显然,连接处的一条接缝也是不可接受的。
它需要 Screen Recording 或 Accessibility 吗? 绘制两者都不需要。--element、elements、--until-click 和 front --window 会使用 Accessibility,而 macOS 会将该权限授予运行 shell 的应用(Terminal、iTerm2、Ghostty、VS Code、Claude),而绝不是授予 bigarrow 本身。bigarrow doctor 会显示该应用的名称,退出码 4 则会准确告诉 Agent 应向你请求什么权限。--window App:title 需要读取窗口标题,而 macOS 26 在没有 Screen Recording 权限时会隐藏窗口标题;单独使用 --window App 则无需任何权限。
我打字时,它会抢走焦点吗? 不会。这是项目中最难解决的 bug:NSApplication.run() 会悄悄激活一个没有终端的进程,因此分离运行的箭头会抢走焦点。bigarrow 改为自行处理事件,并且测试确保前台应用永远不会改变。
我能点击穿过它吗? 可以,除了提示牌和箭杆:点击那里会移除箭头(鼠标指针悬停时它会稍微变暗,以此说明该行为)。点击目标,或箭头尖端附近任意位置,都会直接穿透并作用于应用。点击箭头绝不会获取焦点。
多显示器?全屏应用?Stage Manager?Spaces? 可以、可以、可以、可以。包括位于主显示器左侧或上方的显示器(负坐标)。如果在某支箭头所在的显示器上将其拔掉,箭头会礼貌地离开。参见验证矩阵。
一个呼吸动画箭头会占用多少 CPU? 在 CI runner 上测得为 1.4%。Core Animation 会在渲染服务器中完成相关工作。
--element 能在网页内部工作吗? 在 Electron 应用中可以。在 Chrome 中,仅当 Chrome 使用 --force-renderer-accessibility 运行(或 VoiceOver 已开启)时才可以;Chrome 会忽略用于暴露页面内容的常规请求,这一点已于 2026 年 10 月在 Chrome 上验证。Chrome 自身的工具栏始终可用。其他情况下,请指向页面坐标,skill 会对此加以说明。
为什么不直接使用[某个屏幕标注应用]? 那些是供人类在屏幕上绘画的工具。这是供程序从 shell 中、通过退出码来指向目标的工具。在写下一行代码前,项目检查了 26 种工具(研究)。没有一个能做到这一点。
它是 AI 吗? 不是。它是你的 AI 技术栈中最不智能的部分,并以此为傲。
- 87 项自动化测试:几何、布局、连接平滑度、黄金图像、录制的 window-server、Accessibility 和 Peekaboo 4.9.0 fixtures,以及针对真实 window server 的测试(窗口层级 1000、点击可穿透、焦点永不移动、分离和停止时序)。CI 在 macOS 15 上运行这些测试;它们也已通过 macOS 26 和 macOS 27。
- 在干净 runner 上执行 17 项行为检查(visual.yml):真实点击 X、
--until-click、--follow、前置窗口(以及--no-raise)、被遮挡时隐藏、选择 Chrome 标签页、随所有者进程结束、stop --hook、--say、全屏应用、Stage Manager、切换 Space、第二块显示器、2x 显示器、箭头显示期间拔掉显示器,以及 CPU。上方的演示 GIF 由同一个工作流录制,录制桌面上没有任何个人内容。 - 一份全新的 a
English / 原文
Let your AI agents paint big arrows, boxes and text on your screen
big-arrow-on-the-screen (bigarrow): one small macOS CLI and an agent skill. Click-through, never steals the focus, gone by itself. MIT.
Your AI agent can refactor a monorepo, write a migration and explain monads, but when it needs you to click one button it prints "please click Allow in the dialog" into a terminal you are not looking at.
bigarrowgives it a finger.
bigarrow point --element "Allow" --app "System Settings" --text "Franz, click Allow"
A big, friendly arrow with a sign appears on top of everything, points at the thing, and goes away again. It is click-through, it never steals your focus, it works on every display and every Space, and it needs no permission at all to draw. It is one small Swift binary. There is no daemon, no menu-bar icon, no account, no telemetry, and, we checked twice, no AI inside. It is an arrow.
What is this actually for?
Fair question. Arrows have existed since roughly the Paleolithic. Here is what changed: software agents now do real work on your Mac, and they keep hitting the same wall, the part that only a human may do.
- "Click Allow." macOS permission prompts, OAuth consent screens, "Open with...?" dialogs. The agent can find the button but must not, or cannot, press it for you. It can now point at it.
- "Your turn." 2FA codes, CAPTCHAs, passkeys, a payment confirmation, a signature, a legal checkbox. The things an agent should never click on its own behalf. It points, you decide, it continues.
- "It's this window, not that one." You have 14 Chrome windows. The agent knows which one it means:
--window "Google Chrome:Pull request". It even picks the right tab:--app "Google Chrome:Pull request". - "I need you, and you're making coffee."
--sayreads the sign aloud. Your Mac will literally call you back to your desk. - Guided setups and onboarding. Walk a human through a settings pane step by step:
start, wait until they acted,stop, next step. Like a product tour, minus the product. - Remote help. "No, the other gear icon." Point at it instead of describing it.
- Demos, screencasts, docs. Highlight what matters while recording, or render the arrow straight into a PNG with
--pngfor documentation. - Debugging coordinates. Not sure your Accessibility, screenshot or Peekaboo coordinates are right? Point at them and look.
--dry-run --jsontells you where it would point without drawing.
Situations we have all been in
Staged with a neutral demo dialog and recorded with the real bigarrow on a clean CI runner (BACKDROP_ARGS=--cover scripts/funny-scenes.sh). The dialogs are fake. The feelings are real.
|
---|---
| 
--color green | --shape zigzag --color orange
| 
--color purple | --close-button, because the human gets the last word
| 
three starts, one button, zero ambiguity | --style box --corners sharp, plus a lesson about macOS permissions
|
--shape spiral: once around the sign, then to the button |
What it is not: a screen annotator for humans, a click bot, or a screenshot tool. It never clicks, types or captures anything. It only points. Deliberately.
brew install franzenzenhofer/tap/bigarrow
bigarrow install-skill # teaches Claude Code (~/.claude/skills) and Codex (~/.agents/skills)
From source: swift build -c release (Xcode 16 or newer, macOS 14 or newer), binary at .build/release/bigarrow.
The three commands an agent needs
bigarrow point --element "Allow" --app "System Settings" --text "Franz, click Allow" # by label
bigarrow point --at 760,500 --text "Franz, click HERE" # by coordinate
bigarrow start --window "Safari:Inbox" --text "This window" && bigarrow stop # until stopped
Every arrow ends by itself. Nobody has to clean up after an agent that forgot:
|
---|---
Time limit | bigarrow point ... --duration 10 (default 8 s; start 300 s; --duration 0 = no limit)
Start and stop | bigarrow start ... returns at once; bigarrow stop (or stop --all) removes it
The agent goes away | an arrow ends when the agent process that drew it exits (CLAUDE_PID, or BIGARROW_OWNER_PID)
The human answers | bigarrow stop --hook as a Claude Code UserPromptSubmit hook clears that session's arrows
The human closes it | --close-button puts a clickable X on the sign (opt-in)
Targets: --at X,Y, --rect X,Y,W,H, --mouse, --window App[:title], --element Label --app App, --peekaboo ID --snapshot see.json (from Peekaboo's see --json). Coordinates are global top-left logical points, the space Accessibility, CGWindowList and Peekaboo report. --display N makes --at and --rect relative to one display.
An arrow is tied to the app it points into. --app App[:window or tab title] (or --window) brings that app, window or Chrome/Safari tab to the front first, because pointing at a window hidden behind your terminal is a special kind of unhelpful; and while another app covers the target, the arrow hides and comes back with it. --no-raise leaves your windows alone. bigarrow elements --app X lists what --element can match. bigarrow doctor shows permissions, who owns them, and your displays.
Every command takes --json. Exit codes: 0 ok, 2 bad input, 3 target not found, 4 permission missing. Agents love exit codes. Humans tolerate them.
It is an arrow, so we spent an unreasonable amount of time on how it looks.
Real screenshots on a clean test machine, six looks over white, macOS grey, dark, black, red and a busy web page:
--shape bend|straight|zigzag|spiral(zigzag for when it is really urgent; spiral loops once around the sign before it points, for when it must be impossible to miss)--style arrow|ring|box; rings and boxes are border-only, so you still see what is under them--size S|M|L,--corners round|sharp--color red|orange|yellow|green|teal|blue|purple|pink|black|white|#RRGGBB--border shadow|white-black|black: the default is a white border (dark on light colours) with a drop shadow;white-blackputs a thin black edge outside the white border instead of the shadow;blackis just a thin black outline- Every colour is yours:
--border-color,--text-color,--edge-color, and for the X--close-colorand--close-x-color. Left out, each picks a readable colour itself --close-buttonputs an X inside the sign's right end (white circle, X in the arrow colour), where it never covers the text or leaves the screen--followmoves with a window or element,--until-clickends on a click on the target,--sayspeaks the sign- Several arrows at once keep their signs out of each other's way
The shaft grows out of the sign through a flared joint that never runs into a rounded corner. scripts/gallery.py renders every combination offscreen and zooms into every joint (junctions), because a seam at the joint was, apparently, unacceptable.
Does it need Screen Recording or Accessibility? Drawing needs neither. --element, elements, --until-click and front --window use Accessibility, which macOS grants to the app that runs your shell (Terminal, iTerm2, Ghostty, VS Code, Claude), never to bigarrow itself. bigarrow doctor names that app, and exit code 4 tells the agent exactly what to ask you for. --window App:title reads window titles, which macOS 26 hides without Screen Recording; --window App alone needs nothing.
Will it steal my focus while I'm typing? No. That was the hardest bug in the project: NSApplication.run() quietly activates a process that has no terminal, so detached arrows grabbed the focus. bigarrow pumps events itself instead, and the tests check that the frontmost app never changes.
Can I click through it? Yes, everywhere except the sign and the shaft: a click there removes the arrow (it dims slightly under the pointer to say so). A click on the target, or anywhere near the arrow's head, goes straight through to the app. Clicking the arrow never takes the focus.
Multiple displays? Full-screen apps? Stage Manager? Spaces? Yes, yes, yes, yes. Displays left of or above the main one (negative coordinates) included. Unplug a display while an arrow is on it and the arrow politely leaves. See the verification matrix.
How much CPU does a pulsing arrow cost? 1.4 % measured on a CI runner. Core Animation does the work in the render server.
Does--element work inside web pages? In Electron apps, yes. In Chrome, only when Chrome runs with --force-renderer-accessibility (or VoiceOver is on); Chrome ignores the usual request to expose page content, verified on Chrome in October 2026. Chrome's own toolbar always works. Otherwise point at the page's coordinates, which the skill explains.
Why not just use [some screen annotation app]? Those are for humans drawing on screens. This is for programs pointing at things, from a shell, with exit codes. Twenty-six tools were checked before writing a line (research). None did this.
Is it AI? No. It is the least intelligent part of your AI stack, and proud of it.
- 87 automated tests: geometry, placement, joint smoothness, a golden image, recorded window-server, Accessibility and Peekaboo 4.9.0 fixtures, and tests against the real window server (window level 1000, clicks pass through, focus never moves, detach and stop timing). CI runs them on macOS 15; they also passed on macOS 26 and macOS 27.
- 17 behaviour checks on a clean runner (visual.yml): real clicks on the X,
--until-click,--follow, raising (and--no-raise), hiding while covered, selecting a Chrome tab, ending with the owner process,stop --hook,--say, full-screen apps, Stage Manager, a Space switch, a second display, a 2x display, unplugging a display mid-arrow, CPU. The demo GIF above is recorded by the same workflow, on a desktop with nothing personal on it. - A fresh agent given only the skill and "show Franz where the Reload button in Chrome is" found it by label and built the right command (transcript). It also found a bug, which is now a test.
For agents (and the humans who configure them)
The skill in skill/big-arrow/ works for both Claude Code and Codex (one SKILL.md, Agent Skills format, plus agents/openai.yaml for Codex). It tells the agent when to point, how to pick a target, to write a full sentence on the sign, to add --say when you are probably not looking, and to stop once you have acted.
Plan, decisions, research
docs/plan/PLAN.md (goal, architecture, risks), docs/plan/TICKETS.md (generated from docs/plan/tickets.json), docs/decisions/, docs/research/ (verified facts with links), docs/verification/, docs/skill-tests/, CHANGELOG.md.
Peekaboo's visualizer (https://github.com/openclaw/Peekaboo) and Nameplate (https://github.com/steipete/Nameplate) by Peter Steinberger showed the overlay window recipe and the agent-skill packaging. Neither draws a pointing arrow with a label, which is the gap this project fills. bigarrow reads Peekaboo's see --json as an optional target source.
MIT. Point responsibly.





