opencli-browser

opencli-browser

热门

当 Agent 需要通过 opencli 操控真实 Chrome 浏览器窗口时使用——适用于页面审查、表单填写、已登录流程顺流操作或临时数据提取等场景。涵盖选择器优先(selector-first)的目标契约、复合表单字段、失效引用(stale-ref)处理、网络请求捕获以及 CLI 返回的 Agent 原生响应包(envelopes)。本 Skill 不适用于编写适配器——如需编写适配器,请参考 opencli-adapter-author。

2.6万Star
2565Fork
更新于 2026/6/27
SKILL.md
只读
名称
opencli-browser
描述

当 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 stateextractclick 等命令。
  • 被 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 newtab selecttab close)在绑定 Session 中依然会被拦截。如果你希望 OpenCLI 全权管理标签页生命周期,请使用接管(Owned)Session。

绑定的 Session 不触发 OpenCLI 的空闲自动关闭定时器;绑定关系会一直保持,直到执行 unbind、标签页关闭、窗口关闭或后台 Daemon 重启。


心智模型(Mental model)

  1. 选择器优先(Selector-first)的目标契约。 每个交互命令(clicktypeselectget text/value/attributes)均接受一个 <target>,它可以是来自 state/find 的数字引用(ref),也可以是 CSS 选择器。当存在多个 CSS 匹配项时,可使用 --nth <n> 消除歧义。
  2. 每个响应包都会提供 matches_nmatch_level match_level 的取值为 exactstablereidentified——CLI 已经帮你自动容忍并修复了中等程度的 DOM 漂移,但这个字段能让你清晰了解当前匹配的置信度。
  3. 默认输出精简内容,按需获取完整 Payload。 state 是兼顾上下文 Token 预算的快照;get html --as json 支持通过 --depth/--children-max/--text-max 进行截断;network 仅返回请求结构预览,具体 Body 可通过 --detail <key> 单独拉取。直接输出巨型 Payload 会无意义地消耗掉你不需要消耗的上下文。
  4. 结构化错误方便机器解析。 发生失败时,CLI 会输出 {error: {code, message, hint?, candidates?}}。请根据 code 字段进行逻辑分支判断,而不是去匹配错误字符串。

核心法则

  1. 先审查,后行动。 务必先运行 statefind。严禁凭借记忆跨 Session 硬编码数字 ref 或选择器——索引仅在当前快照内有效。
  2. 优先使用站点适配器,其次才是底层浏览器操控。 如果 opencli <site> <command> 已经支持该任务,请优先使用对应的适配器命令(例如 opencli facebook notificationsopencli reddit readopencli chatgpt model <level> 等)。仅在遇到适配器未覆盖的功能盲区、调试需求或临时 UI 流程时,才使用 opencli browser ...
  3. 拿到数字 ref 后,优先使用 ref 而不是 CSS。 因为 CLI 对每个打上标签的元素做了指纹记录,数字 ref 能在 DOM 发生轻微变动后依然存活。而手写的 CSS 选择器在页面重新渲染后极易直接失效。
  4. 每次写入操作后都应读取 match_level exact = 一切正常。stable = 元素未变,但部分非关键属性发生了漂移——你的操作已成功生效。reidentified = 原始 ref 已消失,CLI 找到了唯一的替换元素;请仔细二次确认是否命中正确的目标。
  5. 对表单控件善用 compound 字段。 不要用正则去猜日期格式,也不要运行两次 state 来获取完整的 <select> 选项列表。复合(compound)响应包中已包含格式化字符串、前 50 项完整选项列表、溢出计数 options_total,以及针对 <input type=file>accept/multiple 属性。
  6. 对关键的写入操作进行验证。 在执行 type <target> <text> 后,运行 get value <target> 检查。在执行 select 后,运行 get value。自动补全组件、React 受控输入框以及带掩码的输入框都有可能静默吞字,CLI 无法替你自动检测到这一点。
  7. 页面变更后遵循 state → 操作 → state 流程。 页面导航、表单提交以及 SPA 路由跳转都会导致旧 ref 失效。请务必重新获取最新的快照,切勿复用页面跳转前的 ref。
  8. 复用最新解析的 ref 时使用 && 链式调用。 链式命令会在同一个 Shell 进程中运行,以便刚刚从输出中读取到的 ref 能直接传递给下一条命令。跨 Shell 的独立调用虽然能维持命名的浏览器 Session,但在页面发生变动后,上一条命令里保存的 Shell 本地变量或复制的 ref 随时可能会失效。
  9. eval 仅限读取操作。 请将 JS 代码包裹在 IIFE(立即调用函数表达式)中并返回 JSON。如果你需要修改页面,请使用结构化的 click / type / select / keys 等命令——这些命令会生成结构化输出与元素指纹,而 eval 不会。
  10. 优先使用 network 捕获,而不是直接抓取屏幕 DOM。 如果你关注的页面是通过 JSON API 拉取数据的,直接抓取 API 数据通常比解析渲染后的 DOM 可靠得多。先捕获一次,审查数据结构,再通过 --detail <key> 获取你所需的具体 Body。

站点地图(Sitemaps)

如果 browser openbrowser 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) — 来自 statefind[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 valuestate 进行二次校验。
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.codeerror.message。目标相关的错误(selector_not_foundselector_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 语义化点击。写入操作要求唯一匹配;存在歧义的定位器会返回候选列表而不是直接执行。