skills/adisinghstudent/ara.so/chrome-cdp-live-browser

chrome-cdp-live-browser

SKILL.md

Chrome CDP Live Browser Skill

Skill by ara.so — Daily 2026 Skills collection

Give your AI agent access to your live Chrome session — the tabs you already have open, your logged-in accounts, and your current page state. Connects directly to Chrome's remote debugging WebSocket with no Puppeteer, no fresh browser instance, and no re-login required.

What It Does

  • Read live pages — access Gmail, GitHub, internal tools, anything you're already logged into
  • Interact with tabs — click, type, navigate, evaluate JS in your active browser
  • Capture state — screenshots, accessibility trees, full HTML, network timing
  • Persistent daemons — one lightweight background process per tab, modal appears once, reused silently
  • Handles scale — works reliably with 100+ open tabs where Puppeteer-based tools time out

Installation

Enable Remote Debugging in Chrome

Navigate to chrome://inspect/#remote-debugging and toggle the switch. That's it — no flags, no restart needed.

As a pi skill

pi install git:github.com/pasky/chrome-cdp-skill@v1.0.1

For other agents (Amp, Claude Code, Cursor, etc.)

Clone the repository and copy the skills/chrome-cdp/ directory wherever your agent loads skills or context from:

git clone https://github.com/pasky/chrome-cdp-skill.git
cp -r chrome-cdp-skill/skills/chrome-cdp/ ./your-agent-skills/

Requirements: Node.js 22+ only. No npm install needed — zero runtime dependencies.

Configuration

The CLI auto-detects Chrome, Chromium, Brave, Edge, and Vivaldi on macOS and Linux via the DevToolsActivePort file.

For non-standard browser locations, set:

export CDP_PORT_FILE="/path/to/your/browser/profile/DevToolsActivePort"

Key Commands

# List all open tabs (shows targetId prefixes)
scripts/cdp.mjs list

# Take a screenshot of a tab
scripts/cdp.mjs shot <target>

# Get accessibility tree (compact, semantic — best for understanding page structure)
scripts/cdp.mjs snap <target>

# Get full HTML, optionally scoped to a CSS selector
scripts/cdp.mjs html <target>
scripts/cdp.mjs html <target> ".main-content"

# Evaluate JavaScript in the page context
scripts/cdp.mjs eval <target> "document.title"

# Navigate and wait for load
scripts/cdp.mjs nav <target> https://example.com

# Network resource timing
scripts/cdp.mjs net <target>

# Click by CSS selector
scripts/cdp.mjs click <target> "button.submit"

# Click at specific coordinates
scripts/cdp.mjs clickxy <target> 320 240

# Type text at the focused element (works across cross-origin iframes)
scripts/cdp.mjs type <target> "hello world"

# Click "load more" repeatedly until selector disappears
scripts/cdp.mjs loadall <target> ".load-more-btn"

# Raw CDP command passthrough
scripts/cdp.mjs evalraw <target> Page.captureScreenshot '{"format":"png"}'

# Open a new tab (triggers Allow prompt once)
scripts/cdp.mjs open https://example.com

# Stop daemon(s)
scripts/cdp.mjs stop
scripts/cdp.mjs stop <target>

<target> is a unique prefix of the targetId shown by list.

Code Examples

Listing Tabs and Getting a Target

import { execSync } from 'child_process';

// List all open tabs
const tabs = execSync('scripts/cdp.mjs list').toString();
console.log(tabs);
// Output includes lines like:
// abc123  https://github.com/...  GitHub - some repo

// Use just the prefix (e.g., "abc") as <target>
const target = 'abc123';

Reading Page Content

// Get the accessibility tree for semantic page understanding
const tree = execSync(`scripts/cdp.mjs snap ${target}`).toString();

// Get full HTML
const html = execSync(`scripts/cdp.mjs html ${target}`).toString();

// Scope HTML to a specific section
const section = execSync(`scripts/cdp.mjs html ${target} "#content"`).toString();

Interacting with a Page

// Navigate to a URL and wait for load
execSync(`scripts/cdp.mjs nav ${target} https://example.com`);

// Click a button
execSync(`scripts/cdp.mjs click ${target} "button[type=submit]"`);

// Fill in a form field
execSync(`scripts/cdp.mjs click ${target} "input#search"`);
execSync(`scripts/cdp.mjs type ${target} "my search query"`);

