
Security News
Happy Birthday, Shai-Hulud
It has been one year since Shai-Hulud made its first appearance on npm.
@mearl/client
Advanced tools
统一浏览器 SDK 与 CLI。它会发现当前机器及已配置 cloud-server 下所有 connector 的浏览器,并根据 browser_list 返回的全局 browserId 自动选择本地 Socket 或云端 WebSocket 链路。
提供两种用法:类型安全的具名方法(getRequests、sendRequest 等),以及灵活的底层 invoke(action, payload)。
npm install @mearl/client
# 或
pnpm add @mearl/client
import * as client from '@mearl/client';
// 具名方法(类型安全)
const requests = await client.getRequests({ count: 5 });
const result = await client.sendRequest({
url: 'https://api.example.com',
method: 'GET',
withCookies: true,
});
// 底层通用方法(灵活扩展)
const data = await client.invoke('send_request', { url: '...' });
// browser_list 默认聚合本机和所有远端 connector
const browsers = await client.browserList();
await client.getLogs({}, { browser: browsers.browsers[0].browserId });
安装后提供 mearl 命令:
# 获取最近 5 个请求
mearl get_requests --payload '{"count":5}'
# 代理一个 HTTP 请求
mearl send_request --payload '{"url":"https://api.example.com","method":"GET"}'
# 以 multipart/form-data 上传本地文件
mearl send_request --payload '{"url":"https://api.example.com/upload","method":"POST","formData":{"folder":"assets"},"files":[{"fieldName":"file","filePath":"/absolute/path/image.png"}]}'
# 截图并保存(tabId 来自 tab_open 或 tab_list)
mearl page_screenshot --payload '{"tabId":12345}' --output ./screenshot.png
# 从文件读取大体积参数(如 mock 数据)
mearl set_mock --payload-file ./mock-data.json
# 环境自检
mearl check
mearl check --local --json
# 更新本地环境
npx @mearl/setup update --local
# 查看某个 action 的帮助
mearl <action> --help
# 启动两个隔离的 headless Chrome
mearl browser_launch --payload '{"name":"browser-a","url":"https://example.com"}'
mearl browser_launch --payload '{"name":"browser-b","persistent":true}'
mearl browser_launch --payload '{"name":"cookie-copy","copyCookieDomains":["example.com"]}'
mearl browser_launch --payload '{"name":"figma","userAgentMode":"desktop","copyCookieDomains":["figma.com"]}'
mearl browser_list
mearl browser_release
Provider 浏览器与扩展、CDP 浏览器一起出现在 browser_list 中,并使用同一个
全局 browserId 参与路由。Provider 的安装、更新和卸载由 @mearl/setup 管理:
npx @mearl/setup provider install @ali/mearl-provider-brow
npx @mearl/setup provider install @ali/mearl-provider-agentbay
# 查看 Provider 当前版本的能力、参数与使用流程
mearl brow
mearl agentbay --help
# Provider 启动参数统一放在 providerOptions
mearl browser_launch --payload '{"provider":"brow","providerOptions":{}}'
mearl browser_list
# 后续操作使用 browser_list 返回的全局 Browser ID
mearl tab_list --browser '<browserId>'
mearl page_snapshot --payload '{"tabId":12345}' --browser '<browserId>'
npx @mearl/setup provider update brow
npx @mearl/setup provider uninstall brow
browser_launch 创建 pairing 实例时会直接返回 pairing.url 和可选的配对码;Agent 应把 URL 直接渲染为
二维码交给用户,扫码后确认同一 Browser ID 变为 connected,再开始页面操作。在设备连入前
该实例不会成为默认操作目标;可用 browser_close 删除对应 Provider 实例。每个 Provider
只接收它为该浏览器显式声明支持的 actions,截图能力同时标明为原生截图、重建画面或不支持。
输入不存在或拼写有误的 action 时,CLI 会基于可用命令和常见别名直接返回最多三个候选及调用示例,
不连接浏览器,也不会自动执行推荐命令。例如 mearl tab new 会优先推荐 mearl tab_open。
常用选项:
| 选项 | 说明 |
|---|---|
--payload <json> | 直接传入 JSON 参数 |
--payload-file <path> | 从文件读取 JSON 参数 |
--timeout <seconds> | 请求超时时间 |
--compact | stdout 紧凑输出 |
--output <path> | 将结果写入文件(如截图) |
--browser <id|名称> | 指定目标浏览器 |
Mearl 默认聚合当前机器和已配置 cloud-server 下的浏览器,并通过 browser_list 返回的全局
browserId 自动路由。以下覆盖参数仅在限定宿主或连接、传输排障时使用,因此不出现在默认 help:
| 选项 | 说明 |
|---|---|
--connector <id|名称> | 限制到一台远端机器 |
--local | 只使用当前机器 |
--cdp | 当前机器强制使用 CDP,并隐含 --local |
--server <url> | 覆盖自动读取的 cloud-server 地址 |
browser_list --help 和 browser_launch --help 会按场景展示宿主选择参数;连接或传输排障运行
mearl check --help。其中 --json 仅用于输出机器可读的检查结果。
安装 skill 并自动注册命令,或直接注册已有入口:
npx @mearl/setup plugin install trip/mearl --skill yuque-doc-fetch --yes
npx @mearl/setup plugin install trip/mearl --skill buc-request --yes
npx @mearl/setup plugin yuque /absolute/path/to/yuque-doc-fetch
npx @mearl/setup plugin uninstall yuque
mearl yuque read "https://aliyuque.antfin.com/group/book/doc"
mearl yuque --payload '{"command":"read","input":{"url":"https://aliyuque.antfin.com/group/book/doc"}}'
mearl yuque --help
mearl yuque --version
当已注册插件与 Provider 使用同一名称时,mearl <name> --help 会先显示 Provider 的启动和生命周期说明,
再自动追加插件注册的扩展命令;mearl <name> <command> --help 继续显示单个插件命令的详细帮助。
Provider 与插件仍可独立安装、更新和卸载,帮助聚合不会启动 Provider 或执行业务命令。
目录默认使用 scripts/main.mjs 或 scripts/main.py;两者同时存在时使用 JavaScript 入口。JavaScript 入口默认导出 register(app),Python 入口导出 register(app) 函数;两种入口都可声明简短的 name 和 description,并通过 app.command(signature, handler, description?)
注册动作、app.invoke(action, payload, options?) 复用当前浏览器上下文,并用 app.progress(message) 报告可选进度。Python 的 app.invoke 是同步调用,handler 可以是普通函数或 async def。Python 插件要求 python3 >= 3.9,可用 MEARL_PYTHON 指定解释器路径;Mearl 不安装 Python 或执行 pip install。调用另一个插件时,payload 使用 { command, input } envelope;嵌套调用继承宿主选项并拒绝循环依赖。CLI 默认只输出最终结果,传入
--verbose 时才把进度写入 stderr。handler 返回文本或 JSON,宿主统一处理 --output、连接和错误。写命令在用户调用后直接执行,业务模块负责目标、状态、幂等和结果校验。
自动注册默认以 skill 安装目录名作为命令名,也可在入口声明 name 指定短名称。
setup 会补齐缺失或低于自身版本的 client、native-host;安装参数透传给 Ali Skills,并固定全局共享安装。
需要单独检查插件时运行 mearl <name> --version。命令会解析注册记录并加载入口,但不连接浏览器;
退出码为 0 表示插件已注册且入口可加载,stdout 返回同目录 SKILL.md 的版本,缺少版本元数据时返回 unknown。
未注册、入口丢失或加载失败会以退出码 2 和对应的 PLUGIN_* 错误结束。普通业务调用无需预先检查,直接处理同样的错误即可。
插件接受位置参数、字符串业务选项或包含 command/input 的 --payload。业务选项推荐写成
--name=value,也接受 --name value,字段名与 handler 的 input 一致且不依赖位置顺序;同一字段不能同时
使用位置参数和业务选项,--payload 不能与前两种形式混用。JSON 保留业务字段类型;正文等文件输入按具体
skill 的字段约定处理。browser、timeout、output 等宿主选项保留原有含义;同名业务字段以及数字、
布尔值、对象和数组通过 --payload 传入。插件不使用上表中内置 action 的 --payload-file 入口。
注册后的插件也可从 SDK 调用;实例方法 client.invokePlugin 复用既有连接和默认浏览器:
import { invokePlugin } from '@mearl/client';
const result = await invokePlugin(
'yuque',
{ command: 'read', input: { url: 'https://aliyuque.antfin.com/group/book/doc' } },
{ browser: 'work' },
);
MCP Server 通过固定工具 mearl_plugin 接受同样的 plugin、command 和 input,不会把插件子命令动态扩展成 MCP 工具。SDK 与 MCP 不接受任意入口路径;调用尚未注册的 buc 或 tdbank 时,会通过匹配当前 client 版本的 setup 自动安装并重试一次。其他未注册名称返回 PLUGIN_NOT_REGISTERED。
注册记录在 ~/.mearl/plugins/<name>.json,保存入口路径和可选的简短描述;skill 业务代码原地更新直接生效,换路径或更新描述后重新注册。
plugin uninstall <name> 会对 ~/.agents/skills 中的全局 Skill 调用 ali-skills remove --global --yes,
成功后清除相关注册;即使入口目录已被手动删除,也会完成 Ali Skills 跟踪记录的清理。
手工路径只解除注册并保留源码。
PLUGIN_NOT_REGISTERED 表示插件尚未注册。PLUGIN_ENTRY_MISSING 会显示失效入口,并给出带有实际插件名的
卸载清理命令。其他错误按实际原因处理。
编写规范见 Mearl Skill Creator 的 Skill 插件规范。
需要 BUC 身份的内部 HTTP 接口通过官方 buc 插件调用。CLI 使用 mearl buc request,业务插件使用
app.invoke('buc', { command: 'request', input });当前身份和人员资料分别使用 whoami 与 profile
子命令。BUC 插件按请求创建一次性凭据,只接受无 URL 凭据的 HTTPS 地址,过滤认证字段与 Cookie;
调用方须按已验证的业务契约确认目标服务可信。请求始终在运行 CLI、SDK 或 MCP Server 的机器上执行,
不随浏览器或 connector 转发。
buc request 支持与 send_request 同结构的 formData 和 files;files[].filePath 从该插件执行
宿主读取,而不是浏览器 native-host,无法引用宿主路径时使用 Base64 内容与 filename。
| 分类 | Actions |
|---|---|
| API 调试 | tab_checkpoint get_requests get_logs get_events |
| Mock & 规则 | set_mock get_mocks set_rule get_rules |
| 网络请求 | send_request send_mtop_request request_domain_permission |
| 标签页 | tab_open tab_list tab_close |
| 页面感知 | page_snapshot page_inspect page_screenshot page_frames |
| 页面操作 | page_click page_drag page_type page_hover page_scroll page_press page_wait page_navigate page_upload page_eval |
| 组合调用 | run_actions |
| 环境与 Cookie | set_device_emulation set_app_profile set_timezone get_cookie set_cookie |
| 浏览器 | browser_list browser_launch browser_release browser_close |
页面交互动作(page_click / page_drag / page_type / page_hover / page_scroll / page_press / page_upload)默认等待异步稳定并返回 { action, observation }。参数、ref 或目标解析在派发前失败时返回 action.stage: "precondition",省略无意义的 observation / diagnostics;浏览器可能已收到输入但确认超时时返回 action.stage: "dispatch-uncertain",并保留 observation 供核验当前状态。能够在超时前确定的目标、命中、坐标、派发模式和输入序列状态保存在 action.attempt,它是诊断证据,不表示动作已经生效。失败时 CLI 退出码为 1。传 observe: false 可执行裸动作;需要同一动作期间的新增 error logs 和业务 requests 时传 diagnostics: true,埋点通过 diagnostics.events 按需开启。page_eval 默认裸执行,可按需开启观察或诊断。
tab_open active:true 会激活目标 Tab、恢复最小化窗口,并通过 activation 返回实际标签页、窗口和 visibilityState;依赖可信触摸时先确认页面为 visible。页面动作的稳定观察会在有限预算内等待有限时长 CSS 动画。selector/ref 点击遇到嵌套滚动裁剪时会先滚动目标,仍不可见时才以明确的裁剪错误停止。
page_click 默认 auto 在隐藏页使用 DOM fallback,selector、文本、ref 和坐标定位都保持可用,并通过 dispatchMode: "dom"、fallbackReason: "page-hidden" 明确说明实际路径。普通后台任务不需要为了点击主动激活页面;只有站点明确拒绝非可信事件时才切换到可见页并强制 mouse / touch。
observation.effects.interactives 会把内容未变化但 DOM 节点被框架重建的控件标记为 recreated,保留 selector/ref 与语义信息供后续定位,同时省略未变化的 value 和状态字段;值或状态确实变化时仍返回完整差异。
page_press.pressMode 支持 auto / dom / keyboard。默认 auto 在隐藏页使用 DOM 键盘事件,并通过返回的 dispatchMode、fallbackReason 和 defaultAction 说明实际派发及默认行为模拟结果;依赖浏览器原生编辑、选择或滚动行为时使用可见页面和 keyboard。
page_snapshot 默认返回完整 AX Tree;长列表可传 mode: "viewport",只需要当前视口内的控件时传 mode: "interactive",AX 信息为空或过于稀疏时可显式传 mode: "dom",返回实际渲染文本、原生控件、显式 role 和高置信 clickable 节点。DOM 模式同样返回可供后续动作使用的 @ref,但不会猜测任意容器的业务语义。已知 CSS 区域时传 rootSelector,已有 ref 时传 rootRef(可用 ancestorDepth 向上补充上下文),只查找特定文案或角色时传 query。interactive 在视口内缺少 AX 控件语义时仍只回退到 AX viewport,并返回 fallbackMode: "viewport",不会自动切换数据来源。maxNodes / maxChars 截断会同时保留首尾内容。
page_inspect 用 CSS、snapshot @ref 或 DevTools 当前选中元素 $0 返回命中数、边框盒、指定计算样式、中心点遮挡、横纵溢出像素和最近滚动容器。省略 selector 并传 filter: "horizontal-overflow" / "vertical-overflow" / "scrollable" 可直接做全页布局诊断。按文本定位时先用 page_snapshot.query 取得 matches / matchCount 和 ref,再把 ref 交给 page_inspect,不需要手写 page_eval。
重复文本点击可用 page_click.scope 限定 CSS / ref 子树;浏览器扩展后端中,容器或 iframe 内的点坐标使用 coordinateSpace: "active-frame",CSS/text 查询可用 frameId 显式指定 frame。点击结果通过 requestedTarget、resolvedTarget、dispatchTarget、hitTarget 和 coordinates 区分请求语义、DOM 解析、派发节点与可信输入实际命中;selector/ref 目标被嵌套滚动容器裁剪时会自动滚动到可点击区域,只有仍被 overflow 裁剪时才要求显式处理。需要主动浏览列表时,page_scroll.containerPolicy: "nearest" 可自动解析最近可滚动祖先。未指定 selector 时,page_scroll 会优先选择代表性视口位置命中的最近内部滚动容器,再使用文档滚动区域或层级最高且可视面积最大的滚动容器。
browser_list 统一列出普通浏览器、Provider 浏览器和托管浏览器。type 区分
regular / managed,status 区分 connected / pairing / running_disconnected /
stopped;只有 connected 的浏览器可作为常规操作目标。
browser_release 仅在用户明确要求结束调试、退出接管或清理会话资源时调用;它会释放
debugger/CDP 控制和会话级临时状态,保留浏览器及全部标签页。托管实例的启动、关闭、持久化、
接入和登录态同步语义由各 Provider 声明;运行 mearl <providerId> 获取当前说明。访问入口不在
browser_list 中,需要时显式运行 mearl check --browser <id|名称>,并把返回的
browserAccess.url 按敏感信息处理。
@mearl/client (CLI / SDK)
├─ 本机 → @mearl/native-host → Chrome Extension / CDP
├─ 本机 → @mearl/provider runtime → External Provider
└─ WebSocket → @mearl/cloud-server → @mearl/cloud-connector
├─ @mearl/native-host → Chrome Extension / CDP
└─ @mearl/provider runtime → External Provider
基础设施组件必须避免递归路由:@mearl/cloud-connector 使用 @mearl/client/local 子路径直连所在机器的 native-host。普通 Agent、CLI 与 MCP 集成均使用包根入口。
pnpm build # tsc 编译到 dist/,并赋予 cli.js 执行权限
pnpm dev # tsc --watch
pnpm typecheck # 仅类型检查
ISC
FAQs
Unified Mearl SDK & CLI for local and remote browsers
The npm package @mearl/client receives a total of 986 weekly downloads. As such, @mearl/client popularity was classified as not popular.
We found that @mearl/client demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.