
Bb Browser
Extend bb-browser with custom site adapters so your coding agent can call live web APIs through a logged-in tab instead of brittle scrapers.
Install
npx skills add https://github.com/epiral/bb-browser --skill bb-browserWhat is this skill?
- Five-step flow: network capture → eval fetch probe → adapter JS → local sites dir → community PR
- Documents @meta block (name, domain, args, capabilities, readOnly) parsed by parseSiteMeta
- Tier 1–3 complexity ladder: cookie fetch vs extra headers vs Pinia/webpack injection
- CLI patterns: network clear/requests with filter as positional arg, refresh, eval in-tab JSON
- Targets ~/.bb-browser/sites/ for iterative adapter testing before publish
Adoption & trust: 3k installs on skills.sh; 5.7k GitHub stars; 2/3 security scanners passed (skills.sh audits).
Recommended Skills
Journey fit
Adapter authoring is product work: you reverse APIs, ship JS site modules, and test in ~/.bb-browser before contributing—canonical shelf is building agent-facing integrations. bb-browser is agent browser tooling; this skill documents the adapter contract (@meta), tiered auth complexity, and CLI network/eval workflow—not generic frontend UI.
Common Questions / FAQ
Is Bb Browser safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Bb Browser
# Adapter 开发指南 ## 开发流程概览 1. 用 `network` 命令逆向 API 2. 用 `eval` 测试 fetch 是否可行 3. 编写 adapter JS 文件 4. 保存到 `~/.bb-browser/sites/` 测试 5. 提交 PR 到社区仓库 <!-- 证据来源:packages/cli/src/index.ts:601-658 guide 命令输出 --> ## Step 1:逆向 API ```bash # 清空旧记录 bb-browser network clear --tab <tabId> # 刷新页面触发请求 bb-browser refresh --tab <tabId> # 查看 API 请求(filter 是位置参数,不是 --filter) bb-browser network requests "api" --with-body --json --tab <tabId> ``` 重点关注: - 请求 URL 和参数格式 - 认证方式(Cookie / Bearer token / CSRF token) - 响应数据结构 ## Step 2:测试 fetch ```bash # 直接在浏览器中测试 fetch(Tier 1 验证) bb-browser eval "fetch('/api/endpoint',{credentials:'include'}).then(r=>r.json())" --tab <tabId> ``` 根据结果判断复杂度: - **能直接拿到数据** → Tier 1(Cookie 认证,如 Reddit/GitHub/V2EX) - **需要额外请求头** → Tier 2(如 Twitter:Bearer + CSRF token) - **需要请求签名或注入** → Tier 3(如小红书:Pinia store / Webpack 模块) ## Step 3:编写 Adapter ### 元数据格式(`/* @meta */` 块) <!-- 证据来源:site.ts:56-118 parseSiteMeta() --> ```javascript /* @meta { "name": "platform/command", "description": "功能描述", "domain": "www.example.com", "args": { "query": {"required": true, "description": "搜索关键词"}, "count": {"required": false, "description": "返回数量"} }, "capabilities": ["search"], "readOnly": true, "example": "bb-browser site platform/command value" } */ async function(args) { // adapter 实现 } ``` ### 元数据字段说明 | 字段 | 必需 | 说明 | |------|------|------| | `name` | 是 | 唯一标识,格式 `platform/command` | | `description` | 是 | 功能描述 | | `domain` | 是 | 目标网站域名(用于自动 tab 匹配) | | `args` | 是 | 参数定义,每个参数含 `required` 和 `description` | | `capabilities` | 否 | 能力标签数组 | | `readOnly` | 否 | 是否只读操作 | | `example` | 否 | 使用示例 | ### 旧格式兼容 也支持 `// @tag value` 注释格式(向后兼容): ```javascript // @name platform/command // @description 功能描述 // @domain www.example.com // @args query,filter // @example bb-browser site platform/command value ``` <!-- 证据来源:site.ts:100-117 旧格式解析 --> ## 三层复杂度示例 ### Tier 1:Cookie 认证(~1 分钟) 直接 fetch,`credentials: 'include'` 自动带 Cookie。 ```javascript /* @meta { "name": "reddit/search", "description": "Search Reddit posts", "domain": "www.reddit.com", "args": {"query": {"required": true, "description": "Search query"}}, "readOnly": true, "example": "bb-browser site reddit/search 'local LLM'" } */ async function(args) { if (!args.query) return {error: 'Missing argument: query'}; const resp = await fetch( '/search.json?q=' + encodeURIComponent(args.query) + '&limit=10', {credentials: 'include'} ); if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'}; const data = await resp.json(); return data.data.children.map(c => ({ title: c.data.title, url: 'https://www.reddit.com' + c.data.permalink, score: c.data.score, subreddit: c.data.subreddit })); } ``` ### Tier 2:Bearer + CSRF token(~3 分钟) 需要从页面提取 token 构造请求头。 ```javascript /* @meta { "name": "twitter/search", "description": "Search tweets", "domain": "twitter.com", "args": {"query": {"required": true, "description": "Search query"}}, "readOnly": true } */ async function(args) { // 从 cookie 提取 CSRF token const csrf = document.cookie.match(/ct0=([^;]+)/)?.[1]; if (!csrf) return {error: 'CSRF token not found', hint: 'Not logged in?'}; // 构造带认证的请求 const resp = await fetch('/i/api/2/search/adaptive.json?q=' + encodeURIComponent(args.query), { credentials: 'include', headers: { 'authorization': 'Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs...', 'x-csrf-token': csrf } }); if (!resp.ok) return {error: 'HTTP ' + resp.status}; return await resp.json(); } ``` ### Tier 3:Webpack 注入 / Pinia store(~10 分钟) 需要访问页面内部状态或调用内部模块。 ## 抗变更模式 网站频繁更新前端代码(CSS class、webpack module ID、GraphQL queryId 等)。以下是经过验证的抗变更模式。 ### 模式 1:结构化 DOM 提取(替代 CSS class 选择器) **问题**:网站经常修改 CSS class 名(如 Google 从 `div.g` 改为 `div.MjjYud`),导致 adapter 失效。 **方案**:用语义化 HTML 元素(h3、a、article)定位内容,不依赖任何 class name。 ```javascript // ❌ 脆弱:依赖 CSS class(Google 已多次更改) const items = do