// Take a screenshot after interaction
execSync(`scripts/cdp.mjs shot ${target}`);

Evaluating JavaScript

// Read data from the page
const title = execSync(`scripts/cdp.mjs eval ${target} "document.title"`).toString().trim();

// Extract structured data
const links = execSync(
  `scripts/cdp.mjs eval ${target} "JSON.stringify([...document.querySelectorAll('a')].map(a => ({text: a.textContent.trim(), href: a.href})))"`
).toString();

const parsed = JSON.parse(links);

Handling Infinite Scroll / Load More

// Keep clicking "Load more" until button disappears, then get full content
execSync(`scripts/cdp.mjs loadall ${target} ".load-more"`);
const fullContent = execSync(`scripts/cdp.mjs html ${target}`).toString();

Raw CDP Passthrough

// Capture a screenshot with specific format via raw CDP
const result = execSync(
  `scripts/cdp.mjs evalraw ${target} Page.captureScreenshot '{"format":"jpeg","quality":80}'`
).toString();

// Get cookies
const cookies = execSync(
  `scripts/cdp.mjs evalraw ${target} Network.getCookies`
).toString();

Using in an Agent Workflow

// Typical agent pattern: observe → reason → act → verify
async function agentStep(targetPrefix) {
  // 1. Observe current state
  const snapshot = execSync(`scripts/cdp.mjs snap ${targetPrefix}`).toString();
  
  // 2. Reason about the page (pass to LLM, etc.)
  // ...
  
  // 3. Act based on reasoning
  execSync(`scripts/cdp.mjs click ${targetPrefix} ".btn-primary"`);
  
  // 4. Verify result
  const after = execSync(`scripts/cdp.mjs shot ${targetPrefix}`).toString();
  return after; // path to screenshot file
}

Integration Patterns

With Claude Code / Cursor / Amp

Copy the skills/chrome-cdp/ directory into your project and reference SKILL.md in your agent's system prompt or context. The agent can then invoke scripts/cdp.mjs as shell commands.

Accessing Authenticated Services

Because the skill connects to your running Chrome session, no credential management is needed:

// The agent can directly read your logged-in Gmail, GitHub PRs, etc.
execSync(`scripts/cdp.mjs nav ${target} https://github.com/notifications`);
const notifs = execSync(`scripts/cdp.mjs snap ${target}`).toString();

Working with SPAs and Dynamic Content

// Navigate and wait, then get rendered content (not source HTML)
execSync(`scripts/cdp.mjs nav ${target} https://app.example.com/dashboard`);

// Evaluate JS to wait for a specific element
execSync(
  `scripts/cdp.mjs eval ${target} "await new Promise(r => { const i = setInterval(() => { if (document.querySelector('.data-loaded')) { clearInterval(i); r(); } }, 100); })"`
);

const content = execSync(`scripts/cdp.mjs html ${target} ".dashboard"`).toString();

Troubleshooting

"Allow debugging" modal keeps appearing

This happens when tools reconnect on every command. chrome-cdp holds persistent daemons per tab — the modal should only appear once per tab. If it reappears, check that a previous daemon did not crash:

scripts/cdp.mjs stop
# Then retry your command — a fresh daemon will be spawned

Chrome not detected

# Check if DevToolsActivePort exists
ls ~/Library/Application\ Support/Google/Chrome/Default/DevToolsActivePort  # macOS
ls ~/.config/google-chrome/Default/DevToolsActivePort                        # Linux

# If in a non-standard location, set the env var
export CDP_PORT_FILE="/custom/path/DevToolsActivePort"

Remote debugging not enabled

Make sure you've toggled the switch at chrome://inspect/#remote-debugging — it must be on. The toggle persists across Chrome restarts.

Target not found / prefix ambiguous

# Run list to get current targetIds
scripts/cdp.mjs list

# Use a longer prefix to disambiguate
scripts/cdp.mjs snap abc123def  # instead of just "abc"

Node.js version error

The skill requires Node.js 22+. Check your version:

node --version  # must be v22.x.x or higher

Use nvm or fnm to upgrade if needed.

Daemon inactivity timeout

Daemons auto-exit after 20 minutes of inactivity. The next command to a tab simply spawns a new daemon transparently — no action needed.

Weekly Installs
1
GitHub Stars
8
First Seen
1 day ago
Installed on
mcpjam1
claude-code1
replit1
junie1
windsurf1
zencoder1