---
name: browser
description: "Drive the user's local Chrome through mooncat-browser using either the JS/TS BrowserClient or Python Browser client, both connected to the same browserd RPC service. Use for turning written or screenshot SOPs into browser automation, page probing, collection, form automation, downloads, and screenshots."
---

# browser

通过 `mooncat-browser` 的 JS/TS `BrowserClient` 或 Python `Browser` 驱动**用户本地 Chrome**（用户看得见的浏览器，
不是无头集群），做页面探查、采集、表单自动化、截图。

两个 client 都是薄 HTTP RPC client，连接同一个常驻 **browserd 服务**（`mooncat-browser start`
拉起）。browserd 才是真正持有 Chrome 的进程，client 只发指令；两种语言不是两套后端。

**这不是批处理脚本，是 co-work**——和用户一起，看着同一个打开的浏览器，一步一步推进。

## 三个铁律

1. **handle 是纯数据，绝不判断路由。** 拿到 `pageHandle` 就直接用，所有页面动作走
   `browser.operate({ pageHandle, action, params })`。绝不写
   `if (ph.mode === 'cdp') {...}`——路由（extension/CDP）是 browserd 内部的事。
   handle 不可变，没有"切当前 tab"的操作，要操作哪个 page 就拿它的 pageHandle。

2. **会话长生命周期，用户满意前不释放。** `browser.open()` 一次，跨多步复用
   handle。**绝不**每步都 open/close——启动 Chrome 慢，反复开关丢登录态/cookie。
   只在用户说"完成"或要换完全不同的浏览器实例时才 `browser.close()`。`open()` 是幂等的：
   浏览器还活着就复用当前 handle，被关了才重启。

3. **步进式 co-work，一步一确认。** 一次一步，每步落盘中间产物（snapshot/截图/数据），
   给用户看、等反馈。**绝不**把所有操作塞进一个调用——任何中间步失败（弹窗/验证码/加载慢）
   都会让已改的状态不一致，且用户根本没看到过程。

## 怎么用

### 两种客户端入口

| 使用语言 | 安装 | CLI | 程序化客户端 |
|---|---|---|---|
| JS/TS | `npm install mooncat-browser` | `npx mooncat-browser ...` | `BrowserClient` |
| Python | `pip install mooncat-browser-client` | `mooncat-browser ...` | `Browser` |

下面保留 JS/TS 主示例，并在对应位置给出 Python 等价示例。CLI 命令语义一致：
JS 项目可使用 `npx mooncat-browser`，pip 环境直接使用 `mooncat-browser`。

> **前置**:mooncat-browser 是实例化、项目级配置的独立包。**不写全局 appData**,
> 必须先 `init` 生成项目配置,再 `start`。找不到配置会 fail fast。
>
> **实例(instance)= 一个 Chrome 进程边界**:一组端口 + 一个 profile + 一套 state/logs。
> **不是 task**——task 是调用方(workspace/agent)的概念,本包不规定、不关心。
> 一个项目**默认就一个 `default` 实例**(够用);只有需要**同时跑两个独立 Chrome**
> 时才加实例(各自独立 profile,互不串登录态/cookie)。

### 路由:显式二选一,无 auto

`routeMode` 只有 `cdp` | `extension`,**必填,不猜**:
- `cdp` — 暴露调试端口,静态页/调试/非风控站点
- `extension` — 走 WebPlater 扩展(无调试端口),**高危平台(淘宝/京东/银行)必选**

不指定 = 报错。不再有 auto 自动检测(自动检测是歧义来源)。

### 启动服务(CLI,另一个终端常驻)

```bash
# 一次性:在项目目录初始化(生成 config/browser.json + .browser/default/ 数据目录)
npx mooncat-browser init                    # 默认建 default 实例,绝大多数项目就这一个

# 启动实例(常驻)
npx mooncat-browser start default

# 高危平台走 extension 路:先 prepare 扩展目录 + 手动 load unpacked(见 high-risk.md)
npx mooncat-browser prepare-extension default
npx mooncat-browser start default

# 管理命令:list / stop <name> / status <name>
npx mooncat-browser list
```

Python/pip 等价命令：

```bash
pip install mooncat-browser-client
mooncat-browser init default
mooncat-browser start default --route-mode cdp
mooncat-browser prepare-extension default
mooncat-browser list
```

### 浏览器自动化(程序化,主路径)

CLI 只管服务生命周期。**浏览器操作走 BrowserClient**,在脚本/agent 里 import 用:

```ts
import { BrowserClient } from "mooncat-browser";

// 端口 = 实例 rpcPort(看 config/browser.json,或 list 查)
const browser = new BrowserClient({ baseUrl: "http://127.0.0.1:17322" });

// open 必须显式 routeMode(无 auto)
await browser.open({ routeMode: "extension", headless: false });  // 高危平台
// 或:await browser.open({ routeMode: "cdp", headless: false });

const tab = await browser.newTab({ url: "https://example.com" });

// 所有页面动作走 operate (action 清单见 references/operate-actions)
const snap = await browser.operate({ pageHandle: tab.pageHandle, action: "snapshot" });
await browser.operate({ pageHandle: tab.pageHandle, action: "click", params: { selector: "#login" } });
```

Python 等价写法：

