web-access-claude-skill
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWeb Access Skill for Claude Code
适用于Claude Code的Web访问Skill
Skill by ara.so — Daily 2026 Skills collection.
A skill that gives Claude Code complete internet access using three-layer channel dispatch (WebSearch / WebFetch / CDP), Chrome DevTools Protocol browser automation via a local proxy, parallel sub-agent task splitting, and cross-session site experience accumulation.
由ara.so开发的Skill — 属于Daily 2026 Skills系列。
本Skill通过三层通道调度(WebSearch / WebFetch / CDP)、基于本地代理的Chrome DevTools Protocol浏览器自动化、并行子Agent任务拆分以及跨会话站点经验积累,为Claude Code提供完整的互联网访问能力。
What This Project Does
本项目功能
Claude Code ships with and but lacks:
WebSearchWebFetch- Dispatch strategy — knowing when to use which tool
- Browser automation — clicking, scrolling, file upload, dynamic pages
- Accumulated site knowledge — domain-specific patterns reused across sessions
Web Access fills all three gaps with:
| Capability | Detail |
|---|---|
| Auto tool selection | WebSearch / WebFetch / curl / Jina / CDP chosen per scenario |
| CDP Proxy | Connects directly to your running Chrome, inherits login state |
| Three click modes | |
| Parallel dispatch | Multiple targets → sub-agents share one Proxy, tab-isolated |
| Site experience store | Per-domain URL patterns, quirks, traps — persisted across sessions |
| Media extraction | Pull image/video URLs from DOM, screenshot any video frame |
Claude Code原生支持和,但缺少以下能力:
WebSearchWebFetch- 调度策略 — 不清楚何时使用哪种工具
- 浏览器自动化 — 点击、滚动、文件上传、动态页面处理
- 站点知识积累 — 跨会话复用特定域名的交互模式
Web访问Skill填补了这三项空白,具备以下能力:
| 能力 | 详情 |
|---|---|
| 自动工具选择 | 根据场景自动选择WebSearch / WebFetch / curl / Jina / CDP |
| CDP代理 | 直接连接本地运行的Chrome,继承登录状态 |
| 三种点击模式 | |
| 并行调度 | 多目标任务 → 子Agent共享一个代理,标签页相互隔离 |
| 站点经验存储 | 按域名保存URL模式、特殊交互逻辑、陷阱 — 跨会话持久化 |
| 媒体提取 | 从DOM中提取图片/视频URL,截取任意视频帧截图 |
Installation
安装方法
Option A — Let Claude install it:
帮我安装这个 skill:https://github.com/eze-is/web-accessor in English:
Install this skill for me: https://github.com/eze-is/web-accessOption B — Manual:
bash
git clone https://github.com/eze-is/web-access ~/.claude/skills/web-accessThe skill file is . Claude Code loads all files under automatically.
~/.claude/skills/web-access/SKILL.mdSKILL.md~/.claude/skills/选项A — 让Claude自动安装:
帮我安装这个 skill:https://github.com/eze-is/web-access英文指令:
Install this skill for me: https://github.com/eze-is/web-access选项B — 手动安装:
bash
git clone https://github.com/eze-is/web-access ~/.claude/skills/web-accessSkill文件路径为。Claude Code会自动加载目录下所有文件。
~/.claude/skills/web-access/SKILL.md~/.claude/skills/SKILL.mdPrerequisites
前置依赖
Node.js 22+
Node.js 22+
bash
node --version # must be >= 22bash
node --version # 版本需 >= 22Enable Chrome Remote Debugging
启用Chrome远程调试
- Open in your Chrome
chrome://inspect/#remote-debugging - Check Allow remote debugging for this browser instance
- Restart Chrome if prompted
- 在Chrome中打开
chrome://inspect/#remote-debugging - 勾选允许此浏览器实例进行远程调试
- 如提示则重启Chrome
Verify Dependencies
验证依赖
bash
bash ~/.claude/skills/web-access/scripts/check-deps.shExpected output:
✅ Node.js 22.x found
✅ Chrome DevTools reachable at localhost:9222
✅ curl availablebash
bash ~/.claude/skills/web-access/scripts/check-deps.sh预期输出:
✅ 已找到Node.js 22.x
✅ Chrome DevTools可通过localhost:9222访问
✅ curl已安装CDP Proxy — Core Component
CDP代理 — 核心组件
The proxy is a lightweight Node.js WebSocket bridge between Claude and your Chrome instance.
该代理是Claude与本地Chrome实例之间的轻量级Node.js WebSocket桥接工具。
Start the Proxy
启动代理
bash
undefinedbash
undefinedStart in background (auto-exits after 20 min idle)
后台启动(闲置20分钟后自动退出)
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
Confirm it's running
确认代理运行状态
curl -s http://localhost:3456/ping
curl -s http://localhost:3456/ping
→ {"status":"ok"}
→ {"status":"ok"}
undefinedundefinedFull HTTP API Reference
完整HTTP API参考
bash
undefinedbash
undefined── Tab management ──────────────────────────────────────────
── 标签页管理 ──────────────────────────────────────────
Open new tab, returns tab ID
打开新标签页,返回标签页ID
→ {"targetId":"ABC123","url":"https://example.com"}
→ {"targetId":"ABC123","url":"https://example.com"}
Close a tab
关闭标签页
→ {"closed":true}
→ {"closed":true}
── Page content ────────────────────────────────────────────
── 页面内容 ────────────────────────────────────────────
Execute JavaScript, returns result
执行JavaScript,返回结果
curl -s -X POST "http://localhost:3456/eval?target=ABC123"
-d 'document.title'
-d 'document.title'
curl -s -X POST "http://localhost:3456/eval?target=ABC123"
-d 'document.title'
-d 'document.title'
→ {"result":"Example Domain"}
→ {"result":"Example Domain"}
Get full page HTML
获取完整页面HTML
curl -s -X POST "http://localhost:3456/eval?target=ABC123"
-d 'document.documentElement.outerHTML'
-d 'document.documentElement.outerHTML'
curl -s -X POST "http://localhost:3456/eval?target=ABC123"
-d 'document.documentElement.outerHTML'
-d 'document.documentElement.outerHTML'
── Interaction ─────────────────────────────────────────────
── 交互操作 ─────────────────────────────────────────────
JS click (fast, works for most buttons)
JS点击(速度快,适用于大多数按钮)
curl -s -X POST "http://localhost:3456/click?target=ABC123"
-d 'button.submit'
-d 'button.submit'
curl -s -X POST "http://localhost:3456/click?target=ABC123"
-d 'button.submit'
-d 'button.submit'
Real mouse click via CDP (use for upload triggers, canvas elements)
通过CDP实现真实鼠标点击(适用于上传触发按钮、画布元素)
curl -s -X POST "http://localhost:3456/clickAt?target=ABC123"
-d '.upload-btn'
-d '.upload-btn'
curl -s -X POST "http://localhost:3456/clickAt?target=ABC123"
-d '.upload-btn'
-d '.upload-btn'
File upload via input element
通过输入框实现文件上传
curl -s -X POST "http://localhost:3456/setFiles?target=ABC123"
-H "Content-Type: application/json"
-d '{"selector":"input[type=file]","files":["/tmp/photo.png"]}'
-H "Content-Type: application/json"
-d '{"selector":"input[type=file]","files":["/tmp/photo.png"]}'
curl -s -X POST "http://localhost:3456/setFiles?target=ABC123"
-H "Content-Type: application/json"
-d '{"selector":"input[type=file]","files":["/tmp/photo.png"]}'
-H "Content-Type: application/json"
-d '{"selector":"input[type=file]","files":["/tmp/photo.png"]}'
── Navigation ──────────────────────────────────────────────
── 导航操作 ──────────────────────────────────────────────
Scroll to bottom
滚动到底部
Scroll to top
滚动到顶部
── Visual ──────────────────────────────────────────────────
── 视觉操作 ──────────────────────────────────────────────────
Screenshot to file
截图保存到文件
Screenshot returned as base64
截图以base64格式返回
→ {"base64":"iVBORw0KGgo..."}
→ {"base64":"iVBORw0KGgo..."}
undefinedundefinedThree-Layer Channel Dispatch
三层通道调度
The skill teaches Claude to pick the right tool automatically:
Task type → Tool choice
─────────────────────────────────────────
General search query → WebSearch
Static page / docs / API → WebFetch or Jina
Login-gated / dynamic page → CDP Proxy
Heavy JS / SPA → CDP Proxy
Video / canvas interaction → CDP Proxy (clickAt)
Bulk text extraction → Jina (token-efficient)
Raw HTTP / custom headers → curl本Skill会引导Claude自动选择合适的工具:
任务类型 → 工具选择
─────────────────────────────────────────
通用搜索查询 → WebSearch
静态页面/文档/API → WebFetch或Jina
登录受限/动态页面 → CDP代理
重度JS/SPA页面 → CDP代理
视频/画布交互 → CDP代理(clickAt)
批量文本提取 → Jina(高效节省Token)
原始HTTP/自定义请求头 → curlJina Usage (Token-Efficient Reads)
Jina使用(Token高效读取)
bash
undefinedbash
undefinedJina converts any URL to clean markdown — great for docs/articles
Jina可将任意URL转换为简洁的markdown格式 — 非常适合文档/文章
undefinedundefinedCode Examples
代码示例
Example 1: Open a Page and Extract Data
示例1:打开页面并提取数据
javascript
// Claude runs this flow via CDP Proxy
// 1. Open tab
const tabRes = await fetch('http://localhost:3456/new?url=https://news.ycombinator.com');
const { targetId } = await tabRes.json();
// 2. Wait for load, then extract top story titles
const evalRes = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `
Array.from(document.querySelectorAll('.titleline > a'))
.slice(0, 10)
.map(a => ({ title: a.textContent, href: a.href }))
`
});
const { result } = await evalRes.json();
console.log(JSON.parse(result));
// 3. Clean up
await fetch(`http://localhost:3456/close?target=${targetId}`);javascript
// Claude通过CDP代理执行以下流程
// 1. 打开标签页
const tabRes = await fetch('http://localhost:3456/new?url=https://news.ycombinator.com');
const { targetId } = await tabRes.json();
// 2. 等待页面加载,然后提取顶部10条标题
const evalRes = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `
Array.from(document.querySelectorAll('.titleline > a'))
.slice(0, 10)
.map(a => ({ title: a.textContent, href: a.href }))
`
});
const { result } = await evalRes.json();
console.log(JSON.parse(result));
// 3. 清理资源
await fetch(`http://localhost:3456/close?target=${targetId}`);Example 2: Login-Gated Page (Uses Existing Chrome Session)
示例2:登录受限页面(复用现有Chrome会话)
javascript
// Chrome already has the user logged in — CDP inherits cookies automatically
async function scrapeAuthenticatedPage(url) {
// Open tab in the user's real Chrome — no login needed
const { targetId } = await fetch(`http://localhost:3456/new?url=${url}`)
.then(r => r.json());
// Wait for dynamic content
await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `new Promise(r => setTimeout(r, 2000))`
});
// Extract content
const { result } = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `document.querySelector('.main-content')?.innerText`
}).then(r => r.json());
await fetch(`http://localhost:3456/close?target=${targetId}`);
return result;
}javascript
// Chrome已保存用户登录状态 — CDP会自动继承Cookie
async function scrapeAuthenticatedPage(url) {
// 在用户的Chrome中打开标签页 — 无需重新登录
const { targetId } = await fetch(`http://localhost:3456/new?url=${url}`)
.then(r => r.json());
// 等待动态内容加载
await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `new Promise(r => setTimeout(r, 2000))`
});
// 提取内容
const { result } = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `document.querySelector('.main-content')?.innerText`
}).then(r => r.json());
await fetch(`http://localhost:3456/close?target=${targetId}`);
return result;
}Example 3: File Upload Automation
示例3:文件上传自动化
javascript
async function uploadFile(pageUrl, filePath) {
const { targetId } = await fetch(`http://localhost:3456/new?url=${pageUrl}`)
.then(r => r.json());
// Wait for page
await new Promise(r => setTimeout(r, 1500));
// Click the upload trigger button (real mouse event — required for some SPAs)
await fetch(`http://localhost:3456/clickAt?target=${targetId}`, {
method: 'POST',
body: '.upload-trigger-button'
});
await new Promise(r => setTimeout(r, 500));
// Set file on the (possibly hidden) input
await fetch(`http://localhost:3456/setFiles?target=${targetId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
selector: 'input[type=file]',
files: [filePath]
})
});
// Submit
await fetch(`http://localhost:3456/click?target=${targetId}`, {
method: 'POST',
body: 'button[type=submit]'
});
// Screenshot to verify
await fetch(`http://localhost:3456/screenshot?target=${targetId}&file=/tmp/upload-result.png`);
await fetch(`http://localhost:3456/close?target=${targetId}`);
}javascript
async function uploadFile(pageUrl, filePath) {
const { targetId } = await fetch(`http://localhost:3456/new?url=${pageUrl}`)
.then(r => r.json());
// 等待页面加载
await new Promise(r => setTimeout(r, 1500));
// 点击上传触发按钮(真实鼠标事件 — 部分SPA需要此方式)
await fetch(`http://localhost:3456/clickAt?target=${targetId}`, {
method: 'POST',
body: '.upload-trigger-button'
});
await new Promise(r => setTimeout(r, 500));
// 为(可能隐藏的)输入框设置文件
await fetch(`http://localhost:3456/setFiles?target=${targetId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
selector: 'input[type=file]',
files: [filePath]
})
});
// 提交
await fetch(`http://localhost:3456/click?target=${targetId}`, {
method: 'POST',
body: 'button[type=submit]'
});
// 截图验证结果
await fetch(`http://localhost:3456/screenshot?target=${targetId}&file=/tmp/upload-result.png`);
await fetch(`http://localhost:3456/close?target=${targetId}`);
}Example 4: Parallel Research with Sub-Agents
示例4:使用子Agent进行并行调研
javascript
// Instruct Claude to dispatch parallel sub-agents like this:
const targets = [
'https://product-a.com',
'https://product-b.com',
'https://product-c.com',
'https://product-d.com',
'https://product-e.com'
];
// Each sub-agent opens its own tab (tab-isolated, same Proxy)
const results = await Promise.all(
targets.map(async (url) => {
const { targetId } = await fetch(`http://localhost:3456/new?url=${url}`)
.then(r => r.json());
await new Promise(r => setTimeout(r, 2000));
const { result } = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `({
title: document.title,
description: document.querySelector('meta[name=description]')?.content,
h1: document.querySelector('h1')?.textContent,
pricing: document.querySelector('[class*="pric"]')?.innerText?.slice(0,200)
})`
}).then(r => r.json());
await fetch(`http://localhost:3456/close?target=${targetId}`);
return { url, data: JSON.parse(result) };
})
);
console.table(results);javascript
// 引导Claude按以下方式调度并行子Agent:
const targets = [
'https://product-a.com',
'https://product-b.com',
'https://product-c.com',
'https://product-d.com',
'https://product-e.com'
];
// 每个子Agent打开独立标签页(标签页隔离,共享同一个代理)
const results = await Promise.all(
targets.map(async (url) => {
const { targetId } = await fetch(`http://localhost:3456/new?url=${url}`)
.then(r => r.json());
await new Promise(r => setTimeout(r, 2000));
const { result } = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `({
title: document.title,
description: document.querySelector('meta[name=description]')?.content,
h1: document.querySelector('h1')?.textContent,
pricing: document.querySelector('[class*="pric"]')?.innerText?.slice(0,200)
})`
}).then(r => r.json());
await fetch(`http://localhost:3456/close?target=${targetId}`);
return { url, data: JSON.parse(result) };
})
);
console.table(results);Example 5: Video Frame Screenshot
示例5:视频帧截图
javascript
async function screenshotVideoAt(pageUrl, timestampSeconds) {
const { targetId } = await fetch(`http://localhost:3456/new?url=${pageUrl}`)
.then(r => r.json());
await new Promise(r => setTimeout(r, 3000));
// Seek video to timestamp
await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `
const v = document.querySelector('video');
v.currentTime = ${timestampSeconds};
v.pause();
`
});
await new Promise(r => setTimeout(r, 500));
// Capture the frame
await fetch(`http://localhost:3456/screenshot?target=${targetId}&file=/tmp/frame-${timestampSeconds}s.png`);
await fetch(`http://localhost:3456/close?target=${targetId}`);
}javascript
async function screenshotVideoAt(pageUrl, timestampSeconds) {
const { targetId } = await fetch(`http://localhost:3456/new?url=${pageUrl}`)
.then(r => r.json());
await new Promise(r => setTimeout(r, 3000));
// 将视频定位到指定时间点
await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `
const v = document.querySelector('video');
v.currentTime = ${timestampSeconds};
v.pause();
`
});
await new Promise(r => setTimeout(r, 500));
// 截取当前帧
await fetch(`http://localhost:3456/screenshot?target=${targetId}&file=/tmp/frame-${timestampSeconds}s.png`);
await fetch(`http://localhost:3456/close?target=${targetId}`);
}Common Patterns
常用模式
Pattern: Check Proxy Before CDP Tasks
模式:执行CDP任务前检查代理状态
bash
undefinedbash
undefinedAlways verify proxy is up before a CDP workflow
执行CDP工作流前务必验证代理是否正常运行
curl -s http://localhost:3456/ping ||
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
undefinedcurl -s http://localhost:3456/ping ||
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
undefinedPattern: Use Jina for Documentation
模式:使用Jina读取文档
bash
undefinedbash
undefinedCheaper and cleaner than WebFetch for text-heavy pages
对于文本密集型页面,Jina比WebFetch更节省Token且格式更清晰
undefinedundefinedPattern: Prefer WebSearch for Discovery, CDP for Execution
模式:WebSearch用于发现,CDP用于执行
1. WebSearch → find the right URLs
2. WebFetch → read static/public content
3. CDP → interact, authenticate, dynamic content1. WebSearch → 查找目标URL
2. WebFetch → 读取静态/公开内容
3. CDP → 交互操作、登录验证、动态内容处理Pattern: Extract All Media URLs
模式:提取所有媒体URL
javascript
// Get all images and videos on current page
const media = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `({
images: Array.from(document.images).map(i => i.src),
videos: Array.from(document.querySelectorAll('video source, video[src]'))
.map(v => v.src || v.getAttribute('src'))
})`
}).then(r => r.json());javascript
undefinedTroubleshooting
获取当前页面所有图片和视频URL
Proxy won't start
—
bash
undefinedconst media = await fetch(, {
method: 'POST',
body:
}).then(r => r.json());
http://localhost:3456/eval?target=${targetId}({ images: Array.from(document.images).map(i => i.src), videos: Array.from(document.querySelectorAll('video source, video[src]')) .map(v => v.src || v.getAttribute('src')) })undefinedCheck if port 3456 is already in use
故障排除
—
代理无法启动
lsof -i :3456
bash
undefinedKill existing proxy
检查端口3456是否被占用
kill $(lsof -ti :3456)
lsof -i :3456
Restart
终止现有代理进程
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
undefinedkill $(lsof -ti :3456)
Chrome not reachable
重启代理
bash
undefinednode ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
undefinedVerify Chrome remote debugging is on
无法连接到Chrome
bash
undefinedShould return Chrome version JSON
验证Chrome远程调试是否启用
If empty — go to chrome://inspect/#remote-debugging and enable it
—
undefined/clickAt
has no effect
/clickAt应返回Chrome版本JSON信息
—
如果返回空 — 打开chrome://inspect/#remote-debugging并启用远程调试
- The element may need scrolling into view first:
bash
curl -s -X POST "http://localhost:3456/eval?target=ID" \
-d 'document.querySelector(".btn").scrollIntoView()'- Then retry
/clickAt
undefinedPage content is empty / JS not rendered
/clickAt
无效果
/clickAtbash
undefined- 元素可能需要先滚动到可视区域:
bash
curl -s -X POST "http://localhost:3456/eval?target=ID" \
-d 'document.querySelector(".btn").scrollIntoView()'- 然后重试
/clickAt
Add a wait after /new before /eval
页面内容为空/JS未渲染
curl -s -X POST "http://localhost:3456/eval?target=ID"
-d 'new Promise(r => setTimeout(r, 3000))'
-d 'new Promise(r => setTimeout(r, 3000))'
bash
undefinedThen fetch content
在/new之后、/eval之前添加等待时间
undefinedcurl -s -X POST "http://localhost:3456/eval?target=ID"
-d 'new Promise(r => setTimeout(r, 3000))'
-d 'new Promise(r => setTimeout(r, 3000))'
File upload input not found
然后再获取内容
Some SPAs render only after the trigger click. Always:
<input type=file>- the visible upload button first
/clickAt - Wait 500ms
- Then
/setFiles
undefinedSub-agent tabs interfering
找不到文件上传输入框
Each sub-agent should store its own and never share it. The Proxy is stateless per-tab.
targetId部分SPA仅在点击触发按钮后才渲染,请遵循以下步骤:
<input type=file>- 先使用点击可见的上传按钮
/clickAt - 等待500ms
- 再使用
/setFiles
Proxy Auto-Shutdown
子Agent标签页相互干扰
The proxy exits automatically after 20 minutes of no requests. For long-running tasks:
bash
undefined每个子Agent应保存自己的,且绝不共享。代理对每个标签页是无状态的。
targetIdKeep-alive ping in background
代理自动关闭
while true; do curl -s http://localhost:3456/ping > /dev/null; sleep 300; done &
undefined代理在无请求闲置20分钟后会自动退出。对于长时间运行的任务:
bash
undefinedSite Experience Store
后台发送保活请求
The skill accumulates domain knowledge in a local JSON store. When Claude visits , it reads any saved notes about:
twitter.com- Known working URL patterns
- Login flow quirks
- Selectors that are stable vs dynamic
- Rate limiting behavior
This persists across Claude sessions. The store lives at:
~/.claude/skills/web-access/data/site-experience.jsonYou can inspect or edit it manually to add your own domain knowledge.
while true; do curl -s http://localhost:3456/ping > /dev/null; sleep 300; done &
undefinedProject Structure
站点经验存储
~/.claude/skills/web-access/
├── SKILL.md ← This skill file (loaded by Claude)
├── scripts/
│ ├── cdp-proxy.mjs ← CDP Proxy server (Node.js 22+)
│ └── check-deps.sh ← Dependency checker
└── data/
└── site-experience.json ← Accumulated domain knowledge本Skill会在本地JSON文件中积累域名相关知识。当Claude访问时,会读取已保存的以下信息:
twitter.com- 已知可用的URL模式
- 登录流程的特殊处理
- 稳定与动态选择器
- 限流行为
这些信息会跨Claude会话持久化。存储文件路径:
~/.claude/skills/web-access/data/site-experience.json你可以手动查看或编辑该文件,添加自定义的域名知识。
Capability Summary for Task Routing
项目结构
| User says | Claude should use |
|---|---|
| "Search for X" | WebSearch |
| "Read this URL" | WebFetch or Jina |
| "Go to my dashboard on X" | CDP (login state) |
| "Click the submit button on X" | CDP |
| "Upload this file to X" | CDP |
| "Research these 5 products" | Parallel sub-agents via CDP |
| "Extract images from X" | CDP |
| "Screenshot X at 1:23 in the video" | CDP |
~/.claude/skills/web-access/
├── SKILL.md ← 本Skill文件(由Claude加载)
├── scripts/
│ ├── cdp-proxy.mjs ← CDP代理服务器(需Node.js 22+)
│ └── check-deps.sh ← 依赖检查脚本
└── data/
└── site-experience.json ← 积累的域名知识—
任务路由能力汇总
—
| 用户指令 | Claude应使用的工具 |
|---|---|
| "搜索X" | WebSearch |
| "读取这个URL" | WebFetch或Jina |
| "打开我在X上的仪表盘" | CDP(复用登录状态) |
| "点击X上的提交按钮" | CDP |
| "上传文件到X" | CDP |
| "调研这5个产品" | 并行子Agent + CDP |
| "从X提取图片" | CDP |
| "截取X视频1分23秒处的画面" | CDP |