v0.4.3 · chrome-control 对齐 51/51

任何 agent 的
all-in-one 浏览器控制层

一套命令,驱动 Moli 轻内核
每个动作回读核实;做不到,就显式拒绝 —— 从不假装成功。

64子命令
2后端 · 同一套命令
36Moli 冷启动 · 中位
192测试通过
99变异全部变红
0假成功容忍度
三分钟上手 看它怎么工作
向下滚动 ↓
Live Demo

agent 说一句,浏览器做一件,结果一行 JSON

不需要 SDK,不需要写 Playwright 脚本。任何能跑 shell 的 agent 都能直接用;每条命令的输出都是机器可读的一行 JSON,出错时还有可执行的 hint。
下面的输出取自本机实测(本地测试页),只做了截短(…)。


  
Honest by design

别的工具返回 ok 的地方,我们先回读

下面每一张卡都是实测复现过的「看起来成功」。点卡片翻面,看 moli-control 怎么处理。

裸用 CDP

装扩展返回了 id

Chrome 默认会话里 Extensions.loadUnpacked 照样返回 id,但扩展根本没装上。

点击翻面 →
moli-control

以列表回读为准

ext 只在 start --extensions 会话里可用;默认会话直接拒绝 extensions_disabled。

裸用 CDP

「全选」返回 ok

在轻内核上,编辑命令返回成功,但选区一动没动。

点击翻面 →
moli-control

回读选区,如实标注

无效就改走 JS 并标 mode: js;JS 也做不到(如 undo),报 edit_unsupported。

裸用 CDP

点了跨源 iframe 里的按钮

节点号只在子会话里有效,事件按视口中心派发 —— 报 ok,实际点在别处。

点击翻面 →
moli-control

换算坐标 + 命中校验

现场挂子会话、按父文档偏移换算,派发前确认最顶层就是目标,被遮挡就拒绝。

裸用 CDP

DOM 变了,文字还是旧的

冻结布局下 innerText 与几何不刷新,后加的节点点不中。

点击翻面 →
moli-control

动作前自动重建

读文本、坐标动作之前先重建布局;Chrome 后端恒为真实布局,跳过这一步。

裸用 CDP

刚关的标签页还在

closeTarget 是异步的,紧接着列标签页还能看到它。

点击翻面 →
moli-control

关闭后轮询确认

直到目标真的消失才返回;超时给出四要素错误。

裸用

404 和空壳页也是 rc 0

网络空闲超时、HTTP 404、空壳页,抓取都可能「成功」。

点击翻面 →
moli-control

分别留痕

标 best-effort / rc 22 / rc 5,调用方一眼区分「查过没事」和「根本没查」。

Two engines, one CLI

轻的时候用 Moli,要真的时候用 Chrome

同一条命令,换一个 --backend 就换引擎。两端的差异全部由代码处理,并在输出里如实标注 —— 你不需要记住哪边有什么坑。

Architecture

一层薄薄的控制层,把坑都挡在里面

agent 只看见一个 CLI。会话管理负责拉起、核身份、到期回收;动作与观察层负责回读与显式拒绝;后端可以是 Moli(上游或自编内核)或受管 Chrome。

moli-control 架构图
1
核实例身份PID + 指纹参数 + TTL:只认自己起的进程
✖ session_dead / expired
2
attach 当前标签页对话框自动处理,不挂死会话
✖ 写命令:target_gone
3
重放仿真与注入视口、UA、时区、限速、init-js 每条命令重放
4
后端能力判定做不到的给出替代方案
✖ unsupported_backend
5
执行 + 回读副作用回读不一致就报错,四要素齐全
6
一行 JSONrc 0,可直接喂给下一步
Capabilities

64 个子命令,覆盖一个浏览器能做的事

从一次性抓取到多步交互、网络拦截、设备仿真、站点原生工具(WebMCP)。外部的 Playwright / Puppeteer / Selenium 也能经 endpoint 直连同一个受管会话。

Falsifiable

每个判据都被故意打破过

测试全绿不说明什么 —— 也许测试本身失效了。所以每修一个缺陷,就登记一条「变异」:把缺陷打回去,对应的测试必须变红。整轮全红才发版。

① 修好的代码
if target not in pages:
  raise target_not_found
测试通过
② 注入变异
if target not in pages:
if False:
  raise target_not_found
测试必须变红
③ 判据是活的
✔ 变红 ← test_activate…
✔ 变红 ← test_context…
…
还原后再次全绿
变异整轮0 / 99 变红 · 0 失活
Safe by default

网页是数据,不是指令

agent 浏览的页面不可信。受管会话默认多层收紧,并且每次体检都带正对照现场验证 —— 防护有没有生效,用打一次来证明,而不是靠相信。

专用回环地址

端点只监听本机专用地址、随机端口,不对外暴露。

出站黑名单

页面无法连回运行自己的那个实例。

TTL 看门狗

会话到期自动回收,暴露窗口与存活时间成正比。

只认自己的进程

PID 复用也不会误杀、误连别人的浏览器。

代理不透传

受管会话剥掉代理环境变量,防护不会被隧道绕过。

可换更严格的内核

支持指向自编的 Moli 内核(MOLI_BIN),doctor 报告内核级校验是否在位。

Roadmap

一步一个可验证的里程碑

v0.1Moli 控制层:零端口抓取、受管会话、自我接管防护
v0.2功能面补齐:选项透传、外部客户端接入、交互命令、WebMCP、导入登录态
v0.3双后端:同一套命令驱动真 Chrome;chrome-control 子命令逐条登记
v0.4all-in-one:chrome-control 的全部命令吸收(51/51);自编内核起步
Get started

三分钟,让你的 agent 拥有浏览器

# 安装(需要 uv 与 Python ≥ 3.10)
git clone <repo> ~/Code/moli-control && cd ~/Code/moli-control && uv sync
bin/moli-ctl install --yes        # 没有 moli 时:官方安装器
bin/moli-ctl doctor               # 分层体检,期望全 pass

# 一次性抓取(零监听端口)
bin/moli-ctl fetch https://example.com

# 交互会话
bin/moli-ctl --name job start --layout
bin/moli-ctl --name job goto https://example.com
bin/moli-ctl --name job snap
bin/moli-ctl --name job click <ref> && bin/moli-ctl --name job wait-for 已提交

# 换成真 Chrome
bin/moli-ctl --name real start --backend chrome --profile work