```python
from browser import Browser

browser = Browser(host="127.0.0.1", port=17322)
tab = browser.new_tab("https://example.com")

# Python client 可直接接收 new_tab 返回的 TabInfo，也可传 tab["pageHandle"]
snapshot = browser.operate(tab, "snapshot")
browser.operate(tab, "click", selector="#login")
```

> 服务必须先 `start` 常驻。没启动时 `health()` 返回 null,`operate` 连接拒绝。

### CLI open(手动验证用,非主路径)

`npx mooncat-browser open <name> --url <url> --route-mode <cdp|extension>` 是**手动验证**用——
快速开个页面看 Chrome 能不能起、扩展连没连。**不是程序化自动化的方式**;
正经自动化使用 JS/TS `BrowserClient` 或 Python `Browser`。open 的 `--route-mode` 必填(无 auto)。

**SDK 能力清单见** [references/operate-actions.md](references/operate-actions.md) —— 分两段:
BrowserClient **直接方法**(`reuseTab`/`listDownloads`/`waitFor`/`waitForDownload` 等,不走 operate)
+ **operate(action)** 的 40+ 个 action(导航/交互/读取/等待/存储/截图)。
**两套是不同入口,别把 operate 表当全集**——reuseTab/listFrames 这些是 client 直接方法,不在 operate 表里。
始终权威源:`browser-op/backend/browserd.cjs` 的 `rpcOperate`(action) + `src/client.ts`(直接方法)。

## 步进式 co-work 的标准节奏

用户："帮我把这个网站我的订单都导出来。"

```
[回合1] 探查: open + newTab + status → "看到登录页,我先探查,你手动登录后告诉我?"
[回合2] 用户:登录好了 → 进订单页: waitForSelector + snapshot 落盘 → "看到50条订单,要导出吗?"
[回合3] 用户:导出 → 点导出: click + 截图确认 → "导出按钮点了,等下载"
[回合4] 用户:好了 → 收尾: 用户满意才 close
```

全程 browser 只 open 一次（幂等复用），跨越所有回合，最后一回合才 close。
**每一步的中间产物落盘**（snapshot yaml / 截图 / 抓取的数据），便于审计 + 给用户看。

## 从 SOP 开始时

收到文字、截图或表格形式的操作流程时，先完整读完全部材料，再探查页面，最后写代码。
不要一边看第一张图一边实现，避免漏掉后续步骤、分支或第二个下载产物。

把每个目标写成：

```text
开始页面 → 转换动作 → 动作后页面 → 成功判据 → 目标操作
```

“找到”“看到”“加载完成”通常表示等待就绪，不等于点击。截图中的红框、红字编号和箭头是
操作路径证据，编号顺序就是操作顺序。详细转写、探查和实现一致性规则见
[references/probing.md](references/probing.md)。

## 路由不泄漏

`operate` 的 action 在 extension/CDP 两条路由上行为统一（少数例外见 high-risk.md 的 ext 列）。
**绝不**：

- 绝不 `if (ph.mode === 'cdp') { ph.page.click() }` —— 路由泄漏
- 绝不直接调 browserd 内部模块 —— 那是 BrowserClient 背后的实现
- 绝不修改 handle —— `ph.tabId = xxx` 是错的

路由相关（如换 profile、切 extension↔cdp）只能 `close()` 后重新 `open()`，不能中途换。

## 出错时怎么办

**STOP。报告具体错误。等用户指示。** 绝不强杀 Chrome 进程（`taskkill` 丢登录态、留僵尸端口、
用户未保存表单丢失），绝不自动重试轰炸。`open()` 失败时看返回的 notice/error。

句柄过期（用户手滑关了浏览器、CDP 断）时不要推倒重来——重新 `open()` attach 即可（便宜），
不要 close+relaunch。

## 失败可见化（通用纪律，不依赖任何通知框架）

任何一步失败（登录态丢失 / selector 失效 / 下载超时 / 风控拦截 / RPC 错），统一动作：

1. **截图取证**（`screenshot`，extension 模式先 `activate`）——落盘到本地路径。
2. **报告用户**：错误 + 截图路径 + 判断（验证码？登录失效？被限流？DOM 变了？）。
3. **STOP**——绝不吞错静默跳过，绝不重试轰炸（高危平台重试会加速封号）。

> 如果你在一个更大的系统里（有自己的通知渠道，如飞书/Slack/webhook），
> 把"报告用户"换成你的通知机制即可。本 skill 只规定"必须可见化 + 叫人"的纪律，
> 不规定具体通知后端——`mooncat-browser` 是独立工具包，不带任何通知能力。

## 参考

- [references/collect.md](references/collect.md) — **★标准采集工作流**：三件套范式（复用 tab / 清弹窗 / 等就绪），SPA 采集必读
- [references/probing.md](references/probing.md) — **★SOP 转自动化与探查方法论**：完整读取 / 状态与动作区分 / frame 意识 / 同名消歧 / 截图识图 / 探查与实现 1:1
- [references/high-risk.md](references/high-risk.md) — 高危平台专题（淘宝/京东/银行）：扩展路由 + 验证码 + 拟人化
- [references/operate-actions.md](references/operate-actions.md) — **★SDK 能力清单**：BrowserClient 直接方法（reuseTab/listDownloads/waitFor 等，不走 operate）+ operate(action) 40+ 个 action。**两套分开看，别把 operate 表当全集**
