[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M718XRKB18J7FWKX0J3V0N6K":3,"skill-same:01M718XRKB18J7FWKX0J3V0N6K":66},{"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":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":48,"repositoryHtmlUrl":49,"repositoryHomepageUrl":6,"ownerHtmlUrl":50,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":51,"install":52,"resources":65},"01M718XRKB18J7FWKX0J3V0N6K","test-browser",null,"Run browser tests on pages affected by current PR or branch","wangrenzhu-ola\u002FGaleHarnessCodingCLI","wangrenzhu-ola","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F113888128?v=4","01M718T5C0YYVP4Z7F4SH1MCHM","王韧竹(Bamboo Wang\u002F雪落)","01M718T5CN5T80VWXEWPK25PDQ",2,"MIT","https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Fplugins\u002Fgaleharness-cli\u002Fskills\u002Ftest-browser\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],"browser","test","test browser","branch","pr","pages","tests","number","port","affected","run","name","2026-11-10 10:12:30",false,"---\nname: test-browser\ndescription: Run browser tests on pages affected by current PR or branch\nargument-hint: \"[PR number, branch name, 'current', or --port PORT]\"\n---\n\n# Browser Test Skill\n\nRun end-to-end browser tests on pages affected by a PR or branch changes using the `agent-browser` CLI.\n\n## Use `agent-browser` Only For Browser Automation\n\nThis workflow uses the `agent-browser` CLI exclusively. Do not use any alternative browser automation system, browser MCP integration, or built-in browser-control tool. If the platform offers multiple ways to control a browser, always choose `agent-browser`.\n\nUse `agent-browser` for: opening pages, clicking elements, filling forms, taking screenshots, and scraping rendered content.\n\nPlatform-specific hints:\n- In Claude Code, do not use Chrome MCP tools (`mcp__claude-in-chrome__*`).\n- In Codex, do not substitute unrelated browsing tools.\n\n## Prerequisites\n\n- Local development server running (e.g., `bin\u002Fdev`, `rails server`, `npm run dev`)\n- `agent-browser` CLI installed (see Setup below)\n- Git repository with changes to test\n\n## Setup\n\nCheck whether `agent-browser` is installed:\n\n```bash\ncommand -v agent-browser >\u002Fdev\u002Fnull 2>&1 && echo \"Installed\" || echo \"NOT INSTALLED\"\n```\n\nIf not installed, inform the user: \"`agent-browser` is not installed. Run `\u002Fgh:setup` to install required dependencies.\" Then stop — this skill cannot function without agent-browser.\n\n## Workflow\n\n### 1. Verify Installation\n\nBefore starting, verify `agent-browser` is available:\n\n```bash\ncommand -v agent-browser >\u002Fdev\u002Fnull 2>&1 && echo \"Ready\" || echo \"NOT INSTALLED\"\n```\n\nIf not installed, inform the user: \"`agent-browser` is not installed. Run `\u002Fgh:setup` to install required dependencies.\" Then stop.\n\n### 2. Ask Browser Mode\n\n**Pipeline mode (`mode:pipeline`):** Skip this step entirely. Default to headless — no question, no blocking. Proceed directly to step 3.\n\n**Manual mode:** Ask the user whether to run headed or headless (using the platform's question tool — e.g., `AskUserQuestion` in Claude Code, `request_user_input` in Codex, `ask_user` in Gemini, `ask_user` in Pi (requires the `pi-ask-user` extension) — or present options and wait for a reply):\n\n```\nDo you want to watch the browser tests run?\n\n1. Headed (watch) - Opens visible browser window so you can see tests run\n2. Headless (faster) - Runs in background, faster but invisible\n```\n\nStore the choice and use the `--headed` flag when the user selects option 1.\n\n### 3. Determine Test Scope\n\n**If PR number provided:**\n```bash\ngh pr view [number] --json files -q '.files[].path'\n```\n\n**If 'current' or empty:**\n```bash\ngit diff --name-only main...HEAD\n```\n\n**If branch name provided:**\n```bash\ngit diff --name-only main...[branch]\n```\n\n### 4. Map Files to Routes\n\nMap changed files to testable routes:\n\n| File Pattern | Route(s) |\n|-------------|----------|\n| `app\u002Fviews\u002Fusers\u002F*` | `\u002Fusers`, `\u002Fusers\u002F:id`, `\u002Fusers\u002Fnew` |\n| `app\u002Fcontrollers\u002Fsettings_controller.rb` | `\u002Fsettings` |\n| `app\u002Fjavascript\u002Fcontrollers\u002F*_controller.js` | Pages using that Stimulus controller |\n| `app\u002Fcomponents\u002F*_component.rb` | Pages rendering that component |\n| `app\u002Fviews\u002Flayouts\u002F*` | All pages (test homepage at minimum) |\n| `app\u002Fassets\u002Fstylesheets\u002F*` | Visual regression on key pages |\n| `app\u002Fhelpers\u002F*_helper.rb` | Pages using that helper |\n| `src\u002Fapp\u002F*` (Next.js) | Corresponding routes |\n| `src\u002Fcomponents\u002F*` | Pages using those components |\n\nBuild a list of URLs to test based on the mapping.\n\n### 5. Detect and Claim a Free Port\n\n**Pipeline mode only (`mode:pipeline`):** When invoked from LFG or another automated pipeline, always find a port that is actually free — never assume 3000 is available, as multiple agents may be running in parallel on the same machine.\n\n**Manual mode (no `mode:pipeline`):** Use the preferred port as-is. Do not scan for alternatives — the user controls their own server.\n\nDetermine the preferred port using this priority:\n\n1. **Explicit argument** — if the user passed `--port 5000`, use that directly (skip free-port scan)\n2. **Project instructions** — check `AGENTS.md`, `CLAUDE.md`, or other instruction files for port references\n3. **package.json** — check dev\u002Fstart scripts for `--port` flags\n4. **Environment files** — check `.env`, `.env.local`, `.env.development` for `PORT=`\n5. **Default** — fall back to `3000`\n\n**In pipeline mode**, verify the preferred port is free and scan upward if not. **In manual mode**, use the preferred port directly.\n\n```bash\n# Step 1: Determine preferred port\nPORT=\"${EXPLICIT_PORT:-}\"\nif [ -z \"$PORT\" ]; then\n  PORT=$(grep -Eio '(port\\s*[:=]\\s*|localhost:)([0-9]{4,5})' AGENTS.md 2>\u002Fdev\u002Fnull | grep -Eo '[0-9]{4,5}' | head -1)\nfi\nif [ -z \"$PORT\" ]; then\n  PORT=$(grep -Eio '(port\\s*[:=]\\s*|localhost:)([0-9]{4,5})' CLAUDE.md 2>\u002Fdev\u002Fnull | grep -Eo '[0-9]{4,5}' | head -1)\nfi\nif [ -z \"$PORT\" ]; then\n  PORT=$(grep -Eo '\\-\\-port[= ]+[0-9]{4,5}' package.json 2>\u002Fdev\u002Fnull | grep -Eo '[0-9]{4,5}' | head -1)\nfi\nif [ -z \"$PORT\" ]; then\n  PORT=$(grep -h '^PORT=' .env .env.local .env.development 2>\u002Fdev\u002Fnull | tail -1 | cut -d= -f2)\nfi\nPORT=\"${PORT:-3000}\"\n\n# Step 2 (pipeline mode only): scan for a free port\nif [ \"${PIPELINE_MODE}\" = \"1\" ]; then\n  find_free_port() {\n    local p=$1\n    while lsof -i \":$p\" -sTCP:LISTEN -t >\u002Fdev\u002Fnull 2>&1; do\n      p=$((p + 1))\n    done\n    echo $p\n  }\n  PORT=$(find_free_port \"$PORT\")\nfi\necho \"Using dev server port: $PORT\"\n```\n\nSet `PIPELINE_MODE=1` in your shell when the argument `mode:pipeline` is present.\n\n### 6. Start Dev Server if Not Running, Then Verify\n\n**Pipeline mode only:** If no server is already listening on `$PORT`, start one automatically in the background. In manual mode, inform the user and stop.\n\n```bash\nif lsof -i \":${PORT}\" -sTCP:LISTEN -t >\u002Fdev\u002Fnull 2>&1; then\n  echo \"Server already running on port ${PORT}\"\nelse\n  if [ \"${PIPELINE_MODE}\" = \"1\" ]; then\n    # Auto-start in pipeline — pick the right command for this project\n    echo \"Starting dev server on port ${PORT}...\"\n    if [ -f \"bin\u002Fdev\" ]; then\n      PORT=${PORT} bin\u002Fdev > \u002Ftmp\u002Fdev-server-${PORT}.log 2>&1 &\n    elif [ -f \"bin\u002Frails\" ]; then\n      bin\u002Frails server -p ${PORT} > \u002Ftmp\u002Fdev-server-${PORT}.log 2>&1 &\n    elif [ -f \"package.json\" ]; then\n      PORT=${PORT} npm run dev > \u002Ftmp\u002Fdev-server-${PORT}.log 2>&1 &\n    fi\n    # Wait up to 30 seconds for server to become ready\n    for i in $(seq 1 30); do\n      lsof -i \":${PORT}\" -sTCP:LISTEN -t >\u002Fdev\u002Fnull 2>&1 && break\n      sleep 1\n    done\n    if ! lsof -i \":${PORT}\" -sTCP:LISTEN -t >\u002Fdev\u002Fnull 2>&1; then\n      echo \"Server did not start in 30s. Last output:\"\n      tail -20 \u002Ftmp\u002Fdev-server-${PORT}.log 2>\u002Fdev\u002Fnull\n      exit 1\n    fi\n  else\n    # Manual mode — ask the user to start the server\n    echo \"Server not running on port ${PORT}\"\n    echo \"\"\n    echo \"Please start your development server:\"\n    echo \"  Rails: bin\u002Fdev  or  rails server -p ${PORT}\"\n    echo \"  Node\u002FNext.js: npm run dev\"\n    echo \"  Custom port: run this skill again with --port \u003Cyour-port>\"\n    exit 0\n  fi\nfi\n\nagent-browser open http:\u002F\u002Flocalhost:${PORT}\nagent-browser snapshot -i\n```\n\n### 7. Test Each Affected Page\n\nFor each affected route:\n\n**Navigate and capture snapshot:**\n```bash\nagent-browser open \"http:\u002F\u002Flocalhost:${PORT}\u002F[route]\"\nagent-browser snapshot -i\n```\n\n**For headed mode:**\n```bash\nagent-browser --headed open \"http:\u002F\u002Flocalhost:${PORT}\u002F[route]\"\nagent-browser --headed snapshot -i\n```\n\n**Verify key elements:**\n- Use `agent-browser snapshot -i` to get interactive elements with refs\n- Page title\u002Fheading present\n- Primary content rendered\n- No error messages visible\n- Forms have expected fields\n\n**Test critical interactions:**\n```bash\nagent-browser click @e1\nagent-browser snapshot -i\n```\n\n**Take screenshots:**\n```bash\nagent-browser screenshot page-name.png\nagent-browser screenshot --full page-name-full.png\n```\n\n### 8. Human Verification (When Required)\n\nPause for human input when testing touches flows that require external interaction:\n\n| Flow Type | What to Ask |\n|-----------|-------------|\n| OAuth | \"Please sign in with [provider] and confirm it works\" |\n| Email | \"Check your inbox for the test email and confirm receipt\" |\n| Payments | \"Complete a test purchase in sandbox mode\" |\n| SMS | \"Verify you received the SMS code\" |\n| External APIs | \"Confirm the [service] integration is working\" |\n\nAsk the user (using the platform's question tool, or present numbered options and wait):\n\n```\nHuman Verification Needed\n\nThis test touches [flow type]. Please:\n1. [Action to take]\n2. [What to verify]\n\nDid it work correctly?\n1. Yes - continue testing\n2. No - describe the issue\n```\n\n### 9. Handle Failures\n\nWhen a test fails:\n\n1. **Document the failure:**\n   - Screenshot the error state: `agent-browser screenshot error.png`\n   - Note the exact reproduction steps\n\n2. **Ask the user how to proceed:**\n\n   ```\n   Test Failed: [route]\n\n   Issue: [description]\n   Console errors: [if any]\n\n   How to proceed?\n   1. Fix now - debug and fix the failing test\n   2. Skip - continue testing other pages\n   ```\n\n3. **If \"Fix now\":** investigate, propose a fix, apply, re-run the failing test\n4. **If \"Skip\":** log as skipped, continue\n\n### 10. Test Summary\n\nAfter all tests complete, present a summary:\n\n```markdown\n## Browser Test Results\n\n**Test Scope:** PR #[number] \u002F [branch name]\n**Server:** http:\u002F\u002Flocalhost:${PORT}\n\n### Pages Tested: [count]\n\n| Route | Status | Notes |\n|-------|--------|-------|\n| `\u002Fusers` | Pass | |\n| `\u002Fsettings` | Pass | |\n| `\u002Fdashboard` | Fail | Console error: [msg] |\n| `\u002Fcheckout` | Skip | Requires payment credentials |\n\n### Console Errors: [count]\n- [List any errors found]\n\n### Human Verifications: [count]\n- OAuth flow: Confirmed\n- Email delivery: Confirmed\n\n### Failures: [count]\n- `\u002Fdashboard` - [issue description]\n\n### Result: [PASS \u002F FAIL \u002F PARTIAL]\n```\n\n## Quick Usage Examples\n\n```bash\n# Test current branch changes (auto-detects port)\n\u002Ftest-browser\n\n# Test specific PR\n\u002Ftest-browser 847\n\n# Test specific branch\n\u002Ftest-browser feature\u002Fnew-dashboard\n\n# Test on a specific port\n\u002Ftest-browser --port 5000\n```\n\n## agent-browser CLI Reference\n\nRun `agent-browser --help` for all commands.\n\nKey commands:\n\n```bash\n# Navigation\nagent-browser open \u003Curl>           # Navigate to URL\nagent-browser back                 # Go back\nagent-browser close                # Close browser\n\n# Snapshots (get element refs)\nagent-browser snapshot -i          # Interactive elements with refs (@e1, @e2, etc.)\nagent-browser snapshot -i --json   # JSON output\n\n# Interactions (use refs from snapshot)\nagent-browser click @e1            # Click element\nagent-browser fill @e1 \"text\"      # Fill input\nagent-browser type @e1 \"text\"      # Type without clearing\nagent-browser press Enter          # Press key\n\n# Screenshots\nagent-browser screenshot out.png       # Viewport screenshot\nagent-browser screenshot --full out.png # Full page screenshot\n\n# Headed mode (visible browser)\nagent-browser --headed open \u003Curl>      # Open with visible browser\nagent-browser --headed click @e1       # Click in visible browser\n\n# Wait\nagent-browser wait @e1             # Wait for element\nagent-browser wait 2000            # Wait milliseconds\n```\n","# Browser Test Skill\n\nRun end-to-end browser tests on pages affected by a PR or branch changes using the `agent-browser` CLI.\n\n## Use `agent-browser` Only For Browser Automation\n\nThis workflow uses the `agent-browser` CLI exclusively. Do not use any alternative browser automation system, browser MCP integration, or built-in browser-control tool. If the platform offers multiple ways to control a browser, always choose `agent-browser`.\n\nUse `agent-browser` for: opening pages, clicking elements, filling forms, taking screenshots, and scraping rendered content.\n\nPlatform-specific hints:\n- In Claude Code, do not use Chrome MCP tools (`mcp__claude-in-chrome__*`).\n- In Codex, do not substitute unrelated browsing tools.\n\n## Prerequisites\n\n- Local development server running (e.g., `bin\u002Fdev`, `rails server`, `npm run dev`)\n- `agent-browser` CLI installed (see Setup below)\n- Git repository with changes to test\n\n## Setup\n\nCheck whether `agent-browser` is installed:\n\n```bash\ncommand -v agent-browser >\u002Fdev\u002Fnull 2>&1 && echo \"Installed\" || echo \"NOT INSTALLED\"\n```\n\nIf not installed, inform the user: \"`agent-browser` is not installed. Run `\u002Fgh:setup` to install required dependencies.\" Then stop — this skill cannot function without agent-browser.\n\n## Workflow\n\n### 1. Verify Installation\n\nBefore starting, verify `agent-browser` is available:\n\n```bash\ncommand -v agent-browser >\u002Fdev\u002Fnull 2>&1 && echo \"Ready\" || echo \"NOT INSTALLED\"\n```\n\nIf not installed, inform the user: \"`agent-browser` is not installed. Run `\u002Fgh:setup` to install required dependencies.\" Then stop.\n\n### 2. Ask Browser Mode\n\n**Pipeline mode (`mode:pipeline`):** Skip this step entirely. Default to headless — no question, no blocking. Proceed directly to step 3.\n\n**Manual mode:** Ask the user whether to run headed or headless (using the platform's question tool — e.g., `AskUserQuestion` in Claude Code, `request_user_input` in Codex, `ask_user` in Gemini, `ask_user` in Pi (requires the `pi-ask-user` extension) — or present options and wait for a reply):\n\n```\nDo you want to watch the browser tests run?\n\n1. Headed (watch) - Opens visible browser window so you can see tests run\n2. Headless (faster) - Runs in background, faster but invisible\n```\n\nStore the choice and use the `--headed` flag when the user selects option 1.\n\n### 3. Determine Test Scope\n\n**If PR number provided:**\n```bash\ngh pr view [number] --json files -q '.files[].path'\n```\n\n**If 'current' or empty:**\n```bash\ngit diff --name-only main...HEAD\n```\n\n**If branch name provided:**\n```bash\ngit diff --name-only main...[branch]\n```\n\n### 4. Map Files to Routes\n\nMap changed files to testable routes:\n\n| File Pattern | Route(s) |\n|-------------|----------|\n| `app\u002Fviews\u002Fusers\u002F*` | `\u002Fusers`, `\u002Fusers\u002F:id`, `\u002Fusers\u002Fnew` |\n| `app\u002Fcontrollers\u002Fsettings_controller.rb` | `\u002Fsettings` |\n| `app\u002Fjavascript\u002Fcontrollers\u002F*_controller.js` | Pages using that Stimulus controller |\n| `app\u002Fcomponents\u002F*_component.rb` | Pages rendering that component |\n| `app\u002Fviews\u002Flayouts\u002F*` | All pages (test homepage at minimum) |\n| `app\u002Fassets\u002Fstylesheets\u002F*` | Visual regression on key pages |\n| `app\u002Fhelpers\u002F*_helper.rb` | Pages using that helper |\n| `src\u002Fapp\u002F*` (Next.js) | Corresponding routes |\n| `src\u002Fcomponents\u002F*` | Pages using those components |\n\nBuild a list of URLs to test based on the mapping.\n\n### 5. Detect and Claim a Free Port\n\n**Pipeline mode only (`mode:pipeline`):** When invoked from LFG or another automated pipeline, always find a port that is actually free — never assume 3000 is available, as multiple agents may be running in parallel on the same machine.\n\n**Manual mode (no `mode:pipeline`):** Use the preferred port as-is. Do not scan for alternatives — the user controls their own server.\n\nDetermine the preferred port using this priority:\n\n1. **Explicit argument** — if the user passed `--port 5000`, use that directly (skip free-port scan)\n2. **Project instructions** — check `AGENTS.md`, `CLAUDE.md`, or other instruction files for port references\n3. **package.json** — check dev\u002Fstart scripts for `--port` flags\n4. **Environment files** — check `.env`, `.env.local`, `.env.development` for `PORT=`\n5. **Default** — fall back to `3000`\n\n**In pipeline mode**, verify the preferred port is free and scan upward if not. **In manual mode**, use the preferred port directly.\n\n```bash\n# Step 1: Determine preferred port\nPORT=\"${EXPLICIT_PORT:-}\"\nif [ -z \"$PORT\" ]; then\n  PORT=$(grep -Eio '(port\\s*[:=]\\s*|localhost:)([0-9]{4,5})' AGENTS.md 2>\u002Fdev\u002Fnull | grep -Eo '[0-9]{4,5}' | head -1)\nfi\nif [ -z \"$PORT\" ]; then\n  PORT=$(grep -Eio '(port\\s*[:=]\\s*|localhost:)([0-9]{4,5})' CLAUDE.md 2>\u002Fdev\u002Fnull | grep -Eo '[0-9]{4,5}' | head -1)\nfi\nif [ -z \"$PORT\" ]; then\n  PORT=$(grep -Eo '\\-\\-port[= ]+[0-9]{4,5}' package.json 2>\u002Fdev\u002Fnull | grep -Eo '[0-9]{4,5}' | head -1)\nfi\nif [ -z \"$PORT\" ]; then\n  PORT=$(grep -h '^PORT=' .env .env.local .env.development 2>\u002Fdev\u002Fnull | tail -1 | cut -d= -f2)\nfi\nPORT=\"${PORT:-3000}\"\n\n# Step 2 (pipeline mode only): scan for a free port\nif [ \"${PIPELINE_MODE}\" = \"1\" ]; then\n  find_free_port() {\n    local p=$1\n    while lsof -i \":$p\" -sTCP:LISTEN -t >\u002Fdev\u002Fnull 2>&1; do\n      p=$((p + 1))\n    done\n    echo $p\n  }\n  PORT=$(find_free_port \"$PORT\")\nfi\necho \"Using dev server port: $PORT\"\n```\n\nSet `PIPELINE_MODE=1` in your shell when the argument `mode:pipeline` is present.\n\n### 6. Start Dev Server if Not Running, Then Verify\n\n**Pipeline mode only:** If no server is already listening on `$PORT`, start one automatically in the background. In manual mode, inform the user and stop.\n\n```bash\nif lsof -i \":${PORT}\" -sTCP:LISTEN -t >\u002Fdev\u002Fnull 2>&1; then\n  echo \"Server already running on port ${PORT}\"\nelse\n  if [ \"${PIPELINE_MODE}\" = \"1\" ]; then\n    # Auto-start in pipeline — pick the right command for this project\n    echo \"Starting dev server on port ${PORT}...\"\n    if [ -f \"bin\u002Fdev\" ]; then\n      PORT=${PORT} bin\u002Fdev > \u002Ftmp\u002Fdev-server-${PORT}.log 2>&1 &\n    elif [ -f \"bin\u002Frails\" ]; then\n      bin\u002Frails server -p ${PORT} > \u002Ftmp\u002Fdev-server-${PORT}.log 2>&1 &\n    elif [ -f \"package.json\" ]; then\n      PORT=${PORT} npm run dev > \u002Ftmp\u002Fdev-server-${PORT}.log 2>&1 &\n    fi\n    # Wait up to 30 seconds for server to become ready\n    for i in $(seq 1 30); do\n      lsof -i \":${PORT}\" -sTCP:LISTEN -t >\u002Fdev\u002Fnull 2>&1 && break\n      sleep 1\n    done\n    if ! lsof -i \":${PORT}\" -sTCP:LISTEN -t >\u002Fdev\u002Fnull 2>&1; then\n      echo \"Server did not start in 30s. Last output:\"\n      tail -20 \u002Ftmp\u002Fdev-server-${PORT}.log 2>\u002Fdev\u002Fnull\n      exit 1\n    fi\n  else\n    # Manual mode — ask the user to start the server\n    echo \"Server not running on port ${PORT}\"\n    echo \"\"\n    echo \"Please start your development server:\"\n    echo \"  Rails: bin\u002Fdev  or  rails server -p ${PORT}\"\n    echo \"  Node\u002FNext.js: npm run dev\"\n    echo \"  Custom port: run this skill again with --port \u003Cyour-port>\"\n    exit 0\n  fi\nfi\n\nagent-browser open http:\u002F\u002Flocalhost:${PORT}\nagent-browser snapshot -i\n```\n\n### 7. Test Each Affected Page\n\nFor each affected route:\n\n**Navigate and capture snapshot:**\n```bash\nagent-browser open \"http:\u002F\u002Flocalhost:${PORT}\u002F[route]\"\nagent-browser snapshot -i\n```\n\n**For headed mode:**\n```bash\nagent-browser --headed open \"http:\u002F\u002Flocalhost:${PORT}\u002F[route]\"\nagent-browser --headed snapshot -i\n```\n\n**Verify key elements:**\n- Use `agent-browser snapshot -i` to get interactive elements with refs\n- Page title\u002Fheading present\n- Primary content rendered\n- No error messages visible\n- Forms have expected fields\n\n**Test critical interactions:**\n```bash\nagent-browser click @e1\nagent-browser snapshot -i\n```\n\n**Take screenshots:**\n```bash\nagent-browser screenshot page-name.png\nagent-browser screenshot --full page-name-full.png\n```\n\n### 8. Human Verification (When Required)\n\nPause for human input when testing touches flows that require external interaction:\n\n| Flow Type | What to Ask |\n|-----------|-------------|\n| OAuth | \"Please sign in with [provider] and confirm it works\" |\n| Email | \"Check your inbox for the test email and confirm receipt\" |\n| Payments | \"Complete a test purchase in sandbox mode\" |\n| SMS | \"Verify you received the SMS code\" |\n| External APIs | \"Confirm the [service] integration is working\" |\n\nAsk the user (using the platform's question tool, or present numbered options and wait):\n\n```\nHuman Verification Needed\n\nThis test touches [flow type]. Please:\n1. [Action to take]\n2. [What to verify]\n\nDid it work correctly?\n1. Yes - continue testing\n2. No - describe the issue\n```\n\n### 9. Handle Failures\n\nWhen a test fails:\n\n1. **Document the failure:**\n   - Screenshot the error state: `agent-browser screenshot error.png`\n   - Note the exact reproduction steps\n\n2. **Ask the user how to proceed:**\n\n   ```\n   Test Failed: [route]\n\n   Issue: [description]\n   Console errors: [if any]\n\n   How to proceed?\n   1. Fix now - debug and fix the failing test\n   2. Skip - continue testing other pages\n   ```\n\n3. **If \"Fix now\":** investigate, propose a fix, apply, re-run the failing test\n4. **If \"Skip\":** log as skipped, continue\n\n### 10. Test Summary\n\nAfter all tests complete, present a summary:\n\n```markdown\n## Browser Test Results\n\n**Test Scope:** PR #[number] \u002F [branch name]\n**Server:** http:\u002F\u002Flocalhost:${PORT}\n\n### Pages Tested: [count]\n\n| Route | Status | Notes |\n|-------|--------|-------|\n| `\u002Fusers` | Pass | |\n| `\u002Fsettings` | Pass | |\n| `\u002Fdashboard` | Fail | Console error: [msg] |\n| `\u002Fcheckout` | Skip | Requires payment credentials |\n\n### Console Errors: [count]\n- [List any errors found]\n\n### Human Verifications: [count]\n- OAuth flow: Confirmed\n- Email delivery: Confirmed\n\n### Failures: [count]\n- `\u002Fdashboard` - [issue description]\n\n### Result: [PASS \u002F FAIL \u002F PARTIAL]\n```\n\n## Quick Usage Examples\n\n```bash\n# Test current branch changes (auto-detects port)\n\u002Ftest-browser\n\n# Test specific PR\n\u002Ftest-browser 847\n\n# Test specific branch\n\u002Ftest-browser feature\u002Fnew-dashboard\n\n# Test on a specific port\n\u002Ftest-browser --port 5000\n```\n\n## agent-browser CLI Reference\n\nRun `agent-browser --help` for all commands.\n\nKey commands:\n\n```bash\n# Navigation\nagent-browser open \u003Curl>           # Navigate to URL\nagent-browser back                 # Go back\nagent-browser close                # Close browser\n\n# Snapshots (get element refs)\nagent-browser snapshot -i          # Interactive elements with refs (@e1, @e2, etc.)\nagent-browser snapshot -i --json   # JSON output\n\n# Interactions (use refs from snapshot)\nagent-browser click @e1            # Click element\nagent-browser fill @e1 \"text\"      # Fill input\nagent-browser type @e1 \"text\"      # Type without clearing\nagent-browser press Enter          # Press key\n\n# Screenshots\nagent-browser screenshot out.png       # Viewport screenshot\nagent-browser screenshot --full out.png # Full page screenshot\n\n# Headed mode (visible browser)\nagent-browser --headed open \u003Curl>      # Open with visible browser\nagent-browser --headed click @e1       # Click in visible browser\n\n# Wait\nagent-browser wait @e1             # Wait for element\nagent-browser wait 2000            # Wait milliseconds\n```\n",{"name":5,"description":7,"argument-hint":44},"[PR number, branch name, 'current', or --port PORT]","main","adde77e5116dc3a65ca3385f7d19d086cd10a74c","plugins\u002Fgaleharness-cli\u002Fskills\u002Ftest-browser",1,"https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola\u002FGaleHarnessCodingCLI","https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola","2026-06-13 09:21:37",{"source":8,"skillName":5,"commands":53,"prompt":63,"zipAvailable":64},[54,57,60],{"tool":55,"command":56},"npx","npx skills add wangrenzhu-ola\u002FGaleHarnessCodingCLI --skill test-browser",{"tool":58,"command":59},"bunx","bunx skills add wangrenzhu-ola\u002FGaleHarnessCodingCLI --skill test-browser",{"tool":61,"command":62},"pnpm","pnpm dlx skills add wangrenzhu-ola\u002FGaleHarnessCodingCLI --skill test-browser","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Fplugins\u002Fgaleharness-cli\u002Fskills\u002Ftest-browser\u002FSKILL.md",true,[],[67,78,91,103,111,119],{"skillNo":68,"name":69,"nameZh":6,"description":70,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":74,"publishedAt":39},"01M718XZ8QAQPM8BS5K9M2YQTJ","skill-one","Sample skill","https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fsample-plugin\u002Fskills\u002Fskill-one\u002FSKILL.md",[73],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[75,76,77],"skill one","sample skill","sample",{"skillNo":79,"name":80,"nameZh":6,"description":81,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":85,"publishedAt":39},"01M718XYEEENP5G592XVQ6MGVR","disabled-skill","A skill with model invocation disabled","https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fsample-plugin\u002Fskills\u002Fdisabled-skill\u002FSKILL.md",[84],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[86,87,88,89,90],"disabled skill","with","with model","true","model",{"skillNo":92,"name":93,"nameZh":6,"description":94,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":98,"publishedAt":39},"01M718XXNH8T61H0EJE0BHE593","claude-only-skill","A skill restricted to Claude Code only","https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fsample-plugin\u002Fskills\u002Fclaude-only-skill\u002FSKILL.md",[97],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[99,100,101,102],"only","claude only skill","claude only","code",{"skillNo":104,"name":105,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":108,"publishedAt":39},"01M718XWMPEPBWHC05JNGKSEF0","default-skill","https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fcustom-paths\u002Fskills\u002Fdefault-skill\u002FSKILL.md",[],[109,110],"default skill","default",{"skillNo":112,"name":113,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":39},"01M718XVZXW8CXYBNQZPJPNB6B","custom-skill","https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fcustom-paths\u002Fcustom-skills\u002Fcustom-skill\u002FSKILL.md",[],[117,118],"custom","custom skill",{"skillNo":120,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":126,"publishedAt":39},"01M718XT6P96FVR69X0EEKK2N6","test-xcode","Build and test iOS apps on simulator using XcodeBuildMCP. Use after making iOS code changes, before creating a PR, or when verifying app behavior and checking for crashes on simulator.","https:\u002F\u002Fgithub.com\u002Fwangrenzhu-ola\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Fplugins\u002Fgaleharness-cli\u002Fskills\u002Ftest-xcode\u002FSKILL.md",[125],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[28,127,128,129,130,131,31,132,110,89,133,134,135,136,102,137,138,139,38,140],"xcode","test xcode","apps","app","build and test","for","xcodebuildmcp","use","scheme","when","changes","build","ios","behavior"]