相关 Skills
当 Agent 需要通过 opencli 操控真实 Chrome 浏览器窗口时使用——适用于页面审查、表单填写、已登录流程顺流操作或临时数据提取等场景。涵盖选择器优先(selector-first)的目标契约、复合表单字段、失效引用(stale-ref)处理、网络请求捕获以及 CLI 返回的 Agent 原生响应包(envelopes)。本 Skill 不适用于编写适配器——如需编写适配器,请参考 opencli-adapter-author。
opencli-browser
这个 CLI 的首要读者是 Agent,而不是人类。每个子命令都会返回一个结构化的响应包(envelope),明确告诉你匹配到了什么、匹配置信度有多高,以及匹配失败时该怎么处理。请善用这些响应包,切勿盲目凭空猜测。
本 Skill 用于操控实时浏览器以完成 Agent 任务。如果你要在 ~/.opencli/clis/<site>/ 下开发可复用的适配器,请改用 opencli-adapter-author。
前置条件
opencli doctor
在 doctor 输出全绿之前,其他任何命令都无法正常工作。常见失败原因包括:Chrome 未运行、扩展未安装、调试端口被 1Password 或其他扩展阻塞。doctor 的输出会明确告诉你具体问题所在。
Session(会话)生命周期
opencli browser *命令必须在browser紧跟一个<session>位置参数。在多步操作流程中请复用相同的 session 名称;如需隔离并行进行的浏览器任务,请使用不同的名称。- 对于任何多命令或与人类交替操作的浏览器工作流,请使用固定的 session 名称。示例:先执行
opencli browser fb-yaya-warmup open https://example.com,随后复用opencli browser fb-yaya-warmup state、extract、click等命令。 - 被 opencli 接管(Owned)的浏览器 Session 会在多次调用之间保持标签页租约(tab lease)的活性。你可以通过
opencli browser <session> close手动释放租约,或等待空闲超时自动失效。 opencli browser <session> bind可将你当前已打开的 Chrome 标签页绑定到该 Session。适合处理已登录页面、SSO 登录流程,或者在将控制权移交给 Agent 前已手动定位好的页面。--window foreground|background(或设置环境变量OPENCLI_WINDOW=foreground|background)用于决定 OpenCLI 是在接管 Session 时创建/聚焦前台浏览器窗口,还是使用后台浏览器窗口。
绑定标签页(Bind Tab)
opencli browser gmail bind
opencli browser gmail state
opencli browser gmail click "Search"
opencli browser gmail network
opencli browser gmail unbind
绑定操作永远不会占用用户的主窗口,也不会关闭用户的标签页。如果标签页被关闭或变得不可调试,绑定会直接失败并关断(fail closed)。当你在真实的浏览器中切换到其他标签页时,请重新运行 opencli browser <session> bind。
在绑定的 Session 上是允许进行页面导航(Navigation)的,因为此时 Session 代表 Agent 对该标签页拥有明确的操作权。但标签页变更操作(tab new、tab select、tab close)在绑定 Session 中依然会被拦截。如果你希望 OpenCLI 全权管理标签页生命周期,请使用接管(Owned)Session。
绑定的 Session 不触发 OpenCLI 的空闲自动关闭定时器;绑定关系会一直保持,直到执行 unbind、标签页关闭、窗口关闭或后台 Daemon 重启。
心智模型(Mental model)
- 选择器优先(Selector-first)的目标契约。 每个交互命令(
click、type、select、get text/value/attributes)均接受一个<target>,它可以是来自state/find的数字引用(ref),也可以是 CSS 选择器。当存在多个 CSS 匹配项时,可使用--nth <n>消除歧义。 - 每个响应包都会提供
matches_n和match_level。match_level的取值为exact、stable或reidentified——CLI 已经帮你自动容忍并修复了中等程度的 DOM 漂移,但这个字段能让你清晰了解当前匹配的置信度。 - 默认输出精简内容,按需获取完整 Payload。
state是兼顾上下文 Token 预算的快照;get html --as json支持通过--depth/--children-max/--text-max进行截断;network仅返回请求结构预览,具体 Body 可通过--detail <key>单独拉取。直接输出巨型 Payload 会无意义地消耗掉你不需要消耗的上下文。 - 结构化错误方便机器解析。 发生失败时,CLI 会输出
{error: {code, message, hint?, candidates?}}。请根据code字段进行逻辑分支判断,而不是去匹配错误字符串。
核心法则
- 先审查,后行动。 务必先运行
state或find。严禁凭借记忆跨 Session 硬编码数字 ref 或选择器——索引仅在当前快照内有效。 - 优先使用站点适配器,其次才是底层浏览器操控。 如果
opencli <site> <command>已经支持该任务,请优先使用对应的适配器命令(例如opencli facebook notifications、opencli reddit read、opencli chatgpt model <level>等)。仅在遇到适配器未覆盖的功能盲区、调试需求或临时 UI 流程时,才使用opencli browser ...。 - 拿到数字 ref 后,优先使用 ref 而不是 CSS。 因为 CLI 对每个打上标签的元素做了指纹记录,数字 ref 能在 DOM 发生轻微变动后依然存活。而手写的 CSS 选择器在页面重新渲染后极易直接失效。
- 每次写入操作后都应读取
match_level。exact= 一切正常。stable= 元素未变,但部分非关键属性发生了漂移——你的操作已成功生效。reidentified= 原始 ref 已消失,CLI 找到了唯一的替换元素;请仔细二次确认是否命中正确的目标。 - 对表单控件善用
compound字段。 不要用正则去猜日期格式,也不要运行两次state来获取完整的<select>选项列表。复合(compound)响应包中已包含格式化字符串、前 50 项完整选项列表、溢出计数options_total,以及针对<input type=file>的accept/multiple属性。 - 对关键的写入操作进行验证。 在执行
type <target> <text>后,运行get value <target>检查。在执行select后,运行get value。自动补全组件、React 受控输入框以及带掩码的输入框都有可能静默吞字,CLI 无法替你自动检测到这一点。 - 页面变更后遵循
state→ 操作 →state流程。 页面导航、表单提交以及 SPA 路由跳转都会导致旧 ref 失效。请务必重新获取最新的快照,切勿复用页面跳转前的 ref。 - 复用最新解析的 ref 时使用
&&链式调用。 链式命令会在同一个 Shell 进程中运行,以便刚刚从输出中读取到的 ref 能直接传递给下一条命令。跨 Shell 的独立调用虽然能维持命名的浏览器 Session,但在页面发生变动后,上一条命令里保存的 Shell 本地变量或复制的 ref 随时可能会失效。 eval仅限读取操作。 请将 JS 代码包裹在 IIFE(立即调用函数表达式)中并返回 JSON。如果你需要修改页面,请使用结构化的click/type/select/keys等命令——这些命令会生成结构化输出与元素指纹,而eval不会。- 优先使用
network捕获,而不是直接抓取屏幕 DOM。 如果你关注的页面是通过 JSON API 拉取数据的,直接抓取 API 数据通常比解析渲染后的 DOM 可靠得多。先捕获一次,审查数据结构,再通过--detail <key>获取你所需的具体 Body。
站点地图(Sitemaps)
如果 browser open 或 browser analyze 返回 sitemap.available: true,在继续执行多步骤站点流程之前,请先切换至 opencli-browser-sitemap。站点地图提供了关于页面、操作、工作流、API 以及已知坑点的先验上下文,但它并非绝对真理。如果浏览器当前真实状态与站点地图不符,请以浏览器实时状态为准,并通过 opencli-sitemap-author 将站点地图标记为失效(stale)。
目标契约(适用于 click / type / select / get text|value|attributes 的 <target>)
<target> ::= <numeric-ref> | <css-selector>
- 数字引用(Numeric ref) — 来自
state或find的[N]索引。轻量且对轻度 DOM 漂移具备容错能力。 - CSS 选择器 — 任何
querySelectorAll支持的语法。在写入操作中必须具备唯一性,或者配合--nth <n>参数使用。
成功时的响应包(Envelope)
{ "clicked": true, "target": "3", "matches_n": 1, "match_level": "exact" }
{ "value": "kalevin@example.com", "matches_n": 1, "match_level": "stable" }
match_level 说明
| 级别 | 含义 | 建议操作 |
|---|---|---|
exact |
标签 + 强特征 ID 完全一致,且最多仅有一项非关键属性变动 | 继续执行。 |
stable |
标签 + 强特征 ID 依然匹配,但软信号(aria-label, role, text)发生变动 | 继续执行,但如果你输入的文本/点击的内容非常关键,建议通过 get value 或 state 进行二次校验。 |
reidentified |
原始 ref 已不存在;页面上唯一的实时元素匹配了指纹,并被重新绑定到了旧 ref 上 | 在继续链式执行更多写入命令前,请二次确认是否命中了正确的元素。 |
结构化错误代码
请基于这些错误码进行逻辑分支判断,而不是匹配人类可读的提示信息:
| 错误码 | 含义 |
|---|---|
not_found |
数字 ref 在 DOM 中已不存在。请重新运行 state。 |
stale_ref |
ref 仍然存在,但该 ref 对应的元素身份已改变。请重新运行 state。 |
invalid_selector |
CSS 选择器无法被 querySelectorAll 解析。请修复选择器。 |
selector_not_found |
CSS 选择器匹配到了 0 个元素。请尝试使用更宽泛的选择器配合 find 查找。 |
selector_ambiguous |
CSS 选择器匹配到了 >1 个元素且未指定 --nth。请添加 --nth 或缩窄选择器范围。 |
selector_nth_out_of_range |
--nth 超出了实际匹配到的数量范围。 |
option_not_found |
select 无法找到匹配该 label/value 的选项。错误响应包中会附带真实选项文本的 available: string[]。 |
not_a_select |
在非 <select> 元素上调用了 select 命令。 |
错误响应包始终包含 error.code 和 error.message。目标相关的错误(selector_not_found、selector_ambiguous 等)通常会附加推荐选择器列表 error.candidates: string[]。而 option_not_found 则会附带 error.available: string[]。
命令参考手册
审查(Inspect)
| 命令 | 用途 |
|---|---|
browser state |
快照:带有 [N] ref 的文本树、滚动提示、隐藏可交互元素提示,以及用于 date/select/file 引用信息的 compounds (N): 旁路数据(sidecar)。 |
browser state --source ax |
主动开启可访问性树(Accessibility tree)快照。当自定义控件、Portals 或 iframe 内的内容在普通 state 中难以识别时使用。AX ref 可以通过 role/name/nth 挽救因 React 重新渲染而失效的情况,并支持同源 iframe ref 路由。跨源 iframe ref 采取尽力而为(best-effort)原则,因为 Chrome 可能不会向扩展暴露可挂载的 OOPIF 目标。 |
browser state --compare-sources |
仅输出 DOM 与 AX 的对比指标,用于评估是否应将 AX 设为默认模式。该命令仅打印数量与大小而非页面文本,因此更安全,适合分享用于校验。 |
browser find --css <sel> [--limit N] [--text-max N] |
执行 CSS 查询,每个匹配项返回一条包含 {nth, ref, tag, role, text, attrs, visible, compound?} 的数据。会为上一份快照未打标签的匹配项分配 ref。当你已明确选择器时,它是比 state 更轻量的替代方案。 |
browser find --role button --name Save |
语义化定位器查询。同样支持 --label、--text 和 --testid。当控件包含可访问标签时,优先于原始 CSS 使用。 |
browser frames |
列出跨源 iframe 目标。可在 eval 命令中将索引传递给 --frame。 |
browser screenshot [path] |
视口 PNG 截图。不传路径则输出 base64 到标准输出。如果仅需结构信息,优先使用 state。 |
browser screenshot --annotate [path] |
可视化 ref 标注图。刷新 DOM ref 并叠加可视化的 [N] 标签,使截图能够映射回 browser click <ref> 的目标。适用于纯图标控件、视觉布局、图表或文本状态存在歧义的场景。 |
获取(Get - 只读)
| 命令 | 返回内容 |
|---|---|
browser get title |
纯文本 |
browser get url |
纯文本 |
browser get text <target> [--nth N] |
{value, matches_n, match_level} |
browser get value <target> [--nth N] |
{value, matches_n, match_level} |
browser get attributes <target> [--nth N] |
{value: {attr: val, ...}, matches_n, match_level} |
browser get text --role option --name Travel |
无需先调用 state 的语义化定位器读取。参数标志与 browser find 一致。 |
browser get html [--selector <css>] [--as html|json] [--depth N] [--children-max N] [--text-max N] [--max N] |
原始 HTML 或结构化树。JSON 树节点包含 {tag, attrs, text, children[], compound?}。截断情况通过 truncated: {depth?, children_dropped?, text_truncated?} 汇报。 |
交互(Interact)
| 命令 | 备注 |
|---|---|
browser click <target> [--nth N] |
返回 {clicked, target, matches_n, match_level}。 |
browser click --role button --name Submit |
语义化点击。写入操作要求唯一匹配;存在歧义的定位器会返回候选列表而不是直接执行。 |






