Point and Yap 实测:双击 Control 指屏说话,编码 Agent 经 MCP 自己来取任务

给编码 Agent 提需求,最费劲的从来不是等它写代码,而是把「我指的是屏幕上那个按钮」这件事讲清楚。截图、裁剪、描述坐标、补上下文,一轮下来 bug 还没修,先花了五分钟打字。10 月 18 日刚开放下载的 Point and Yap 就是冲着这一步来的:双击 Control,指着屏幕上有问题的元素,把想改什么说出来,松手——这条录音连同截图和元素信息会进入本地队列,你的编码 Agent 通过 MCP 自己来取。

我在这台 macOS 26.5 的 MacBook 上把安装、配置和 MCP 服务端完整跑了一遍,下面是真实过程,包括一个官方文档没提的坑。

它是什么,和 BigArrow 有什么不一样

Point and Yap 是开发者 Marc Maurer 的开源项目(MIT 协议,GitHub 仓库 mfmaur/pointandyap,当前版本 0.1.4),只支持 macOS 26 以上的 Apple silicon 机器。工作流是反过来的:BigArrow 那类工具是让 Agent 在屏幕上画箭头给人看,而 Point and Yap 是人指给 Agent 看——每次录制会产生一个队列条目,里面装三样东西:

  • 你说的话,用 Apple 的端侧语音识别框架 SpeechAnalyzer 转成文字,每个词还有时间戳,能和光标位置对齐;
  • 录制期间光标停留和点击位置下的 UI 元素(角色、标签、窗口、所属应用,通过 macOS 辅助功能 API 读取);
  • 对应时刻的裁剪截图——录制提示条本身会被排除在截图外,不会污染画面。

Agent 端通过标准 MCP(Model Context Protocol) 来取任务、改代码、标记完成。全程数据不出本机:录音、截图、队列都存在 ~/PointAndYap/sessions,App 自己唯一联网行为是检查更新。

安装:一条命令,实测通过

官方给了安装脚本,我实测完整跑通:

Bash
curl -fsSL https://pointandyap.com/install.sh | sh

我把脚本源码先读了一遍再执行的:它从 GitHub Releases 下载签名 DMG,用 spctl 验证 Apple 公证后才拷贝进 /Applications,中途会检查系统版本(低于 macOS 26 直接拒绝安装),逻辑干净,没有多余动作。也支持 Homebrew cask(brew install --cask mfmaur/tap/point-and-yap),或者去官网 pointandyap.com 手动下载 DMG。

装完第一次打开要授权三样权限:麦克风(录音)、屏幕录制(截图)、辅助功能(读元素)。别嫌多,这三样缺一个功能就残废——没有辅助功能权限它就拿不到你指的元素是什么,Agent 收到的就只剩一句转写文字和一张图。

第一个坑:它没有 –help

装完我想看看 CLI 有什么参数,习惯性敲了:

Bash
"/Applications/Point and Yap.app/Contents/MacOS/PointAndYap" --help

结果没有任何输出,进程直接挂住,等了快三分钟也没反应,最后只能杀掉。这个二进制不认识 --help,传了未知参数不会报错退出,而是静默等待——对脚本党来说这算是隐性陷阱:如果你的自动化脚本里拼错了参数,不会得到失败信号,只会得到一个永远不返回的进程。想要命令行能力,正确的入口是这两个:

Bash
# 列出当前队列(无 MCP 客户端时的 shell 回退)
"/Applications/Point and Yap.app/Contents/MacOS/PointAndYap" --items
# Agent 完成后标记
POINTANDYAP_AGENT=my-agent "/Applications/Point and Yap.app/Contents/MacOS/PointAndYap" --done <id> --note "what changed"

我实测了空队列下的 --items,输出是一句干净的 Nothing open in Point and Yap.,退出码 0——脚本化判断队列状态没问题。

MCP 服务端实测:8 个工具全部在线

App 自带 stdio MCP 服务器,启动参数是 --mcp。我写了个最小 JSON-RPC 客户端直接和它对话,完整验证了协议握手和工具调用:

Python
import json, subprocess

BIN = "/Applications/Point and Yap.app/Contents/MacOS/PointAndYap"
p = subprocess.Popen([BIN, "--mcp"], stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE, text=True)

def send(obj):
    p.stdin.write(json.dumps(obj) + "\n")
    p.stdin.flush()

def recv():
    return json.loads(p.stdout.readline())

# 1. 握手
send({"jsonrpc": "2.0", "id": 1, "method": "initialize",
      "params": {"protocolVersion": "2024-11-05", "capabilities": {},
                 "clientInfo": {"name": "test", "version": "0"}}})
print(recv()["result"]["serverInfo"])   # {'name': 'pointandyap', 'version': '0.1.4'}
send({"jsonrpc": "2.0", "method": "notifications/initialized"})

# 2. 列出工具
send({"jsonrpc": "2.0", "id": 2, "method": "tools/list"})
print([t["name"] for t in recv()["result"]["tools"]])

# 3. 空队列下调用
send({"jsonrpc": "2.0", "id": 3, "method": "tools/call",
      "params": {"name": "get_open_items", "arguments": {}}})
print(recv()["result"]["content"][0]["text"])

实测结果:服务端自报版本 0.1.4,tools/list 返回 8 个工具,和文档一字不差:

Plaintext
get_open_items   取走开放任务并标记为「由我处理中」
mark_done        完成任务并留一行备注
start_items      只标记不取内容
list_items       看全部任务状态(open / in progress / done)
release_items    把任务退回队列
list_sessions    列出所有录音会话
get_session      取某次录音的对齐时间线
get_frame        取全分辨率截图帧

几个值得说的实测细节:

  • 空队列行为友好:list_items 返回 Nothing open or in progress.,get_open_items 返回 No open items.,不会抛异常——Agent 空轮询是安全的。
  • 错误处理克制:我故意传了不存在的 ID,start_items 和 mark_done 都返回 Not changed: nonexistent-123.,get_session 返回 no such session,全程无崩溃无堆栈。
  • 并发保护是真的:源码里用文件锁防止两个 Agent 同时取走同一条任务;超过两小时没人完成的「处理中」任务会自动退回队列。这两点是很多个人项目会偷懒的地方,它做了。

接到你的 Agent 上

首次启动 App 时它会扫描本机的编码 Agent,问你要不要连接:同意后会自动写入 Claude Code(user scope)、Codex(~/.codex/config.toml)和 Cursor(~/.cursor/mcp.json),并且往 ~/.claude/skills 和 ~/.agents/skills 链接一个 skill。每个配置文件改之前都会先备份到 ~/Library/Application Support/PointAndYap/backups/,已存在的同名 pointandyap 条目不会被覆盖。

跳过了也没关系,之后在 Settings 里随时可以 Connect now。任何支持本地 stdio MCP 的客户端都能手动接,命令就是上面那个 --mcp 启动路径。如果你用的 Agent 不支持 MCP,只要有 shell 就能用 --items / --done 的回退方案,我在上面已经验证过 --items 可用。

哪些部分我没能测,以及一个不建议的使用场景

语音录制这条链路(双击 Control → 说话 → 转写 → 入队)需要真实麦克风交互和 GUI 操作,我在无人值守环境下没有实测,转写质量和词级时间戳与光标对齐的准确度属于未实测、需人工确认的部分。源码层面可以确认转写用的是 Transcriber.swift 里的 SpeechAnalyzer(整个项目 22 个 Swift 文件共约 2500 行,体量很小,想审计的话半小时能读完)。

一个不建议的使用场景:别把含敏感代码的窗口对着它随意说话。App 本身确实零外传,但 Agent 取走任务后,你的原话和裁剪截图会跟着它发到大模型那边——这和把文件贴进对话框没有任何区别。在受管设备或客户项目上用之前,先想清楚这一点,相关风险可以参考我之前写的 AI Agent 安全风险开发者指南。

我的判断

这个工具聪明的地方不在语音识别(那是系统能力),而在于它把「指哪」这件事结构化了:光标位置 + 辅助功能元素 + 时间对齐的转写,让 Agent 拿到的不是一段模糊描述,而是可以直接定位到代码的线索。同类产品里同日还冒出来一个走对讲机硬件路线的 walkai-talkai,思路更猎奇但通用性差一截,标准 MCP 接入这一点上 Point and Yap 是更稳的选择。

如果你日常用 Claude Code 或 Codex 改 UI,值得花十分钟装上试试——前提是 macOS 26 和 Apple silicon 这两道门槛你都得够得着。配置好之后,让 Agent 把修完的任务标记 done 的那一刻,这个「说句话就修 bug」的闭环才算真正跑起来。上手之前也可以先看看 Codex Harness 的能力边界,理解 Agent 端是怎么消费这类任务的。

最后补一条相关阅读:如果你关心端侧语音的另一种玩法——不采集环境音、纯离线清洗转写文稿,可以看这篇 S1-mini 开源 ASR 文稿清洗模型实测,两个工具正好覆盖「录」和「清」两端。

推荐阅读

  • DeepSeek Search/Fetch API 实测:给 Agent 装上实时网页检索,5 元/1000 次的计费坑我先踩了

    DeepSeek 10/17 开放 Search/Fetch API:Search 返回带权威性评分的结构化网页结果,Fetch 把 URL 转成 Markdown。本文实测端点响应、鉴权错误、计费规…

  • Superwhisper 开源 S1-mini 实测:462MB 小模型把 ASR 乱稿洗成正式文稿,我在 Mac 上跑了一遍

    Superwhisper 开源的 S1-mini 基于 Qwen3-0.6B 微调,专做 ASR 文稿清洗,量化后仅 462MB。本文在 Apple M4 上用 llama.cpp 实测 7 组用例:…

  • LFM2.5-24B-A2B 实测:激活只有 2B 的 24B 端侧模型,我在 16GB MacBook 上踩了一遍内存坑

    Liquid AI 开源的 LFM2.5-24B-A2B 是 24B 总参、每 token 只激活 2B 的端侧 Agent 模型。本文在 16GB 内存 Apple M4 上用 llama.cpp …

  • CC Switch 实测:把 Claude Code、Codex、Gemini CLI 等 10 款 Agent CLI 的配置统一到一处

    同时装 Claude Code、Codex、Gemini CLI 的人越来越多,配置文件却散落在各处。本文实测 CC Switch v4.0.13:从安装、自动导入、Provider 三模式,到 to…