[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7AFW1XMVGS79WDKKMMB1M0R":3,"skill-same:01M7AFW1XMVGS79WDKKMMB1M0R":163},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":14,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":30,"ownerDescription":31,"updatedAt":32,"install":33,"resources":46},"01M7AFW1XMVGS79WDKKMMB1M0R","chrome-devtools",null,"Automate browsers with Puppeteer CLI scripts and persistent sessions. Use for screenshots, performance analysis, network monitoring, web scraping, form automation, JavaScript debugging.","minhlongs\u002Fsophia-ai-factory","minhlongs","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F186063428?v=4","01M7AETK9R4ST1TK6JXR2CV5BY","Minh Long","01M7AETKAFVJDBYMX448AMZV0Y",0,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: chrome-devtools\ndescription: Automate browsers with Puppeteer CLI scripts and persistent sessions. Use for screenshots, performance analysis, network monitoring, web scraping, form automation, JavaScript debugging.\nlicense: Apache-2.0\nversion: 1.1.0\n---\n\n# Chrome DevTools Agent Skill\n\nBrowser automation via Puppeteer scripts with persistent sessions. All scripts output JSON.\n\n## Skill Location\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n```bash\n# Detect skill location (no cd needed - scripts use __dirname for paths)\nSKILL_DIR=\"\"\nif [ -d \".opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\" ]; then\n  SKILL_DIR=\".opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\"\nelif [ -d \"$HOME\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\" ]; then\n  SKILL_DIR=\"$HOME\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\"\nfi\n# Run scripts with full path: node \"$SKILL_DIR\u002Fscript.js\" --args\n```\n\n## Choosing Your Approach\n\n| Scenario | Approach |\n|----------|----------|\n| **Source-available sites** | Read source code first, write selectors directly |\n| **Unknown layouts** | Use `aria-snapshot.js` for semantic discovery |\n| **Visual inspection** | Take screenshots to verify rendering |\n| **Debug issues** | Collect console logs, analyze with session storage |\n| **Accessibility audit** | Use ARIA snapshot for semantic structure analysis |\n\n## Automation Browsing Running Mode\n\n- Detect current OS and launch browser as headless only when running on Linux, WSL, or CI environments.\n- For macOS\u002FWindows, browser always runs in headed mode for better debugging.\n- Run multiple scripts\u002Fsessions in parallel to simulate real user interactions.\n- Run multiple scripts\u002Fsessions in parallel to simulate different device types (mobile, tablet, desktop).\n- Skills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n## ARIA Snapshot (Element Discovery)\n\nWhen page structure is unknown, use `aria-snapshot.js` to get a YAML-formatted accessibility tree with semantic roles, accessible names, states, and stable element references.\n\n### Get ARIA Snapshot\n\n```bash\n# Generate ARIA snapshot and output to stdout\nnode \"$SKILL_DIR\u002Faria-snapshot.js\" --url https:\u002F\u002Fexample.com\n\n# Save to file in snapshots directory\nnode \"$SKILL_DIR\u002Faria-snapshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fsnapshots\u002Fpage.yaml\n```\n\n### Example YAML Output\n\n```yaml\n- banner:\n  - link \"Hacker News\" [ref=e1]\n    \u002Furl: https:\u002F\u002Fnews.ycombinator.com\n  - navigation:\n    - link \"new\" [ref=e2]\n    - link \"past\" [ref=e3]\n    - link \"comments\" [ref=e4]\n- main:\n  - list:\n    - listitem:\n      - link \"Show HN: My new project\" [ref=e8]\n      - text: \"128 points by user 3 hours ago\"\n- contentinfo:\n  - textbox [ref=e10]\n    \u002Fplaceholder: \"Search\"\n```\n\n### Interpreting ARIA Notation\n\n| Notation | Meaning |\n|----------|---------|\n| `[ref=eN]` | Stable identifier for interactive elements |\n| `[checked]` | Checkbox\u002Fradio is selected |\n| `[disabled]` | Element is inactive |\n| `[expanded]` | Accordion\u002Fdropdown is open |\n| `[level=N]` | Heading hierarchy (1-6) |\n| `\u002Furl:` | Link destination |\n| `\u002Fplaceholder:` | Input placeholder text |\n| `\u002Fvalue:` | Current input value |\n\n### Interact by Ref\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nUse `select-ref.js` to interact with elements by their ref:\n\n```bash\n# Click element with ref e5\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e5 --action click\n\n# Fill input with ref e10\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e10 --action fill --value \"search query\"\n\n# Get text content\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e8 --action text\n\n# Screenshot specific element\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e1 --action screenshot --output .\u002Flogo.png\n\n# Focus element\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e10 --action focus\n\n# Hover over element\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e5 --action hover\n```\n\n### Store Snapshots\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nStore snapshots for analysis in `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Fsnapshots\u002F`:\n\n```bash\n# Create snapshots directory\nmkdir -p .opencode\u002Fchrome-devtools\u002Fsnapshots\n\n# Capture and store with timestamp\nSESSION=\"$(date +%Y%m%d-%H%M%S)\"\nnode \"$SKILL_DIR\u002Faria-snapshot.js\" --url https:\u002F\u002Fexample.com --output .opencode\u002Fchrome-devtools\u002Fsnapshots\u002F$SESSION.yaml\n```\n\n### Workflow: Unknown Page Structure\n\n1. **Get snapshot** to discover elements:\n   ```bash\n   node \"$SKILL_DIR\u002Faria-snapshot.js\" --url https:\u002F\u002Fexample.com\n   ```\n\n2. **Identify target** from YAML output (e.g., `[ref=e5]` for a button)\n\n3. **Interact by ref**:\n   ```bash\n   node \"$SKILL_DIR\u002Fselect-ref.js\" --ref e5 --action click\n   ```\n\n4. **Verify result** with screenshot or new snapshot:\n   ```bash\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002Fresult.png\n   ```\n\n## Local HTML Files\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n**IMPORTANT**: Never browse local HTML files via `file:\u002F\u002F` protocol. Always serve via local server:\n**Why**: `file:\u002F\u002F` protocol blocks many browser features (CORS, ES modules, fetch API, service workers). Local server ensures proper HTTP behavior.\n\n```bash\n# Option 1: npx serve (recommended)\nnpx serve .\u002Fdist -p 3000 &\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url http:\u002F\u002Flocalhost:3000\n\n# Option 2: Python http.server\npython -m http.server 3000 --directory .\u002Fdist &\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url http:\u002F\u002Flocalhost:3000\n```\n\n**Note**: when port 3000 is busy, find an available port with `lsof -i :3000` and use a different one.\n\n## Quick Start\n\n```bash\n# Install dependencies (one-time setup)\nnpm install --prefix \"$SKILL_DIR\"\n\n# Test (browser stays running for session reuse)\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fexample.com\n# Output: {\"success\": true, \"url\": \"...\", \"title\": \"...\"}\n```\n\n**Linux\u002FWSL only**: Run `\"$SKILL_DIR\u002Finstall-deps.sh\"` first for Chrome system libraries.\n\n## Session Persistence\n\nBrowser state persists across script executions via WebSocket endpoint file (`.browser-session.json`).\n\n**Default behavior**: Scripts disconnect but keep browser running for session reuse.\n\n```bash\n# First script: launches browser, navigates, disconnects (browser stays running)\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fexample.com\u002Flogin\n\n# Subsequent scripts: connect to existing browser, reuse page state\nnode \"$SKILL_DIR\u002Ffill.js\" --selector \"#email\" --value \"user@example.com\"\nnode \"$SKILL_DIR\u002Ffill.js\" --selector \"#password\" --value \"secret\"\nnode \"$SKILL_DIR\u002Fclick.js\" --selector \"button[type=submit]\"\n\n# Close browser when done\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url about:blank --close true\n```\n\n**Session management**:\n- `--close true`: Close browser and clear session\n- Default (no flag): Keep browser running for next script\n\n## Available Scripts\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nAll in `.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002F`:\n\n| Script | Purpose |\n|--------|---------|\n| `navigate.js` | Navigate to URLs |\n| `screenshot.js` | Capture screenshots (auto-compress >5MB via Sharp) |\n| `click.js` | Click elements |\n| `fill.js` | Fill form fields |\n| `evaluate.js` | Execute JS in page context |\n| `snapshot.js` | Extract interactive elements (JSON format) |\n| `aria-snapshot.js` | Get ARIA accessibility tree (YAML format with refs) |\n| `select-ref.js` | Interact with elements by ref from ARIA snapshot |\n| `console.js` | Monitor console messages\u002Ferrors |\n| `network.js` | Track HTTP requests\u002Fresponses |\n| `performance.js` | Measure Core Web Vitals |\n| `ws-debug.js` | Debug WebSocket connections (basic) |\n| `ws-full-debug.js` | Debug WebSocket with full events\u002Fframes |\n| `inject-auth.js` | Inject cookies\u002Ftokens for authentication |\n| `import-cookies.js` | Import cookies from JSON\u002FNetscape file |\n| `connect-chrome.js` | Connect to Chrome with remote debugging |\n\n## Workflow Loop\n\n1. **Execute** focused script for single task\n2. **Observe** JSON output\n3. **Assess** completion status\n4. **Decide** next action\n5. **Repeat** until done\n\n## Writing Custom Test Scripts\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nFor complex automation, write scripts to `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Ftmp\u002F`:\n\n```bash\n# Create tmp directory for test scripts\nmkdir -p $SKILL_DIR\u002F.opencode\u002Fchrome-devtools\u002Ftmp\n\n# Write a test script\ncat > $SKILL_DIR\u002F.opencode\u002Fchrome-devtools\u002Ftmp\u002Flogin-test.js \u003C\u003C 'EOF'\nimport { getBrowser, getPage, disconnectBrowser, outputJSON } from '..\u002Fscripts\u002Flib\u002Fbrowser.js';\n\nasync function loginTest() {\n  const browser = await getBrowser();\n  const page = await getPage(browser);\n\n  await page.goto('https:\u002F\u002Fexample.com\u002Flogin');\n  await page.type('#email', 'user@example.com');\n  await page.type('#password', 'secret');\n  await page.click('button[type=submit]');\n  await page.waitForNavigation();\n\n  outputJSON({\n    success: true,\n    url: page.url(),\n    title: await page.title()\n  });\n\n  await disconnectBrowser();\n}\n\nloginTest();\nEOF\n\n# Run the test\nnode $SKILL_DIR\u002F.opencode\u002Fchrome-devtools\u002Ftmp\u002Flogin-test.js\n```\n\n**Key principles for custom scripts**:\n- Single-purpose: one script, one task\n- Always call `disconnectBrowser()` at the end (keeps browser running)\n- Use `closeBrowser()` only when ending session completely\n- Output JSON for easy parsing\n- Plain JavaScript only in `page.evaluate()` callbacks\n\n## Screenshots\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nStore screenshots for analysis in `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002F`:\n\n```bash\n# Basic screenshot\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png\n\n# Full page\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --full-page true\n\n# Specific element\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --selector \".main-content\" --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Felement.png\n```\n\n### Auto-Compression (Sharp)\n\nScreenshots >5MB auto-compress using Sharp (4-5x faster than ImageMagick):\n\n```bash\n# Default: compress if >5MB\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png\n\n# Custom threshold (3MB)\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --max-size 3\n\n# Disable compression\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --no-compress\n```\n\nStore screenshots for analysis in `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002F`.\n\n## Console Log Collection & Analysis\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n### Capture Logs\n\n```bash\n# Capture all logs for 10 seconds\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --duration 10000\n\n# Filter by type\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --types error,warn --duration 5000\n```\n\n### Session Storage Pattern\n\nStore logs for analysis in `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Flogs\u002F\u003Csession>\u002F`:\n\n```bash\n# Create session directory\nSESSION=\"$(date +%Y%m%d-%H%M%S)\"\nmkdir -p .opencode\u002Fchrome-devtools\u002Flogs\u002F$SESSION\n\n# Capture and store\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --duration 10000 > .opencode\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fconsole.json\nnode \"$SKILL_DIR\u002Fnetwork.js\" --url https:\u002F\u002Fexample.com > .opencode\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fnetwork.json\n\n# View errors\njq '.messages[] | select(.type==\"error\")' .opencode\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fconsole.json\n```\n\n### Root Cause Analysis\n\n```bash\n# 1. Check for JavaScript errors\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --types error,pageerror --duration 5000 | jq '.messages'\n\n# 2. Correlate with network failures\nnode \"$SKILL_DIR\u002Fnetwork.js\" --url https:\u002F\u002Fexample.com | jq '.requests[] | select(.response.status >= 400)'\n\n# 3. Check specific error stack traces\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --types error --duration 5000 | jq '.messages[].stack'\n```\n\n## Finding Elements\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nUse `snapshot.js` to discover selectors before interacting:\n\n```bash\n# Get all interactive elements\nnode \"$SKILL_DIR\u002Fsnapshot.js\" --url https:\u002F\u002Fexample.com | jq '.elements[] | {tagName, text, selector}'\n\n# Find buttons\nnode \"$SKILL_DIR\u002Fsnapshot.js\" --url https:\u002F\u002Fexample.com | jq '.elements[] | select(.tagName==\"button\")'\n\n# Find by text content\nnode \"$SKILL_DIR\u002Fsnapshot.js\" --url https:\u002F\u002Fexample.com | jq '.elements[] | select(.text | contains(\"Submit\"))'\n```\n\n## Error Recovery\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nIf script fails:\n\n```bash\n# 1. Capture current state (without navigating to preserve state)\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscreenshots\u002Fdebug.png\n\n# 2. Get console errors\nnode \"$SKILL_DIR\u002Fconsole.js\" --url about:blank --types error --duration 1000\n\n# 3. Discover correct selector\nnode \"$SKILL_DIR\u002Fsnapshot.js\" | jq '.elements[] | select(.text | contains(\"Submit\"))'\n\n# 4. Try XPath if CSS fails\nnode \"$SKILL_DIR\u002Fclick.js\" --selector \"\u002F\u002Fbutton[contains(text(),'Submit')]\"\n```\n\n## Common Patterns\n\n### Web Scraping\n```bash\nnode \"$SKILL_DIR\u002Fevaluate.js\" --url https:\u002F\u002Fexample.com --script \"\n  Array.from(document.querySelectorAll('.item')).map(el => ({\n    title: el.querySelector('h2')?.textContent,\n    link: el.querySelector('a')?.href\n  }))\n\" | jq '.result'\n```\n\n### Form Automation\n```bash\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fexample.com\u002Fform\nnode \"$SKILL_DIR\u002Ffill.js\" --selector \"#search\" --value \"query\"\nnode \"$SKILL_DIR\u002Fclick.js\" --selector \"button[type=submit]\"\n```\n\n### Performance Testing\n```bash\nnode \"$SKILL_DIR\u002Fperformance.js\" --url https:\u002F\u002Fexample.com | jq '.vitals'\n```\n\n## Script Options\n\nAll scripts support:\n- `--headless false` - Show browser window\n- `--close true` - Close browser completely (default: stay running)\n- `--timeout 30000` - Set timeout (ms)\n- `--wait-until networkidle2` - Wait strategy\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n## Troubleshooting\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n| Error | Solution |\n|-------|----------|\n| `Cannot find package 'puppeteer'` | Run `npm install` in scripts directory |\n| `libnss3.so` missing (Linux) | Run `.\u002Finstall-deps.sh` |\n| Element not found | Use `snapshot.js` to find correct selector |\n| Script hangs | Use `--timeout 60000` or `--wait-until load` |\n| Screenshot >5MB | Auto-compressed; use `--max-size 3` for lower |\n| Session stale | Delete `.browser-session.json` and retry |\n\n### Screenshot Analysis: Missing Images\n\nIf images don't appear in screenshots, they may be waiting for animation triggers:\n\n1. **Scroll-triggered animations**: Scroll element into view first\n   ```bash\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"document.querySelector('.lazy-image').scrollIntoView()\"\n   # Wait for animation\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"await new Promise(r => setTimeout(r, 1000))\"\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002Fresult.png\n   ```\n\n2. **Sequential animation queue**: Wait longer and retry\n   ```bash\n   # First attempt\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --url http:\u002F\u002Flocalhost:3000 --output .\u002Fattempt1.png\n\n   # Wait for animations to complete\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"await new Promise(r => setTimeout(r, 2000))\"\n\n   # Retry screenshot\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002Fattempt2.png\n   ```\n\n3. **Intersection Observer animations**: Trigger by scrolling through page\n   ```bash\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"window.scrollTo(0, document.body.scrollHeight)\"\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"await new Promise(r => setTimeout(r, 1500))\"\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"window.scrollTo(0, 0)\"\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002Ffull-loaded.png --full-page true\n   ```\n\n## Authentication & Cookies\n\nFor accessing protected\u002Fauthenticated pages, use one of these methods:\n\n### Method 1: Inject Cookies Directly\n\nUse when you have cookie values (from DevTools or manual extraction):\n\n```bash\n# Inject single cookie\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fsite.com \\\n  --cookies '[{\"name\":\"session\",\"value\":\"abc123\",\"domain\":\".site.com\"}]'\n\n# Multiple cookies with all properties\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fsite.com \\\n  --cookies '[{\"name\":\"session\",\"value\":\"abc\",\"domain\":\".site.com\",\"httpOnly\":true,\"secure\":true}]'\n\n# With Bearer token header\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fapi.site.com \\\n  --token \"Bearer eyJhbG...\" --header Authorization\n```\n\n### Method 2: Import from Browser Extension\n\nBest for complex auth (OAuth, multi-cookie sessions):\n\n```bash\n# 1. Install \"Cookie-Editor\" or \"EditThisCookie\" Chrome extension\n# 2. Navigate to site → Log in manually\n# 3. Click extension → Export as JSON → Save to cookies.json\n# 4. Import into puppeteer session:\n\nnode \"$SKILL_DIR\u002Fimport-cookies.js\" --file .\u002Fcookies.json --url https:\u002F\u002Fsite.com\n\n# Netscape format (from curl\u002Fwget):\nnode \"$SKILL_DIR\u002Fimport-cookies.js\" --file .\u002Fcookies.txt --format netscape --url https:\u002F\u002Fsite.com\n\n# Only import cookies matching target domain:\nnode \"$SKILL_DIR\u002Fimport-cookies.js\" --file .\u002Fcookies.json --url https:\u002F\u002Fsite.com --strict-domain\n```\n\n### Method 3: Use Your Chrome Profile\n\nMost reliable for complex auth (2FA, OAuth, SSO). Uses your existing Chrome session:\n\n```bash\n# Use Chrome's default profile (preserves all cookies, extensions, saved passwords)\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fsite.com --use-default-profile true\n\n# Use specific Chrome profile directory\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fsite.com --profile \"\u002Fpath\u002Fto\u002Fchrome\u002Fprofile\"\n```\n\n**⚠️ Important**: Chrome must be fully closed when using its profile (single instance lock).\n\n**Profile paths by OS:**\n- **macOS**: `~\u002FLibrary\u002FApplication Support\u002FGoogle\u002FChrome`\n- **Windows**: `%LOCALAPPDATA%\u002FGoogle\u002FChrome\u002FUser Data`\n- **Linux**: `~\u002F.config\u002Fgoogle-chrome`\n\n### Method 4: Connect to Running Chrome\n\nBest for debugging (can see browser window while scripts run):\n\n```bash\n# Step 1: Launch Chrome with remote debugging (in separate terminal)\n# macOS:\n\u002FApplications\u002FGoogle\\ Chrome.app\u002FContents\u002FMacOS\u002FGoogle\\ Chrome --remote-debugging-port=9222\n\n# Windows:\n\"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --remote-debugging-port=9222\n\n# Linux:\ngoogle-chrome --remote-debugging-port=9222\n\n# Step 2: Log in manually in the Chrome window\n\n# Step 3: Connect and automate\nnode \"$SKILL_DIR\u002Fconnect-chrome.js\" --browser-url http:\u002F\u002Flocalhost:9222 --url https:\u002F\u002Fsite.com\n\n# Or launch Chrome automatically (opens new window):\nnode \"$SKILL_DIR\u002Fconnect-chrome.js\" --launch --port 9222 --url https:\u002F\u002Fsite.com\n```\n\n### Session Persistence\n\nAuth sessions are saved to `.auth-session.json` for 24-hour reuse:\n\n```bash\n# First script injects auth\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fsite.com --cookies '[...]'\n\n# Subsequent scripts reuse saved auth automatically\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fsite.com\u002Fdashboard\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fsite.com\u002Fprofile --output .\u002Fprofile.png\n\n# Clear auth session when done\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fsite.com --clear true\n```\n\n### Choosing the Right Method\n\n| Method | Best For | Complexity |\n|--------|----------|------------|\n| Inject cookies | Simple session cookies, API tokens | Low |\n| Import from extension | Multi-cookie auth, OAuth tokens | Medium |\n| Chrome profile | 2FA, SSO, complex OAuth flows | Low* |\n| Connect to Chrome | Debugging, visual verification | Medium |\n\n*Requires Chrome to be closed first\n\n## Reference Documentation\n\n- `.\u002Freferences\u002Fcdp-domains.md` - Chrome DevTools Protocol domains\n- `.\u002Freferences\u002Fpuppeteer-reference.md` - Puppeteer API patterns\n- `.\u002Freferences\u002Fperformance-guide.md` - Core Web Vitals optimization\n- `.\u002Fscripts\u002FREADME.md` - Detailed script options\n","# Chrome DevTools Agent Skill\n\nBrowser automation via Puppeteer scripts with persistent sessions. All scripts output JSON.\n\n## Skill Location\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n```bash\n# Detect skill location (no cd needed - scripts use __dirname for paths)\nSKILL_DIR=\"\"\nif [ -d \".opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\" ]; then\n  SKILL_DIR=\".opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\"\nelif [ -d \"$HOME\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\" ]; then\n  SKILL_DIR=\"$HOME\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\"\nfi\n# Run scripts with full path: node \"$SKILL_DIR\u002Fscript.js\" --args\n```\n\n## Choosing Your Approach\n\n| Scenario | Approach |\n|----------|----------|\n| **Source-available sites** | Read source code first, write selectors directly |\n| **Unknown layouts** | Use `aria-snapshot.js` for semantic discovery |\n| **Visual inspection** | Take screenshots to verify rendering |\n| **Debug issues** | Collect console logs, analyze with session storage |\n| **Accessibility audit** | Use ARIA snapshot for semantic structure analysis |\n\n## Automation Browsing Running Mode\n\n- Detect current OS and launch browser as headless only when running on Linux, WSL, or CI environments.\n- For macOS\u002FWindows, browser always runs in headed mode for better debugging.\n- Run multiple scripts\u002Fsessions in parallel to simulate real user interactions.\n- Run multiple scripts\u002Fsessions in parallel to simulate different device types (mobile, tablet, desktop).\n- Skills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n## ARIA Snapshot (Element Discovery)\n\nWhen page structure is unknown, use `aria-snapshot.js` to get a YAML-formatted accessibility tree with semantic roles, accessible names, states, and stable element references.\n\n### Get ARIA Snapshot\n\n```bash\n# Generate ARIA snapshot and output to stdout\nnode \"$SKILL_DIR\u002Faria-snapshot.js\" --url https:\u002F\u002Fexample.com\n\n# Save to file in snapshots directory\nnode \"$SKILL_DIR\u002Faria-snapshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fsnapshots\u002Fpage.yaml\n```\n\n### Example YAML Output\n\n```yaml\n- banner:\n  - link \"Hacker News\" [ref=e1]\n    \u002Furl: https:\u002F\u002Fnews.ycombinator.com\n  - navigation:\n    - link \"new\" [ref=e2]\n    - link \"past\" [ref=e3]\n    - link \"comments\" [ref=e4]\n- main:\n  - list:\n    - listitem:\n      - link \"Show HN: My new project\" [ref=e8]\n      - text: \"128 points by user 3 hours ago\"\n- contentinfo:\n  - textbox [ref=e10]\n    \u002Fplaceholder: \"Search\"\n```\n\n### Interpreting ARIA Notation\n\n| Notation | Meaning |\n|----------|---------|\n| `[ref=eN]` | Stable identifier for interactive elements |\n| `[checked]` | Checkbox\u002Fradio is selected |\n| `[disabled]` | Element is inactive |\n| `[expanded]` | Accordion\u002Fdropdown is open |\n| `[level=N]` | Heading hierarchy (1-6) |\n| `\u002Furl:` | Link destination |\n| `\u002Fplaceholder:` | Input placeholder text |\n| `\u002Fvalue:` | Current input value |\n\n### Interact by Ref\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nUse `select-ref.js` to interact with elements by their ref:\n\n```bash\n# Click element with ref e5\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e5 --action click\n\n# Fill input with ref e10\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e10 --action fill --value \"search query\"\n\n# Get text content\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e8 --action text\n\n# Screenshot specific element\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e1 --action screenshot --output .\u002Flogo.png\n\n# Focus element\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e10 --action focus\n\n# Hover over element\nnode \"$SKILL_DIR\u002Fselect-ref.js\" --ref e5 --action hover\n```\n\n### Store Snapshots\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nStore snapshots for analysis in `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Fsnapshots\u002F`:\n\n```bash\n# Create snapshots directory\nmkdir -p .opencode\u002Fchrome-devtools\u002Fsnapshots\n\n# Capture and store with timestamp\nSESSION=\"$(date +%Y%m%d-%H%M%S)\"\nnode \"$SKILL_DIR\u002Faria-snapshot.js\" --url https:\u002F\u002Fexample.com --output .opencode\u002Fchrome-devtools\u002Fsnapshots\u002F$SESSION.yaml\n```\n\n### Workflow: Unknown Page Structure\n\n1. **Get snapshot** to discover elements:\n   ```bash\n   node \"$SKILL_DIR\u002Faria-snapshot.js\" --url https:\u002F\u002Fexample.com\n   ```\n\n2. **Identify target** from YAML output (e.g., `[ref=e5]` for a button)\n\n3. **Interact by ref**:\n   ```bash\n   node \"$SKILL_DIR\u002Fselect-ref.js\" --ref e5 --action click\n   ```\n\n4. **Verify result** with screenshot or new snapshot:\n   ```bash\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002Fresult.png\n   ```\n\n## Local HTML Files\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n**IMPORTANT**: Never browse local HTML files via `file:\u002F\u002F` protocol. Always serve via local server:\n**Why**: `file:\u002F\u002F` protocol blocks many browser features (CORS, ES modules, fetch API, service workers). Local server ensures proper HTTP behavior.\n\n```bash\n# Option 1: npx serve (recommended)\nnpx serve .\u002Fdist -p 3000 &\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url http:\u002F\u002Flocalhost:3000\n\n# Option 2: Python http.server\npython -m http.server 3000 --directory .\u002Fdist &\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url http:\u002F\u002Flocalhost:3000\n```\n\n**Note**: when port 3000 is busy, find an available port with `lsof -i :3000` and use a different one.\n\n## Quick Start\n\n```bash\n# Install dependencies (one-time setup)\nnpm install --prefix \"$SKILL_DIR\"\n\n# Test (browser stays running for session reuse)\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fexample.com\n# Output: {\"success\": true, \"url\": \"...\", \"title\": \"...\"}\n```\n\n**Linux\u002FWSL only**: Run `\"$SKILL_DIR\u002Finstall-deps.sh\"` first for Chrome system libraries.\n\n## Session Persistence\n\nBrowser state persists across script executions via WebSocket endpoint file (`.browser-session.json`).\n\n**Default behavior**: Scripts disconnect but keep browser running for session reuse.\n\n```bash\n# First script: launches browser, navigates, disconnects (browser stays running)\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fexample.com\u002Flogin\n\n# Subsequent scripts: connect to existing browser, reuse page state\nnode \"$SKILL_DIR\u002Ffill.js\" --selector \"#email\" --value \"user@example.com\"\nnode \"$SKILL_DIR\u002Ffill.js\" --selector \"#password\" --value \"secret\"\nnode \"$SKILL_DIR\u002Fclick.js\" --selector \"button[type=submit]\"\n\n# Close browser when done\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url about:blank --close true\n```\n\n**Session management**:\n- `--close true`: Close browser and clear session\n- Default (no flag): Keep browser running for next script\n\n## Available Scripts\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nAll in `.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002F`:\n\n| Script | Purpose |\n|--------|---------|\n| `navigate.js` | Navigate to URLs |\n| `screenshot.js` | Capture screenshots (auto-compress >5MB via Sharp) |\n| `click.js` | Click elements |\n| `fill.js` | Fill form fields |\n| `evaluate.js` | Execute JS in page context |\n| `snapshot.js` | Extract interactive elements (JSON format) |\n| `aria-snapshot.js` | Get ARIA accessibility tree (YAML format with refs) |\n| `select-ref.js` | Interact with elements by ref from ARIA snapshot |\n| `console.js` | Monitor console messages\u002Ferrors |\n| `network.js` | Track HTTP requests\u002Fresponses |\n| `performance.js` | Measure Core Web Vitals |\n| `ws-debug.js` | Debug WebSocket connections (basic) |\n| `ws-full-debug.js` | Debug WebSocket with full events\u002Fframes |\n| `inject-auth.js` | Inject cookies\u002Ftokens for authentication |\n| `import-cookies.js` | Import cookies from JSON\u002FNetscape file |\n| `connect-chrome.js` | Connect to Chrome with remote debugging |\n\n## Workflow Loop\n\n1. **Execute** focused script for single task\n2. **Observe** JSON output\n3. **Assess** completion status\n4. **Decide** next action\n5. **Repeat** until done\n\n## Writing Custom Test Scripts\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nFor complex automation, write scripts to `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Ftmp\u002F`:\n\n```bash\n# Create tmp directory for test scripts\nmkdir -p $SKILL_DIR\u002F.opencode\u002Fchrome-devtools\u002Ftmp\n\n# Write a test script\ncat > $SKILL_DIR\u002F.opencode\u002Fchrome-devtools\u002Ftmp\u002Flogin-test.js \u003C\u003C 'EOF'\nimport { getBrowser, getPage, disconnectBrowser, outputJSON } from '..\u002Fscripts\u002Flib\u002Fbrowser.js';\n\nasync function loginTest() {\n  const browser = await getBrowser();\n  const page = await getPage(browser);\n\n  await page.goto('https:\u002F\u002Fexample.com\u002Flogin');\n  await page.type('#email', 'user@example.com');\n  await page.type('#password', 'secret');\n  await page.click('button[type=submit]');\n  await page.waitForNavigation();\n\n  outputJSON({\n    success: true,\n    url: page.url(),\n    title: await page.title()\n  });\n\n  await disconnectBrowser();\n}\n\nloginTest();\nEOF\n\n# Run the test\nnode $SKILL_DIR\u002F.opencode\u002Fchrome-devtools\u002Ftmp\u002Flogin-test.js\n```\n\n**Key principles for custom scripts**:\n- Single-purpose: one script, one task\n- Always call `disconnectBrowser()` at the end (keeps browser running)\n- Use `closeBrowser()` only when ending session completely\n- Output JSON for easy parsing\n- Plain JavaScript only in `page.evaluate()` callbacks\n\n## Screenshots\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nStore screenshots for analysis in `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002F`:\n\n```bash\n# Basic screenshot\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png\n\n# Full page\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --full-page true\n\n# Specific element\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --selector \".main-content\" --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Felement.png\n```\n\n### Auto-Compression (Sharp)\n\nScreenshots >5MB auto-compress using Sharp (4-5x faster than ImageMagick):\n\n```bash\n# Default: compress if >5MB\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png\n\n# Custom threshold (3MB)\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --max-size 3\n\n# Disable compression\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --no-compress\n```\n\nStore screenshots for analysis in `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Fscreenshots\u002F`.\n\n## Console Log Collection & Analysis\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n### Capture Logs\n\n```bash\n# Capture all logs for 10 seconds\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --duration 10000\n\n# Filter by type\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --types error,warn --duration 5000\n```\n\n### Session Storage Pattern\n\nStore logs for analysis in `\u003Cproject>\u002F.opencode\u002Fchrome-devtools\u002Flogs\u002F\u003Csession>\u002F`:\n\n```bash\n# Create session directory\nSESSION=\"$(date +%Y%m%d-%H%M%S)\"\nmkdir -p .opencode\u002Fchrome-devtools\u002Flogs\u002F$SESSION\n\n# Capture and store\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --duration 10000 > .opencode\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fconsole.json\nnode \"$SKILL_DIR\u002Fnetwork.js\" --url https:\u002F\u002Fexample.com > .opencode\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fnetwork.json\n\n# View errors\njq '.messages[] | select(.type==\"error\")' .opencode\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fconsole.json\n```\n\n### Root Cause Analysis\n\n```bash\n# 1. Check for JavaScript errors\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --types error,pageerror --duration 5000 | jq '.messages'\n\n# 2. Correlate with network failures\nnode \"$SKILL_DIR\u002Fnetwork.js\" --url https:\u002F\u002Fexample.com | jq '.requests[] | select(.response.status >= 400)'\n\n# 3. Check specific error stack traces\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --types error --duration 5000 | jq '.messages[].stack'\n```\n\n## Finding Elements\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nUse `snapshot.js` to discover selectors before interacting:\n\n```bash\n# Get all interactive elements\nnode \"$SKILL_DIR\u002Fsnapshot.js\" --url https:\u002F\u002Fexample.com | jq '.elements[] | {tagName, text, selector}'\n\n# Find buttons\nnode \"$SKILL_DIR\u002Fsnapshot.js\" --url https:\u002F\u002Fexample.com | jq '.elements[] | select(.tagName==\"button\")'\n\n# Find by text content\nnode \"$SKILL_DIR\u002Fsnapshot.js\" --url https:\u002F\u002Fexample.com | jq '.elements[] | select(.text | contains(\"Submit\"))'\n```\n\n## Error Recovery\n\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\nIf script fails:\n\n```bash\n# 1. Capture current state (without navigating to preserve state)\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscreenshots\u002Fdebug.png\n\n# 2. Get console errors\nnode \"$SKILL_DIR\u002Fconsole.js\" --url about:blank --types error --duration 1000\n\n# 3. Discover correct selector\nnode \"$SKILL_DIR\u002Fsnapshot.js\" | jq '.elements[] | select(.text | contains(\"Submit\"))'\n\n# 4. Try XPath if CSS fails\nnode \"$SKILL_DIR\u002Fclick.js\" --selector \"\u002F\u002Fbutton[contains(text(),'Submit')]\"\n```\n\n## Common Patterns\n\n### Web Scraping\n```bash\nnode \"$SKILL_DIR\u002Fevaluate.js\" --url https:\u002F\u002Fexample.com --script \"\n  Array.from(document.querySelectorAll('.item')).map(el => ({\n    title: el.querySelector('h2')?.textContent,\n    link: el.querySelector('a')?.href\n  }))\n\" | jq '.result'\n```\n\n### Form Automation\n```bash\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fexample.com\u002Fform\nnode \"$SKILL_DIR\u002Ffill.js\" --selector \"#search\" --value \"query\"\nnode \"$SKILL_DIR\u002Fclick.js\" --selector \"button[type=submit]\"\n```\n\n### Performance Testing\n```bash\nnode \"$SKILL_DIR\u002Fperformance.js\" --url https:\u002F\u002Fexample.com | jq '.vitals'\n```\n\n## Script Options\n\nAll scripts support:\n- `--headless false` - Show browser window\n- `--close true` - Close browser completely (default: stay running)\n- `--timeout 30000` - Set timeout (ms)\n- `--wait-until networkidle2` - Wait strategy\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n## Troubleshooting\nSkills can exist in **project-scope** or **user-scope**. Priority: project-scope > user-scope.\n\n| Error | Solution |\n|-------|----------|\n| `Cannot find package 'puppeteer'` | Run `npm install` in scripts directory |\n| `libnss3.so` missing (Linux) | Run `.\u002Finstall-deps.sh` |\n| Element not found | Use `snapshot.js` to find correct selector |\n| Script hangs | Use `--timeout 60000` or `--wait-until load` |\n| Screenshot >5MB | Auto-compressed; use `--max-size 3` for lower |\n| Session stale | Delete `.browser-session.json` and retry |\n\n### Screenshot Analysis: Missing Images\n\nIf images don't appear in screenshots, they may be waiting for animation triggers:\n\n1. **Scroll-triggered animations**: Scroll element into view first\n   ```bash\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"document.querySelector('.lazy-image').scrollIntoView()\"\n   # Wait for animation\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"await new Promise(r => setTimeout(r, 1000))\"\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002Fresult.png\n   ```\n\n2. **Sequential animation queue**: Wait longer and retry\n   ```bash\n   # First attempt\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --url http:\u002F\u002Flocalhost:3000 --output .\u002Fattempt1.png\n\n   # Wait for animations to complete\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"await new Promise(r => setTimeout(r, 2000))\"\n\n   # Retry screenshot\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002Fattempt2.png\n   ```\n\n3. **Intersection Observer animations**: Trigger by scrolling through page\n   ```bash\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"window.scrollTo(0, document.body.scrollHeight)\"\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"await new Promise(r => setTimeout(r, 1500))\"\n   node \"$SKILL_DIR\u002Fevaluate.js\" --script \"window.scrollTo(0, 0)\"\n   node \"$SKILL_DIR\u002Fscreenshot.js\" --output .\u002Ffull-loaded.png --full-page true\n   ```\n\n## Authentication & Cookies\n\nFor accessing protected\u002Fauthenticated pages, use one of these methods:\n\n### Method 1: Inject Cookies Directly\n\nUse when you have cookie values (from DevTools or manual extraction):\n\n```bash\n# Inject single cookie\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fsite.com \\\n  --cookies '[{\"name\":\"session\",\"value\":\"abc123\",\"domain\":\".site.com\"}]'\n\n# Multiple cookies with all properties\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fsite.com \\\n  --cookies '[{\"name\":\"session\",\"value\":\"abc\",\"domain\":\".site.com\",\"httpOnly\":true,\"secure\":true}]'\n\n# With Bearer token header\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fapi.site.com \\\n  --token \"Bearer eyJhbG...\" --header Authorization\n```\n\n### Method 2: Import from Browser Extension\n\nBest for complex auth (OAuth, multi-cookie sessions):\n\n```bash\n# 1. Install \"Cookie-Editor\" or \"EditThisCookie\" Chrome extension\n# 2. Navigate to site → Log in manually\n# 3. Click extension → Export as JSON → Save to cookies.json\n# 4. Import into puppeteer session:\n\nnode \"$SKILL_DIR\u002Fimport-cookies.js\" --file .\u002Fcookies.json --url https:\u002F\u002Fsite.com\n\n# Netscape format (from curl\u002Fwget):\nnode \"$SKILL_DIR\u002Fimport-cookies.js\" --file .\u002Fcookies.txt --format netscape --url https:\u002F\u002Fsite.com\n\n# Only import cookies matching target domain:\nnode \"$SKILL_DIR\u002Fimport-cookies.js\" --file .\u002Fcookies.json --url https:\u002F\u002Fsite.com --strict-domain\n```\n\n### Method 3: Use Your Chrome Profile\n\nMost reliable for complex auth (2FA, OAuth, SSO). Uses your existing Chrome session:\n\n```bash\n# Use Chrome's default profile (preserves all cookies, extensions, saved passwords)\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fsite.com --use-default-profile true\n\n# Use specific Chrome profile directory\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fsite.com --profile \"\u002Fpath\u002Fto\u002Fchrome\u002Fprofile\"\n```\n\n**⚠️ Important**: Chrome must be fully closed when using its profile (single instance lock).\n\n**Profile paths by OS:**\n- **macOS**: `~\u002FLibrary\u002FApplication Support\u002FGoogle\u002FChrome`\n- **Windows**: `%LOCALAPPDATA%\u002FGoogle\u002FChrome\u002FUser Data`\n- **Linux**: `~\u002F.config\u002Fgoogle-chrome`\n\n### Method 4: Connect to Running Chrome\n\nBest for debugging (can see browser window while scripts run):\n\n```bash\n# Step 1: Launch Chrome with remote debugging (in separate terminal)\n# macOS:\n\u002FApplications\u002FGoogle\\ Chrome.app\u002FContents\u002FMacOS\u002FGoogle\\ Chrome --remote-debugging-port=9222\n\n# Windows:\n\"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --remote-debugging-port=9222\n\n# Linux:\ngoogle-chrome --remote-debugging-port=9222\n\n# Step 2: Log in manually in the Chrome window\n\n# Step 3: Connect and automate\nnode \"$SKILL_DIR\u002Fconnect-chrome.js\" --browser-url http:\u002F\u002Flocalhost:9222 --url https:\u002F\u002Fsite.com\n\n# Or launch Chrome automatically (opens new window):\nnode \"$SKILL_DIR\u002Fconnect-chrome.js\" --launch --port 9222 --url https:\u002F\u002Fsite.com\n```\n\n### Session Persistence\n\nAuth sessions are saved to `.auth-session.json` for 24-hour reuse:\n\n```bash\n# First script injects auth\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fsite.com --cookies '[...]'\n\n# Subsequent scripts reuse saved auth automatically\nnode \"$SKILL_DIR\u002Fnavigate.js\" --url https:\u002F\u002Fsite.com\u002Fdashboard\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fsite.com\u002Fprofile --output .\u002Fprofile.png\n\n# Clear auth session when done\nnode \"$SKILL_DIR\u002Finject-auth.js\" --url https:\u002F\u002Fsite.com --clear true\n```\n\n### Choosing the Right Method\n\n| Method | Best For | Complexity |\n|--------|----------|------------|\n| Inject cookies | Simple session cookies, API tokens | Low |\n| Import from extension | Multi-cookie auth, OAuth tokens | Medium |\n| Chrome profile | 2FA, SSO, complex OAuth flows | Low* |\n| Connect to Chrome | Debugging, visual verification | Medium |\n\n*Requires Chrome to be closed first\n\n## Reference Documentation\n\n- `.\u002Freferences\u002Fcdp-domains.md` - Chrome DevTools Protocol domains\n- `.\u002Freferences\u002Fpuppeteer-reference.md` - Puppeteer API patterns\n- `.\u002Freferences\u002Fperformance-guide.md` - Core Web Vitals optimization\n- `.\u002Fscripts\u002FREADME.md` - Detailed script options\n",{"name":5,"license":15,"version":24,"description":7},"1.1.0","main","b2c7cb35d94e515781b32f7e3948740c401f86dc",".claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory","https:\u002F\u002Fgithub.com\u002Fminhlongs","https:\u002F\u002Fwww.mekongmind.com","AI-powered business ops for Vietnam — Zalo OA, tax compliance, AI video","2026-11-15 02:50:35",{"source":8,"skillName":5,"commands":34,"prompt":44,"zipAvailable":45},[35,38,41],{"tool":36,"command":37},"npx","npx skills add minhlongs\u002Fsophia-ai-factory --skill chrome-devtools",{"tool":39,"command":40},"bunx","bunx skills add minhlongs\u002Fsophia-ai-factory --skill chrome-devtools",{"tool":42,"command":43},"pnpm","pnpm dlx skills add minhlongs\u002Fsophia-ai-factory --skill chrome-devtools","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002FSKILL.md",true,[47,53,57,61,67,71,75,79,83,87,91,95,99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159],{"path":48,"resourceType":49,"resourceTypeDesc":50,"sizeBytes":51,"sourceHtmlUrl":52},"references\u002Fcdp-domains.md","REFERENCE","参考文档",17812,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Freferences\u002Fcdp-domains.md",{"path":54,"resourceType":49,"resourceTypeDesc":50,"sizeBytes":55,"sourceHtmlUrl":56},"references\u002Fperformance-guide.md",21550,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Freferences\u002Fperformance-guide.md",{"path":58,"resourceType":49,"resourceTypeDesc":50,"sizeBytes":59,"sourceHtmlUrl":60},"references\u002Fpuppeteer-reference.md",19065,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Freferences\u002Fpuppeteer-reference.md",{"path":62,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":65,"sourceHtmlUrl":66},"scripts\u002F__tests__\u002Ferror-handling.test.js","SCRIPT","脚本",3711,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002F__tests__\u002Ferror-handling.test.js",{"path":68,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":69,"sourceHtmlUrl":70},"scripts\u002F__tests__\u002Fselector.test.js",6525,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002F__tests__\u002Fselector.test.js",{"path":72,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":73,"sourceHtmlUrl":74},"scripts\u002F.gitignore",53,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002F.gitignore",{"path":76,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":77,"sourceHtmlUrl":78},"scripts\u002Faria-snapshot.js",10330,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Faria-snapshot.js",{"path":80,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":81,"sourceHtmlUrl":82},"scripts\u002Fclick.js",2446,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fclick.js",{"path":84,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":85,"sourceHtmlUrl":86},"scripts\u002Fconnect-chrome.js",4235,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fconnect-chrome.js",{"path":88,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":89,"sourceHtmlUrl":90},"scripts\u002Fconsole.js",1974,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fconsole.js",{"path":92,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":93,"sourceHtmlUrl":94},"scripts\u002Fevaluate.js",1316,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fevaluate.js",{"path":96,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":97,"sourceHtmlUrl":98},"scripts\u002Ffill.js",2111,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Ffill.js",{"path":100,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":101,"sourceHtmlUrl":102},"scripts\u002Fimport-cookies.js",5859,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fimport-cookies.js",{"path":104,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":105,"sourceHtmlUrl":106},"scripts\u002Finject-auth.js",7442,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Finject-auth.js",{"path":108,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":109,"sourceHtmlUrl":110},"scripts\u002Finstall-deps.sh",4371,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Finstall-deps.sh",{"path":112,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":113,"sourceHtmlUrl":114},"scripts\u002Finstall.sh",2137,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Finstall.sh",{"path":116,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":117,"sourceHtmlUrl":118},"scripts\u002Flib\u002Fbrowser.js",8798,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Flib\u002Fbrowser.js",{"path":120,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":121,"sourceHtmlUrl":122},"scripts\u002Flib\u002Fselector.js",5422,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Flib\u002Fselector.js",{"path":124,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":125,"sourceHtmlUrl":126},"scripts\u002Fnavigate.js",1978,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fnavigate.js",{"path":128,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":129,"sourceHtmlUrl":130},"scripts\u002Fnetwork.js",2955,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fnetwork.js",{"path":132,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":133,"sourceHtmlUrl":134},"scripts\u002Fpackage.json",345,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fpackage.json",{"path":136,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":137,"sourceHtmlUrl":138},"scripts\u002Fperformance.js",4103,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fperformance.js",{"path":140,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":141,"sourceHtmlUrl":142},"scripts\u002FREADME.md",8092,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002FREADME.md",{"path":144,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":145,"sourceHtmlUrl":146},"scripts\u002Fscreenshot.js",6400,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fscreenshot.js",{"path":148,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":149,"sourceHtmlUrl":150},"scripts\u002Fselect-ref.js",3931,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fselect-ref.js",{"path":152,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":153,"sourceHtmlUrl":154},"scripts\u002Fsnapshot.js",3725,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fsnapshot.js",{"path":156,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":157,"sourceHtmlUrl":158},"scripts\u002Fws-debug.js",1496,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fws-debug.js",{"path":160,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":161,"sourceHtmlUrl":162},"scripts\u002Fws-full-debug.js",3335,"https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.claude\u002Fworktrees-archive.bak\u002F20260614-234042\u002Fagent-phase-01-openclaw\u002Fagent-phase-01-openclaw\u002F.opencode\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fws-full-debug.js",[164,171,179,187,194,202],{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":168,"categories":169,"keywords":170,"publishedAt":19},"01M7AGRPKF5YS8YXJG94537JBP","web-testing","Web testing with Playwright, Vitest, k6. E2E\u002Funit\u002Fintegration\u002Fload\u002Fsecurity\u002Fvisual\u002Fa11y testing. Use for test automation, flakiness, Core Web Vitals, mobile gestures, cross-browser.","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fweb-testing\u002FSKILL.md",[],[],{"skillNo":172,"name":173,"nameZh":6,"description":174,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":175,"licenseFileUrl":6,"sourceHtmlUrl":176,"categories":177,"keywords":178,"publishedAt":19},"01M7AGRGNGKWMZKBGMBCNNAQ9M","web-frameworks","Build with Next.js (App Router, RSC, SSR, ISR), Turborepo monorepos. Use for React apps, server rendering, build optimization, caching strategies, shared dependencies.","MIT","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fweb-frameworks\u002FSKILL.md",[],[],{"skillNo":180,"name":181,"nameZh":6,"description":182,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":175,"licenseFileUrl":183,"sourceHtmlUrl":184,"categories":185,"keywords":186,"publishedAt":19},"01M7AGQYS5CV6TSY3JFT05XZ3C","ui-styling","Style UIs with shadcn\u002Fui components (Radix UI + Tailwind CSS). Use for accessible components, themes, dark mode, responsive layouts, design systems, color customization.","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fui-styling\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fui-styling\u002FSKILL.md",[],[],{"skillNo":188,"name":189,"nameZh":6,"description":190,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":175,"licenseFileUrl":6,"sourceHtmlUrl":191,"categories":192,"keywords":193,"publishedAt":19},"01M7AGQSGV9RP800VBKRWNT0GG","threejs","Build 3D web apps with Three.js (WebGL\u002FWebGPU). 556 searchable examples, 60 API classes, 20 use cases. Actions: create 3D scene, load model, add animation, implement physics, build VR\u002FXR. Topics: GLTF loader, PBR materials, particle effects, shadows, post-processing, compute shaders, TSL. Integrations: WebGPU, physics engines, spatial audio.","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fthreejs\u002FSKILL.md",[],[],{"skillNo":195,"name":196,"nameZh":6,"description":197,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":198,"sourceHtmlUrl":199,"categories":200,"keywords":201,"publishedAt":19},"01M7AGQKNJ8AZ0XP1BZ99Q6NTM","skill-creator","Create or update Claude skills. Use for new skills, skill references, skill scripts, optimizing existing skills, extending Claude's capabilities.","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fskill-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fskill-creator\u002FSKILL.md",[],[],{"skillNo":203,"name":204,"nameZh":6,"description":205,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":175,"licenseFileUrl":6,"sourceHtmlUrl":206,"categories":207,"keywords":208,"publishedAt":19},"01M7AGQ73E70SY4RGWW11TC7HN","sequential-thinking","Apply step-by-step analysis for complex problems with revision capability. Use for multi-step reasoning, hypothesis verification, adaptive planning, problem decomposition, course correction.","https:\u002F\u002Fgithub.com\u002Fminhlongs\u002Fsophia-ai-factory\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fsequential-thinking\u002FSKILL.md",[],[]]