← 所有文章
·cdpchromearchitecture

为什么 Hover 通过 CDP 驱动你真实的 Chrome,而不是另起一个 headless 上下文

做一个驱动浏览器的工具,省事的路子很明显:每个会话都拉起一个全新的 headless Chromium,干净、隔离、可复现。可这条路用来测你正在做的应用是错的,所以 Hover 没走它。

全新 headless 上下文的麻烦

全新的 headless 浏览器一起步就是空的:没有会话,没有登录,没有 localStorage,没有 cookie。测个营销页面无所谓。可你正在做的应用——藏在登录之后,购物车里塞着东西,表单填了一半,某个 feature flag 还开着——在它眼里是一张白纸,跟你屏幕上那个八竿子打不着。

于是你写脚本一步步把状态补回来:登录、灌数据、切 flag,每个会话都来一遍,就为了回到你的 dev 浏览器本来就停在的那个状态。到头来 agent 测的是你亲手重建的一个合成环境,而不是你正在做的那个应用。

Hover 连的是一个真实的、已经在跑的 Chrome

Hover 走的是另一条路:通过 Chrome DevTools Protocol 连上一个已经开着的 Chrome,落到 URL 和你 dev-server origin 对得上的那个标签页。agent 就在这个标签页的真实状态里操作。

你登录一次,会话就一直在,agent 直接继承。它看到的 DOM、cookie、localStorage,和你看到的一模一样。弹窗、支付方的跳转、new-tab 回调全都正常,因为这是一个有真实标签页的真实浏览器,不是隔离的上下文。agent 从不自己启动 Chromium,而是挂到正在跑的浏览器上,在里面干活。

不是你日常那个 Chrome

Hover 驱动的这个 Chrome,不是你天天用的那个。它会在一个临时 user-data 目录下另起一个隔离的调试 Chrome,开着远程调试,指向你的 dev URL。这是个专用 profile,跨会话复用,跟那个装着你邮箱、网银标签页、五十个扩展的 Chrome 各过各的。

为什么不直接挂到你的主浏览器上?那会逼你带着远程调试端口重启每天在用的 Chrome,还会把你主会话里的每个标签页、cookie、扩展一股脑交给 agent。Hover 把这笔账摆在明面上:你在调试 Chrome 里给自己的应用登录一次,此后这个 profile 就跨命令、跨 dev-server 重启地替你保住会话,同时又不让你的主 profile 落到 agent 手边。

Hover 会告诉你什么

Hover 知道你的 dev-server origin,它的引擎又能从 /json/list 得知哪个 Chrome 是自己能通过 CDP 够到的。两下一对照,就替你回答了一个本来得自己琢磨半天的问题:到底有没有一个调试 Chrome 开着、而且正停在你的应用上?

三个答案,对应三种状态。同一个窗口:origin 对上了,agent 可以驱动这个标签页。错的窗口:调试 Chrome 是有,但没停在你的应用上,Hover 会把对的标签页翻到前台。没有调试 Chrome:一个都没跑,Hover 就在你的 dev URL 上把它拉起来。端口、协议这些你都不用操心,Hover 会一路把你带到能用的状态。

背后的原则

测你应用的 agent,就该测你正在做的这个应用——在你此刻做它时的状态里,以用户真正会遇到的样子。一个通过 CDP 够到的、真实却又隔离的调试 Chrome,正是 Hover 做到这点的办法:不必重建合成环境,也不必碰你天天在用的那个浏览器。

了解 Hover 的 Chrome 生命周期 →

在你自己的应用上试试 Hover。

把 Hover 的 MCP 加到你已经在用的编码 agent。它探索你的应用,结晶出你自己拥有的纯 Playwright spec。

npm i -g @hover-dev/mcp && claude mcp add hover -- hover-mcp阅读快速开始 →