关于 chrome-relay
chrome-relay 是通过浏览器扩展和本地原生主机控制真实 Chrome 的技能。它提供带可操作元素引用的页面快照及标签页操作命令,适用于需要沿用现有登录状态的场景。
主要功能
- 01控制 Chrome 标签页
- 02生成带可操作引用的页面快照
- 03点击、填写、输入并等待页面响应
- 04检查页面文本、网络和控制台
- 05截取屏幕截图与录屏
适用场景
- 01自动化已登录浏览器中的工作流
- 02检查并更新网页字段
- 03排查页面交互或加载问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ kiluazen/ chrome-relay --skill chrome-relay安装后在 Claude Code 中输入/chrome-relay确认已加载。
附带文件references/patterns.mdreferences/troubleshooting.md
详细介绍
Chrome Relay
通过 Chrome 扩展和本地原生主机驱动用户的真实 Chrome。当登录后的浏览器状态(身份验证 Cookie、会话、已安装的扩展)很重要时,优先使用它。
设置
- Chrome 扩展
- CLI:
pnpm add -g chrome-relay chrome-relay install chrome-relay doctor
确认 CLI ≥ 0.7.0——wait/get/batch/snapshot --diff 在此版本中推出(0.6.0 引入了 snapshot/@ref 循环;≥ 0.5.20 修复了 Radix/React-Aria UI 中的静默点击错误):
chrome-relay --version
核心循环
chrome-relay tabs # find or create a tab
chrome-relay navigate "https://kushalsm.com" --new # background tab by default
chrome-relay snapshot --tab 1234 -i # see the page: actionable elements get @refs
chrome-relay click @e12 # act on refs — no --tab, no selector
chrome-relay fill @e14 "hello"
chrome-relay wait --text "Saved" --tab 1234 # block until the page reacts
chrome-relay snapshot --tab 1234 --diff # print only what changed (~100 tokens)
Snapshot 输出为精简的缩进文本(大多数页面约为 1–15 KB)——可直接阅读,无需 jq:
- link "Hacker News" [ref=e4]
- textbox "Search" [ref=e41]: current value
- checkbox "Remember me" [checked, ref=e42]
- clickable "Open card" [ref=e88] ← cursor-pointer div the AX tree missed
Ref 自带其所属标签页。 click @e12 会在生成 e12 的标签页上执行,而非当前活动标签页——即使用户继续浏览,也很安全。与之矛盾的 --tab 会报错 target_conflict。
Ref 的生命周期。 Ref 在同一页面的 DOM 变化中仍然有效(缓存的 backendNodeId 会在节点被替换时通过角色和名称重新查找来修复),但在真正导航后会失效。失效的 Ref 会返回 error.code = stale_ref → 重新运行 snapshot。
拦截检测。 Ref 点击会先对目标点进行命中测试:如果覆盖层 / 粘性页眉 / 模态框占用了该位置,就会返回指出拦截元素的 error.code = click_intercepted——关闭它或滚动页面,然后重试。点击操作不会执行。fill/type 会跳过此检查(被遮挡的输入框仍可写入)。
工具概览
| 命令 | 功能 |
|---|---|
tabs | 列出窗口和标签页及其 tabId |
navigate <url> | 在当前标签页中打开。--new 会在后台打开新标签页(默认)。--active 会将其切换到前台。--tab <id> 会将操作目标改为现有标签页。 |
snapshot --tab <id> -i | 提供带可操作 @refs 的页面快照——无障碍树 + 光标交互式扫描,共用一个 ref 空间,文本精简。-d N 限制深度,-s <css> 将范围限定到子树,-u 包含 href,--diff 仅输出自上次快照以来的变化,--json 返回包含 refs 映射的结构化封装。 |
wait <css|@ref> / wait --text / --url <glob> / --load networkidle / --fn <js> | 阻塞至条件成立(每次调用一个条件,默认 10s,最长 25s)。wait 1500 只会休眠。超时错误会包含当前页面状态。 |
get text|value|attr|count|title|url <target> | 获取单个值,原样输出到 stdout——不提供完整快照。get text @e12、get attr @e7 href、get count ".row"。 |
batch '[{"name":"chrome_...","args":{...}}, ...]' | 在一次往返中顺序执行 N 次工具调用,默认遇错即停。使用 wire 工具名称。 |
skills get core | 输出此操作指南,版本与已安装的二进制文件匹配。 |
click <@ref | selector> --tab <id> | 在元素中心执行可信的悬停 + 按下 + 释放操作(pointerType: "mouse")。ref 无需 --tab。 |
click --x N --y N --tab <id> | 坐标模式点击——适用于没有 DOM 句柄的 canvas/SVG 图表内部区域。 |
hover <@ref | selector | --x --y> | 仅移动指针——触发 :hover 样式。 |
fill <@ref | selector> <value> | 将值原子写入 <input>/<textarea>/<select>。绕过 React 的值跟踪器。ref 可以访问 shadow DOM 内部(选择器不行)。 |
type <text> [-s <@ref | selector>] | 使用 CDP Input.insertText。适用于 contenteditable / Draft.js / Lexical / ProseMirror。会在光标处追加;如果输入框已有值,请先清空。 |
keys <chord> --tab <id> | 单个按键或组合键:Enter、Tab、Escape、Cmd+K、Shift+ArrowDown。 |
js <code> --tab <id> | 在 MAIN world 中执行 Runtime.evaluate。使用 return 返回值。支持顶层 await。 |
screenshot --tab <id> -o <path> | PNG。--full 会截取视口之外的内容。--max-edge N 会调整尺寸。 |
screencast --tab <id> -o <path> | 通过 CDP 录制标签页(由绘制事件驱动)。需要有活动标签页。 |
network --tab <id> | HTTP 请求/响应环形缓冲区,每个标签页保留最近 200 条。使用 network read --request-id <id> 读取正文。 |
console --tab <id> | console.log/warn/error + 页面异常,保留最近 200 条。 |
viewport | 模拟设备视口、DPR、移动设备标记、触控和 UA。 |
workspace / group | 管理命名窗口/标签页组,以便多个 Agent 分别操作不同窗口。 |
switch <tabId> / close <tabIds...> | 激活或关闭标签页 |
self-reload | 在重新构建后重启扩展的 service worker |
release-notes --since <ver> / update | 可查询的变更日志;可由 Agent 读取的 JSON。 |
call <tool> [json] | 对任何内部工具进行原始透传调用。 |
read / ax / click-ax | 已弃用——分别是 snapshot / click @ref 的别名。将会移除;请勿在新工作中使用。 |
选择合适的文本工具
| 目标元素 | 工具 |
|---|---|
<input>、<textarea>、<select>(包括由 React 控制的元素、shadow DOM) | fill @ref |
[contenteditable]、role="textbox"、Draft.js / Lexical / ProseMirror、X 撰写框、LinkedIn 私信、新 Reddit 撰写框 | type |
| 提交、导航菜单、修饰键快捷键 | keys |
| 组合框 / 自动完成选项选择 | 在筛选框中使用 type → 使用 keys ArrowDown → 使用 keys Enter(原因) |
| 框架内部操作、抓取数据、自定义组件 | js |
元素定位——后备方案顺序
- 来自
snapshot -i的@ref——默认方式。适用于按钮/链接/输入框、带名称的内容、指针光标的 div 堆叠(扫描结果)以及 shadow DOM。 - CSS 选择器——当你已知静态选择器且不需要快照时使用。
js探测 → 坐标点击——适用于 canvas 内部元素和 SVG 图表区段(匿名<path>元素在任何地方都没有 DOM 句柄):chrome-relay js --tab 1234 "const r = document.querySelector('svg path').getBoundingClientRect(); return {x: r.x + r.width/2, y: r.y + r.height/2}" chrome-relay click --tab 1234 --x 312 --y 218
不要轮询——等待
每次操作后都获取快照会浪费轮次。对于正在变化的页面,使用开销低的循环:
chrome-relay click @e12
chrome-relay wait --text "Saved" --tab 1234 # or wait <selector> / --url / --load
chrome-relay snapshot --tab 1234 --diff # only the changes, refs included
常见注意事项
- **
snapshot -i用于执行操作,不用于提取事实。**它只会输出带 ref 的元素——非交互式值(仪表盘指标、段落文本、图表标签)会被忽略。实测中,Cloudflare Pages 指标页面在-i模式下所有数字都消失了。要读取事实,请使用完整的snapshot、get text <target>或js投影。 type会追加内容——它会在插入光标处输入。如果输入框已有值(自动保存的草稿、默认文本),请先通过js或keys清除(Cmd+A 后按 Backspace)。- 导航后 ref 会失效——
stale_ref表示页面已发生变化;请重新获取快照。不要重试同一个 ref。 - 坐标很快就会过时——读取
getBoundingClientRect后,滚动或重新排版,再点击时可能会点错元素。尤其是自动补全弹窗,请使用键盘导航,而不是坐标点击。 - 点击“成功”但没有任何反应——首先进行诊断:
document.elementFromPoint(x, y)。如果返回的是包装元素或表单背景,说明坐标有误。如果返回了正确元素但状态没有变化,很可能是 chrome-relay <0.5.20——请升级。
更多操作示例:references/patterns.md
故障模式:references/troubleshooting.md
操作指南
- **不要过早放弃。**点击失败也是信息,并不意味着要停止。附加一个文档级监听器并设置
capture:true,观察触发的事件:chrome-relay js --tab 1234 " ['pointerdown','mousedown','click'].forEach(t => document.addEventListener(t, e => console.log(t, e.target.tagName, e.target.className), {capture:true}) ); return 'listening' " # do the action, then: chrome-relay console --tab 1234 - **不要回显机密。**通过
js提取令牌/API 密钥时,请将结果直接写入文件。切勿执行echo $TOKEN或将其插入 shell 字符串——内容会出现在滚动历史记录、日志和工具记录中。 - **对
network输出进行脱敏。**请求/响应标头包含 Cookie、身份验证/CSRF 令牌、账户和项目 ID。切勿将原始chrome-relay network输出粘贴到聊天、文档、问题或提交中——请仅筛选所需字段(url、status、timings),或先对标头进行脱敏。 - 在执行不可逆操作前留存截图(提交表单、发送消息、更改账户)。保存截图路径。
防护措施
- 错误采用结构化格式:根据
relayError.code(stale_ref、click_intercepted、element_not_found、target_conflict、timeout)进行分支处理,而不是根据消息文本。 - 如果某个标志的含义不明确,以
chrome-relay <command> --help为准——这些文档可能滞后。