🚀 快速安装
复制以下命令并运行,立即安装此 Skill:
npx skills add https://skills.sh/aradotso/trending-skills/chrome-cdp-live-browser
💡 提示:需要 Node.js 和 NPM
chrome-cdp: 面向 AI 代理的实时 Chrome 会话
技能来自 ara.so — 每日 2026 技能合集。
chrome-cdp 通过 Chrome DevTools 协议(CDP)将你的 AI 代理直接连接到正在运行的 Chrome 浏览器。与启动全新隔离浏览器的浏览器自动化工具不同,它连接到你已经打开的标签页——保留你的登录状态、Cookie 和当前页面状态。
功能
- 实时会话访问 — 读取并与你已登录的标签页进行交互
- 持久化守护进程 — 每个标签页一个 WebSocket 守护进程;“允许调试”提示仅出现一次,不会每次命令都弹出
- 无需 npm 安装 — 只需 Node.js 22+
- 支持 100+ 标签页 — 可靠处理大量打开的标签页
- 支持跨域 iframe —
type命令即使在跨域 iframe 内也能正常工作
安装
作为 pi 技能安装
pi install git:github.com/pasky/chrome-cdp-skill@v1.0.1
手动安装(适用于 Amp、Claude Code、Cursor、Codex 等)
git clone https://github.com/pasky/chrome-cdp-skill
# 将 skills/chrome-cdp/ 目录复制到你的代理加载上下文的任何位置
在 Chrome 中启用远程调试
- 打开 Chrome 并导航到:
chrome://inspect/#remote-debugging - 打开“启用远程调试”开关
就这样。无需额外标志,无需重启 Chrome。
该脚本可自动检测 macOS、Linux 和 Windows 上的 Chrome、Chromium、Brave、Edge 和 Vivaldi。对于非标准安装:
export CDP_PORT_FILE=/path/to/DevToolsActivePort
主要命令
所有命令都使用 scripts/cdp.mjs 作为入口点。<target> 是 list 命令显示的 targetId 的唯一前缀。
列出打开的标签页
node scripts/cdp.mjs list
# 输出示例:
# A1B2C3 https://github.com/pasky/chrome-cdp-skill chrome-cdp-skill
# D4E5F6 https://mail.google.com/mail/u/0/ Gmail
截取标签页截图
node scripts/cdp.mjs shot A1B2
# 将截图保存到运行时目录,并打印文件路径
无障碍树(语义快照)
node scripts/cdp.mjs snap A1B2
# 返回紧凑的语义化无障碍树 — 最适合理解页面结构
完整 HTML 或作用域内 HTML
node scripts/cdp.mjs html A1B2 # 完整页面 HTML
node scripts/cdp.mjs html A1B2 ".main-content" # 限制在 CSS 选择器范围内
node scripts/cdp.mjs html A1B2 "#article-body" # 限制在 ID 范围内
执行 JavaScript
node scripts/cdp.mjs eval A1B2 "document.title"
node scripts/cdp.mjs eval A1B2 "window.location.href"
node scripts/cdp.mjs eval A1B2 "document.querySelectorAll('a').length"
导航到 URL
node scripts/cdp.mjs nav A1B2 https://example.com
# 导航并等待页面加载完成
网络资源计时
node scripts/cdp.mjs net A1B2
# 显示当前页面的网络资源计时信息
点击元素
node scripts/cdp.mjs click A1B2 "button.submit"
node scripts/cdp.mjs click A1B2 "#login-btn"
node scripts/cdp.mjs click A1B2 "[data-testid='confirm']"
在坐标处点击
node scripts/cdp.mjs clickxy A1B2 320 480
# 在 CSS 像素坐标 (x=320, y=480) 处点击
输入文本
node scripts/cdp.mjs type A1B2 "Hello, world!"
# 在当前聚焦的元素上输入 — 在跨域 iframe 中也能工作
加载更多(点击直到消失)
node scripts/cdp.mjs loadall A1B2 "button.load-more"
# 持续点击选择器,直到它从 DOM 中消失
打开新标签页
node scripts/cdp.mjs open
node scripts/cdp.mjs open https://example.com
# 注意:会触发 Chrome 的“允许”提示
停止守护进程
node scripts/cdp.mjs stop # 停止所有守护进程
node scripts/cdp.mjs stop A1B2 # 停止特定标签页的守护进程
原始 CDP 命令透传
node scripts/cdp.mjs evalraw A1B2 "Page.getFrameTree"
node scripts/cdp.mjs evalraw A1B2 "Runtime.evaluate" '{"expression":"1+1"}'
常见模式
模式:读取已登录的页面
# 列出标签页找到你的目标
node scripts/cdp.mjs list
# 获取无障碍树以获得语义视图
node scripts/cdp.mjs snap D4E5
# 或获取特定部分的作用域 HTML
node scripts/cdp.mjs html D4E5 ".email-list"
模式:填写并提交表单
# 点击输入框
node scripts/cdp.mjs click A1B2 "input[name='search']"
# 输入文本
node scripts/cdp.mjs type A1B2 "我的搜索查询"
# 点击提交按钮
node scripts/cdp.mjs click A1B2 "button[type='submit']"
# 截图验证结果
node scripts/cdp.mjs shot A1B2
模式:使用 JavaScript 提取数据
# 获取页面所有链接的 href
node scripts/cdp.mjs eval A1B2 "Array.from(document.querySelectorAll('a')).map(a => a.href)"
# 获取特定元素的文本内容
node scripts/cdp.mjs eval A1B2 "document.querySelector('.price').textContent.trim()"
# 将表格数据作为 JSON 获取
node scripts/cdp.mjs eval A1B2 "
Array.from(document.querySelectorAll('table tr')).map(row =>
Array.from(row.querySelectorAll('td,th')).map(cell => cell.textContent.trim())
)
"
模式:导航并等待
# 导航并立即读取页面
node scripts/cdp.mjs nav A1B2 https://news.ycombinator.com
node scripts/cdp.mjs snap A1B2
模式:分页内容
# 持续加载内容直到“加载更多”按钮消失
node scripts/cdp.mjs loadall A1B2 "button[data-action='load-more']"
# 然后提取所有加载的内容
node scripts/cdp.mjs eval A1B2 "document.querySelectorAll('.item').length"
模式:脚本集成(Node.js)
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
const exec = promisify(execFile);
const CDP = (...args) => exec('node', ['scripts/cdp.mjs', ...args]);
async function getPageTitle(tabPrefix) {
const { stdout } = await CDP('eval', tabPrefix, 'document.title');
return stdout.trim();
}
async function takeScreenshot(tabPrefix) {
const { stdout } = await CDP('shot', tabPrefix);
return stdout.trim(); // 返回文件路径
}
async function navigateAndSnap(tabPrefix, url) {
await CDP('nav', tabPrefix, url);
const { stdout } = await CDP('snap', tabPrefix);
return stdout;
}
// 使用示例
const tabs = (await CDP('list')).stdout;
console.log(tabs);
配置
| 环境变量 | 用途 |
|---|---|
CDP_PORT_FILE |
非标准浏览器安装时的 DevToolsActivePort 文件路径 |
守护进程在20 分钟无活动后会自动退出——正常使用中无需手动清理。
故障排除
“允许调试”提示反复出现
如果守护进程没有持久化,就会发生这种情况。确保你使用相同的 scripts/cdp.mjs 入口点——它会自动管理守护进程生命周期。如果你在会话中途切换了工具,运行 stop 并让守护进程重新启动。
未检测到浏览器
如果自动检测失败,找到你的 DevToolsActivePort 文件并设置环境变量:
# macOS Chrome 示例
export CDP_PORT_FILE="$HOME/Library/Application Support/Google/Chrome/Default/DevToolsActivePort"
# Linux Chrome 示例
export CDP_PORT_FILE="$HOME/.config/google-chrome/Default/DevToolsActivePort"
未找到目标 / 前缀不明确
再次运行 list——当标签页关闭或重新打开时,标签页 ID 会改变。如果多个标签页共享相同的前缀字符,请使用更长的前缀。
远程调试开关不可见
确保你在 chrome://inspect/#remote-debugging(而不仅仅是 chrome://inspect/)。开关在页面的右上角。
Node.js 版本错误
此项目需要 Node.js 22+。使用 node --version 检查,如果需要升级,可通过 nvm 或你的包管理器进行升级。
截图为空白或尺寸错误
截图反映实际渲染的视口。如果标签页在后台窗口,或者操作系统启用了显示缩放,clickxy 的像素坐标可能需要调整。使用 snap 或 eval 检查 DOM 状态,而不是仅仅依赖截图。
架构说明
- 无 Puppeteer、无 Playwright、无中间层 — 纯 CDP WebSocket
- 每个标签页一个持久化守护进程(首次访问时自动启动)
- 守护进程重用正是支持 100+ 标签页可靠工作的原因(没有目标枚举超时问题)
type直接使用 CDP Input 域,绕过 iframe 跨域限制
📄 原始文档
完整文档(英文):
https://skills.sh/aradotso/trending-skills/chrome-cdp-live-browser
💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

评论(0)