[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CFHTTC3VN1HH8KYRCPC0CG":3,"skill-same:01M6CFHTTC3VN1HH8KYRCPC0CG":191},{"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":26,"publishedAt":47,"linkOnly":48,"markdownContent":49,"markdownBody":50,"frontMatter":51,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":56,"repositoryHtmlUrl":57,"repositoryHomepageUrl":58,"ownerHtmlUrl":59,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":60,"install":61,"resources":74},"01M6CFHTTC3VN1HH8KYRCPC0CG","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.","hoanghd218\u002Fdocons","hoanghd218","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F49197448?v=4","01M6CEG06HBF8MQKQX19CR32ME","Hoang218","01M6CFGYFPDRM365Q0JTRNVJJ8",0,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],"chrome","chrome devtools","devtools","network monitoring","screenshots","use","scraping","web scraping","automate","analysis","network","monitoring","puppeteer","debugging","sessions","web","javascript","automation","performance","cli","2026-11-10 10:12:30",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 \".claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\" ]; then\n  SKILL_DIR=\".claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\"\nelif [ -d \"$HOME\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\" ]; then\n  SKILL_DIR=\"$HOME\u002F.claude\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.claude\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.claude\u002Fchrome-devtools\u002Fsnapshots\u002F`:\n\n```bash\n# Create snapshots directory\nmkdir -p .claude\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 .claude\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 `.claude\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.claude\u002Fchrome-devtools\u002Ftmp\u002F`:\n\n```bash\n# Create tmp directory for test scripts\nmkdir -p $SKILL_DIR\u002F.claude\u002Fchrome-devtools\u002Ftmp\n\n# Write a test script\ncat > $SKILL_DIR\u002F.claude\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.claude\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.claude\u002Fchrome-devtools\u002Fscreenshots\u002F`:\n\n```bash\n# Basic screenshot\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.claude\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png\n\n# Full page\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.claude\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.claude\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.claude\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png\n\n# Custom threshold (3MB)\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.claude\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --max-size 3\n\n# Disable compression\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.claude\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --no-compress\n```\n\nStore screenshots for analysis in `\u003Cproject>\u002F.claude\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.claude\u002Fchrome-devtools\u002Flogs\u002F\u003Csession>\u002F`:\n\n```bash\n# Create session directory\nSESSION=\"$(date +%Y%m%d-%H%M%S)\"\nmkdir -p .claude\u002Fchrome-devtools\u002Flogs\u002F$SESSION\n\n# Capture and store\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --duration 10000 > .claude\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fconsole.json\nnode \"$SKILL_DIR\u002Fnetwork.js\" --url https:\u002F\u002Fexample.com > .claude\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fnetwork.json\n\n# View errors\njq '.messages[] | select(.type==\"error\")' .claude\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.claude\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 \".claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\" ]; then\n  SKILL_DIR=\".claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\"\nelif [ -d \"$HOME\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\" ]; then\n  SKILL_DIR=\"$HOME\u002F.claude\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.claude\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.claude\u002Fchrome-devtools\u002Fsnapshots\u002F`:\n\n```bash\n# Create snapshots directory\nmkdir -p .claude\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 .claude\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 `.claude\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.claude\u002Fchrome-devtools\u002Ftmp\u002F`:\n\n```bash\n# Create tmp directory for test scripts\nmkdir -p $SKILL_DIR\u002F.claude\u002Fchrome-devtools\u002Ftmp\n\n# Write a test script\ncat > $SKILL_DIR\u002F.claude\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.claude\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.claude\u002Fchrome-devtools\u002Fscreenshots\u002F`:\n\n```bash\n# Basic screenshot\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.claude\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png\n\n# Full page\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.claude\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.claude\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.claude\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png\n\n# Custom threshold (3MB)\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.claude\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --max-size 3\n\n# Disable compression\nnode \"$SKILL_DIR\u002Fscreenshot.js\" --url https:\u002F\u002Fexample.com --output .\u002F.claude\u002Fchrome-devtools\u002Fscreenshots\u002Fpage.png --no-compress\n```\n\nStore screenshots for analysis in `\u003Cproject>\u002F.claude\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.claude\u002Fchrome-devtools\u002Flogs\u002F\u003Csession>\u002F`:\n\n```bash\n# Create session directory\nSESSION=\"$(date +%Y%m%d-%H%M%S)\"\nmkdir -p .claude\u002Fchrome-devtools\u002Flogs\u002F$SESSION\n\n# Capture and store\nnode \"$SKILL_DIR\u002Fconsole.js\" --url https:\u002F\u002Fexample.com --duration 10000 > .claude\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fconsole.json\nnode \"$SKILL_DIR\u002Fnetwork.js\" --url https:\u002F\u002Fexample.com > .claude\u002Fchrome-devtools\u002Flogs\u002F$SESSION\u002Fnetwork.json\n\n# View errors\njq '.messages[] | select(.type==\"error\")' .claude\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.claude\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":52,"description":7},"1.1.0","main","863082984c7c65197a5d20dc7c6e1fda6045b372","landingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools",1,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons","https:\u002F\u002Fdocons.vercel.app","https:\u002F\u002Fgithub.com\u002Fhoanghd218","2026-08-25 23:11:43",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add hoanghd218\u002Fdocons --skill chrome-devtools",{"tool":67,"command":68},"bunx","bunx skills add hoanghd218\u002Fdocons --skill chrome-devtools",{"tool":70,"command":71},"pnpm","pnpm dlx skills add hoanghd218\u002Fdocons --skill chrome-devtools","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002FSKILL.md",true,[75,81,85,89,95,99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187],{"path":76,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":79,"sourceHtmlUrl":80},"references\u002Fcdp-domains.md","REFERENCE","参考文档",17812,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Freferences\u002Fcdp-domains.md",{"path":82,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":83,"sourceHtmlUrl":84},"references\u002Fperformance-guide.md",21550,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Freferences\u002Fperformance-guide.md",{"path":86,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":87,"sourceHtmlUrl":88},"references\u002Fpuppeteer-reference.md",19065,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Freferences\u002Fpuppeteer-reference.md",{"path":90,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":93,"sourceHtmlUrl":94},"scripts\u002F__tests__\u002Ferror-handling.test.js","SCRIPT","脚本",3711,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002F__tests__\u002Ferror-handling.test.js",{"path":96,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":97,"sourceHtmlUrl":98},"scripts\u002F__tests__\u002Fselector.test.js",6525,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002F__tests__\u002Fselector.test.js",{"path":100,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":101,"sourceHtmlUrl":102},"scripts\u002F.gitignore",53,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002F.gitignore",{"path":104,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":105,"sourceHtmlUrl":106},"scripts\u002Faria-snapshot.js",10330,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Faria-snapshot.js",{"path":108,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":109,"sourceHtmlUrl":110},"scripts\u002Fclick.js",2446,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fclick.js",{"path":112,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":113,"sourceHtmlUrl":114},"scripts\u002Fconnect-chrome.js",4235,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fconnect-chrome.js",{"path":116,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":117,"sourceHtmlUrl":118},"scripts\u002Fconsole.js",1974,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fconsole.js",{"path":120,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":121,"sourceHtmlUrl":122},"scripts\u002Fevaluate.js",1316,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fevaluate.js",{"path":124,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":125,"sourceHtmlUrl":126},"scripts\u002Ffill.js",2111,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Ffill.js",{"path":128,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":129,"sourceHtmlUrl":130},"scripts\u002Fimport-cookies.js",5859,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fimport-cookies.js",{"path":132,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":133,"sourceHtmlUrl":134},"scripts\u002Finject-auth.js",7442,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Finject-auth.js",{"path":136,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":137,"sourceHtmlUrl":138},"scripts\u002Finstall-deps.sh",4371,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Finstall-deps.sh",{"path":140,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":141,"sourceHtmlUrl":142},"scripts\u002Finstall.sh",2137,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Finstall.sh",{"path":144,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":145,"sourceHtmlUrl":146},"scripts\u002Flib\u002Fbrowser.js",8798,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Flib\u002Fbrowser.js",{"path":148,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":149,"sourceHtmlUrl":150},"scripts\u002Flib\u002Fselector.js",5422,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Flib\u002Fselector.js",{"path":152,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":153,"sourceHtmlUrl":154},"scripts\u002Fnavigate.js",1978,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fnavigate.js",{"path":156,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":157,"sourceHtmlUrl":158},"scripts\u002Fnetwork.js",2955,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fnetwork.js",{"path":160,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":161,"sourceHtmlUrl":162},"scripts\u002Fpackage.json",345,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fpackage.json",{"path":164,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":165,"sourceHtmlUrl":166},"scripts\u002Fperformance.js",4103,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fperformance.js",{"path":168,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":169,"sourceHtmlUrl":170},"scripts\u002FREADME.md",8082,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002FREADME.md",{"path":172,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":173,"sourceHtmlUrl":174},"scripts\u002Fscreenshot.js",6400,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fscreenshot.js",{"path":176,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":177,"sourceHtmlUrl":178},"scripts\u002Fselect-ref.js",3931,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fselect-ref.js",{"path":180,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":181,"sourceHtmlUrl":182},"scripts\u002Fsnapshot.js",3725,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fsnapshot.js",{"path":184,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":185,"sourceHtmlUrl":186},"scripts\u002Fws-debug.js",1496,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fws-debug.js",{"path":188,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":189,"sourceHtmlUrl":190},"scripts\u002Fws-full-debug.js",3335,"https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.claude\u002Fskills\u002Fchrome-devtools\u002Fscripts\u002Fws-full-debug.js",[192,215,233,259,285,297],{"skillNo":193,"name":194,"nameZh":6,"description":195,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":196,"categories":197,"keywords":199,"publishedAt":47},"01M6CFWQKBPK223JYTA0T4WKGF","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\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.opencode\u002Fskills\u002Fweb-testing\u002FSKILL.md",[198],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[200,42,201,202,203,44,204,205,206,207,208,209,210,211,212,213,32,214],"web testing","testing","security","gestures","playwright","test","test automation","core","browser","integration","core web vitals","k6","e2e","vitest","mobile",{"skillNo":216,"name":217,"nameZh":6,"description":218,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":219,"licenseFileUrl":6,"sourceHtmlUrl":220,"categories":221,"keywords":222,"publishedAt":47},"01M6CFWKWR6J11YJRE9EX702JY","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\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.opencode\u002Fskills\u002Fweb-frameworks\u002FSKILL.md",[],[223,42,224,225,226,32,227,228,229,230,231,232],"web frameworks","Optimization","build","router","js","Next.js","turborepo","server","ssr","react",{"skillNo":234,"name":235,"nameZh":6,"description":236,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":219,"licenseFileUrl":6,"sourceHtmlUrl":237,"categories":238,"keywords":247,"publishedAt":47},"01M6CFW31HEVJTMWZNXXH6RJZW","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\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.opencode\u002Fskills\u002Fui-styling\u002FSKILL.md",[239,242],{"categoryNo":240,"categoryName":241,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":243,"categoryName":244,"taxonomyType":245,"taxonomyTypeDesc":246},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[248,249,250,32,251,252,253,254,255,256,257,258],"ui styling","styling","ui","radix ui","customization","Tailwind","shadcn","design systems","components","css","design",{"skillNo":260,"name":261,"nameZh":6,"description":262,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":219,"licenseFileUrl":6,"sourceHtmlUrl":263,"categories":264,"keywords":268,"publishedAt":47},"01M6CFVY2N18A5J9YW3X14GDHZ","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\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.opencode\u002Fskills\u002Fthreejs\u002FSKILL.md",[265],{"categoryNo":266,"categoryName":267,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",[261,269,270,271,272,273,274,275,42,276,277,278,279,225,280,32,281,282,283,284],"webgl","api","actions","examples","shaders","create","webgpu","implement","Animation","pbr","gltf","Spatial","integrations","model","Audio","3D",{"skillNo":286,"name":287,"nameZh":6,"description":288,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":219,"licenseFileUrl":6,"sourceHtmlUrl":289,"categories":290,"keywords":291,"publishedAt":47},"01M6CFVFW9NS3M49KX9K9GKFF7","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\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.opencode\u002Fskills\u002Fsequential-thinking\u002FSKILL.md",[],[292,293,32,36,294,295,296],"sequential thinking","planning","hypothesis","verification","reasoning",{"skillNo":298,"name":299,"nameZh":6,"description":300,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":219,"licenseFileUrl":6,"sourceHtmlUrl":301,"categories":302,"keywords":306,"publishedAt":47},"01M6CFVA3RNA0DGFNFDM0NZPW5","research","Research technical solutions, analyze architectures, gather requirements thoroughly. Use for technology evaluation, best practices research, solution design, scalability\u002Fsecurity\u002Fmaintainability analysis.","https:\u002F\u002Fgithub.com\u002Fhoanghd218\u002Fdocons\u002Fblob\u002Fmain\u002Flandingpage-app-render\u002F.opencode\u002Fskills\u002Fresearch\u002FSKILL.md",[303],{"categoryNo":304,"categoryName":305,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000021","资料检索与研究",[299,307,308,36,309,202,310,258,32],"best practices","Evaluation","analyze","technical"]