捕获
侧边栏Content script 里有一个 per-frame 端口,把每个 DOM 事件转发给 service worker。Shadow DOM 和同源 iframe 都被透明穿透。
- 六级选择器解析(testid → id → aria → text → css → xpath)
- tabPorts: Map<tabId, Map<frameId, Port>>
- IME 感知输入缓冲 · paste · drag
Skill Recorder 是一个 Chrome 扩展,看你走完一次浏览器流程就够了 — 然后写出一份 SKILL.md,这是一份纯 markdown 规约,Claude Code(或任何接入 browse CLI 的 Agent)都能照着回放,不需要选择器、不需要胶水代码、不需要盯着看。
我们交付的,是一个小巧的 Chrome MV3 扩展加一段 4 KB 的蒸馏管线。录制器接入 chrome.debugger,做到 DOM 级别的保真;蒸馏完全在 service worker 里跑;回放通过 browse CLI 读取 SKILL.md。没有服务器,也没有胶水代码。
Content script 里有一个 per-frame 端口,把每个 DOM 事件转发给 service worker。Shadow DOM 和同源 iframe 都被透明穿透。
六次小规模处理把嘈杂的事件流变成确定性规约。自动参数化只在置信度 0.7 以上触发;低于这个值,录制器会先问而不是猜。
browse CLI 把 SKILL.md 当作纯 markdown 来读 — 没有 schema、没有运行时、没有逃生口。每一步都可审计。
浏览器里到处是录制器陷阱 — 哈希类名、懒加载弹窗、Shadow DOM、多标签流程、IME 输入法合成、拖拽。下表每一行都对应演练场里的一个真实场景,点进去就可以亲自录制。
Tailwind 风格的类名(例如 btn__primary--ab3f9c)每次部署都换;解析器走 6 级回退(testid → id → aria → text → css → xpath),换过哈希的按钮照样命中。
A2 →六行里都是一模一样的 "Pick" 按钮 — 只有位置不同。我们用 fingerprintIndex 锚定每次点击,即便列表重排,点击的还是对的那行。
A3 →"Continue" / "继续" / "Weiter" 都映射到同一个 data-i18n-key="action.continue"。录制器优先使用语言无关属性,所以英文录的 Skill 能在中文页面下回放。
A4 →pushState 和 hashchange 都被跟踪,无需 reload;回放会等待新内容挂载,而不是去探一个空容器。
B1 →触发那一刻 Confirm 按钮还不存在。elementVisible 会一直轮询,直到目标出现才下发下一步 — 没有靠 timeout 拼。
B3 →all_frames: true 注入每一帧;动作带上来源 frameId,且会在 URL 重渲染时按 URL 重新解析,过期的 frameId 不会卡住回放。
C1 →password / phone / 信用卡 / SSN 输入被 type + autocomplete + name 检测出来,落入存储前替换成 ***。字节永远不离开页面。
C2 →自定义的 shadow 选择器把路径编码成 { host, inner } 段;解析器在每个边界走一遍 shadowRoot.querySelector,所以 Web Components 是一等公民。
C3 →当一段流程打开新标签 — 打印预览、OAuth、报价生成 — 录制通过 chrome.tabs.onCreated 跟上。回放通过 chrome.tabs.create 重新打开新标签。
C4 →dragstart → dragover → drop 三件套带共享 DataTransfer,合并成一个 drag 步骤(源 + 目标 + 观察到的类型)。不依赖脆弱的像素坐标。
D1 →孤立的 "k" 是文本输入噪音;加上 metaKey: true 就成了 Cmd-K 快捷键。录制器留下组合键、丢弃噪音,保留修饰状态供回放。
D3 →contenteditable 上 change 事件永远不触发。我们勾住 input + compositionend,去抖 300 毫秒,以最终 innerText 合成一个 change 步骤 — 和文本框形状一致。
D4 →每次点击都附上 comboboxContext(选项文本、根选择器);如果回放时直接点击失败,回退会键入文本、按 ArrowDown 直到 aria-activedescendant 匹配,再按 Enter。
D6 →十六中的十三个。另外还有四个综合场景 — Notion、Linear、Jira、Salesforce — 把其中十二到十五个技术串成一段完整流程。看演练场 →
每个周一早上,一家小型供应商的运营工程师都打开同一个门户,点新建采购单,从 CSV 里粘一个 SKU、敲一个数量,再点提交。然后再来一遍。一周两百行,一周接一周,已经持续十四个月。这是一个五分钟仪式,重复到表格结束。
这正是常被推销给录制器的那种任务 — 也正是大多数录制器栽跟头的那种任务。供应商门户每次发布都换 Tailwind 哈希类名。提交按钮藏在每次保存就重渲染的动态表格行里。鉴权 cookie 中午就过期。基于这个页面写的 Selenium 脚本平均能撑两周,然后开始悄悄失败。
工程师把扩展钉到工具栏,打开门户,点开始录制,原原本本做一遍。八次点击、两个填值、一次提交。侧边栏显示事件实时流 — 包括噪音:滚动、focus、blur、不小心划过帮助图标的鼠标。4.6 秒里录到 23 个事件。
main.example.p4
工程师把生成的 markdown 放到 ~/.claude/skills/create-purchase-order/SKILL.md,给 Claude Code 敲了一句话。Agent 按名字找到这个 Skill,解出前置条件(存的 cookie 中午前都还有效),遍历 CSV 里五十行,回头汇报。三分十一秒后,事儿就办完了。没人盯着它跑。
公开 beta 期间免费。不需要账号、不上传、不发送遥测。整个 bundle 4.5 MB;录制留在你机器上,你要导出才会动。