playwright-skill

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
IMPORTANT - Path Resolution: This skill can be installed in different locations (plugin system, manual installation, global, or project-specific). Before executing any commands, determine the skill directory based on where you loaded this SKILL.md file, and use that path in all commands below. Replace
$SKILL_DIR
with the actual discovered path.
Common installation paths:
  • Plugin system:
    ~/.claude/plugins/marketplaces/playwright-skill/skills/playwright-skill
  • Manual global:
    ~/.claude/skills/playwright-skill
  • Project-specific:
    <project>/.claude/skills/playwright-skill
重要提示 - 路径解析: 此技能可安装在不同位置(插件系统、手动安装、全局安装或项目级安装)。在执行任何命令之前,请根据加载此SKILL.md文件的位置确定技能目录,并在以下所有命令中使用该路径。将
$SKILL_DIR
替换为实际找到的路径。
常见安装路径:
  • 插件系统:
    ~/.claude/plugins/marketplaces/playwright-skill/skills/playwright-skill
  • 手动全局安装:
    ~/.claude/skills/playwright-skill
  • 项目级安装:
    <project>/.claude/skills/playwright-skill

Playwright Browser Automation

Playwright浏览器自动化

General-purpose browser automation skill. I'll write custom Playwright code for any automation task you request and execute it via the universal executor.
CRITICAL WORKFLOW - Follow these steps in order:
  1. Auto-detect dev servers - For localhost testing, ALWAYS run server detection FIRST:
    bash
    cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"
    • If 1 server found: Use it automatically, inform user
    • If multiple servers found: Ask user which one to test
    • If no servers found: Ask for URL or offer to help start dev server
  2. Write scripts to /tmp - NEVER write test files to skill directory; always use
    /tmp/playwright-test-*.js
  3. Use visible browser by default - Always use
    headless: false
    unless user specifically requests headless mode
  4. Parameterize URLs - Always make URLs configurable via environment variable or constant at top of script
通用型浏览器自动化技能。我会根据你的需求编写自定义Playwright代码,并通过通用执行器运行。
关键工作流程 - 请按以下顺序执行步骤:
  1. 自动检测开发服务器 - 对于本地主机测试,务必首先运行服务器检测:
    bash
    cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"
    • 如果找到1个服务器:自动使用该服务器,并告知用户
    • 如果找到多个服务器:询问用户要测试哪一个
    • 如果未找到服务器:询问用户提供URL,或协助启动开发服务器
  2. 将脚本写入/tmp目录 - 切勿将测试文件写入技能目录;始终使用
    /tmp/playwright-test-*.js
    路径
  3. 默认使用可见浏览器 - 除非用户明确请求无头模式,否则始终使用
    headless: false
  4. 参数化URL - 始终通过环境变量或脚本顶部的常量配置URL

How It Works

工作原理

  1. You describe what you want to test/automate
  2. I auto-detect running dev servers (or ask for URL if testing external site)
  3. I write custom Playwright code in
    /tmp/playwright-test-*.js
    (won't clutter your project)
  4. I execute it via:
    cd $SKILL_DIR && node run.js /tmp/playwright-test-*.js
  5. Results displayed in real-time, browser window visible for debugging
  6. Test files auto-cleaned from /tmp by your OS
  1. 你描述想要测试/自动化的任务
  2. 我自动检测运行中的开发服务器(如果测试外部网站则询问URL)
  3. 我将自定义Playwright代码写入
    /tmp/playwright-test-*.js
    (不会占用你的项目空间)
  4. 通过以下命令执行:
    cd $SKILL_DIR && node run.js /tmp/playwright-test-*.js
  5. 实时显示结果,浏览器窗口可见以便调试
  6. 测试文件会由操作系统自动从/tmp目录清理

Setup (First Time)

首次设置

bash
cd $SKILL_DIR
npm run setup
This installs Playwright and Chromium browser. Only needed once.
bash
cd $SKILL_DIR
npm run setup
此命令会安装Playwright和Chromium浏览器。仅需执行一次。

Execution Pattern

执行流程

Step 1: Detect dev servers (for localhost testing)
bash
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"
Step 2: Write test script to /tmp with URL parameter
javascript
// /tmp/playwright-test-page.js
const { chromium } = require('playwright');

// Parameterized URL (detected or user-provided)
const TARGET_URL = 'http://localhost:3001'; // <-- Auto-detected or from user

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(TARGET_URL);
  console.log('Page loaded:', await page.title());

  await page.screenshot({ path: '/tmp/screenshot.png', fullPage: true });
  console.log('📸 Screenshot saved to /tmp/screenshot.png');

  await browser.close();
})();
Step 3: Execute from skill directory
bash
cd $SKILL_DIR && node run.js /tmp/playwright-test-page.js
步骤1:检测开发服务器(适用于本地主机测试)
bash
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"
步骤2:将带URL参数的测试脚本写入/tmp目录
javascript
// /tmp/playwright-test-page.js
const { chromium } = require('playwright');

// 参数化URL(自动检测或用户提供)
const TARGET_URL = 'http://localhost:3001'; // <-- 自动检测或用户提供

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(TARGET_URL);
  console.log('页面已加载:', await page.title());

  await page.screenshot({ path: '/tmp/screenshot.png', fullPage: true });
  console.log('📸 截图已保存至/tmp/screenshot.png');

  await browser.close();
})();
步骤3:从技能目录执行
bash
cd $SKILL_DIR && node run.js /tmp/playwright-test-page.js

Common Patterns

常见场景

Test a Page (Multiple Viewports)

测试页面(多视口)

javascript
// /tmp/playwright-test-responsive.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 100 });
  const page = await browser.newPage();

  // Desktop test
  await page.setViewportSize({ width: 1920, height: 1080 });
  await page.goto(TARGET_URL);
  console.log('Desktop - Title:', await page.title());
  await page.screenshot({ path: '/tmp/desktop.png', fullPage: true });

  // Mobile test
  await page.setViewportSize({ width: 375, height: 667 });
  await page.screenshot({ path: '/tmp/mobile.png', fullPage: true });

  await browser.close();
})();
javascript
// /tmp/playwright-test-responsive.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // 自动检测

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 100 });
  const page = await browser.newPage();

  // 桌面端测试
  await page.setViewportSize({ width: 1920, height: 1080 });
  await page.goto(TARGET_URL);
  console.log('桌面端 - 标题:', await page.title());
  await page.screenshot({ path: '/tmp/desktop.png', fullPage: true });

  // 移动端测试
  await page.setViewportSize({ width: 375, height: 667 });
  await page.screenshot({ path: '/tmp/mobile.png', fullPage: true });

  await browser.close();
})();

Test Login Flow

测试登录流程

javascript
// /tmp/playwright-test-login.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/login`);

  await page.fill('input[name="email"]', 'test@example.com');
  await page.fill('input[name="password"]', 'password123');
  await page.click('button[type="submit"]');

  // Wait for redirect
  await page.waitForURL('**/dashboard');
  console.log('✅ Login successful, redirected to dashboard');

  await browser.close();
})();
javascript
// /tmp/playwright-test-login.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // 自动检测

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/login`);

  await page.fill('input[name="email"]', 'test@example.com');
  await page.fill('input[name="password"]', 'password123');
  await page.click('button[type="submit"]');

  // 等待重定向
  await page.waitForURL('**/dashboard');
  console.log('✅ 登录成功,已重定向至仪表盘');

  await browser.close();
})();

Fill and Submit Form

填写并提交表单

javascript
// /tmp/playwright-test-form.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 50 });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/contact`);

  await page.fill('input[name="name"]', 'John Doe');
  await page.fill('input[name="email"]', 'john@example.com');
  await page.fill('textarea[name="message"]', 'Test message');
  await page.click('button[type="submit"]');

  // Verify submission
  await page.waitForSelector('.success-message');
  console.log('✅ Form submitted successfully');

  await browser.close();
})();
javascript
// /tmp/playwright-test-form.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // 自动检测

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 50 });
  const page = await browser.newPage();

  await page.goto(`${TARGET_URL}/contact`);

  await page.fill('input[name="name"]', 'John Doe');
  await page.fill('input[name="email"]', 'john@example.com');
  await page.fill('textarea[name="message"]', '测试消息');
  await page.click('button[type="submit"]');

  // 验证提交结果
  await page.waitForSelector('.success-message');
  console.log('✅ 表单提交成功');

  await browser.close();
})();

Check for Broken Links

检查失效链接

javascript
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto('http://localhost:3000');

  const links = await page.locator('a[href^="http"]').all();
  const results = { working: 0, broken: [] };

  for (const link of links) {
    const href = await link.getAttribute('href');
    try {
      const response = await page.request.head(href);
      if (response.ok()) {
        results.working++;
      } else {
        results.broken.push({ url: href, status: response.status() });
      }
    } catch (e) {
      results.broken.push({ url: href, error: e.message });
    }
  }

  console.log(`✅ Working links: ${results.working}`);
  console.log(`❌ Broken links:`, results.broken);

  await browser.close();
})();
javascript
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto('http://localhost:3000');

  const links = await page.locator('a[href^="http"]').all();
  const results = { working: 0, broken: [] };

  for (const link of links) {
    const href = await link.getAttribute('href');
    try {
      const response = await page.request.head(href);
      if (response.ok()) {
        results.working++;
      } else {
        results.broken.push({ url: href, status: response.status() });
      }
    } catch (e) {
      results.broken.push({ url: href, error: e.message });
    }
  }

  console.log(`✅ 可用链接:${results.working}`);
  console.log(`❌ 失效链接:`, results.broken);

  await browser.close();
})();

Take Screenshot with Error Handling

带错误处理的截图

javascript
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  try {
    await page.goto('http://localhost:3000', {
      waitUntil: 'networkidle',
      timeout: 10000,
    });

    await page.screenshot({
      path: '/tmp/screenshot.png',
      fullPage: true,
    });

    console.log('📸 Screenshot saved to /tmp/screenshot.png');
  } catch (error) {
    console.error('❌ Error:', error.message);
  } finally {
    await browser.close();
  }
})();
javascript
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  try {
    await page.goto('http://localhost:3000', {
      waitUntil: 'networkidle',
      timeout: 10000,
    });

    await page.screenshot({
      path: '/tmp/screenshot.png',
      fullPage: true,
    });

    console.log('📸 截图已保存至/tmp/screenshot.png');
  } catch (error) {
    console.error('❌ 错误:', error.message);
  } finally {
    await browser.close();
  }
})();

Test Responsive Design

测试响应式设计

javascript
// /tmp/playwright-test-responsive-full.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // Auto-detected

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  const viewports = [
    { name: 'Desktop', width: 1920, height: 1080 },
    { name: 'Tablet', width: 768, height: 1024 },
    { name: 'Mobile', width: 375, height: 667 },
  ];

  for (const viewport of viewports) {
    console.log(
      `Testing ${viewport.name} (${viewport.width}x${viewport.height})`,
    );

    await page.setViewportSize({
      width: viewport.width,
      height: viewport.height,
    });

    await page.goto(TARGET_URL);
    await page.waitForTimeout(1000);

    await page.screenshot({
      path: `/tmp/${viewport.name.toLowerCase()}.png`,
      fullPage: true,
    });
  }

  console.log('✅ All viewports tested');
  await browser.close();
})();
javascript
// /tmp/playwright-test-responsive-full.js
const { chromium } = require('playwright');

const TARGET_URL = 'http://localhost:3001'; // 自动检测

(async () => {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  const viewports = [
    { name: 'Desktop', width: 1920, height: 1080 },
    { name: 'Tablet', width: 768, height: 1024 },
    { name: 'Mobile', width: 375, height: 667 },
  ];

  for (const viewport of viewports) {
    console.log(
      `正在测试${viewport.name}${viewport.width}x${viewport.height}`,
    );

    await page.setViewportSize({
      width: viewport.width,
      height: viewport.height,
    });

    await page.goto(TARGET_URL);
    await page.waitForTimeout(1000);

    await page.screenshot({
      path: `/tmp/${viewport.name.toLowerCase()}.png`,
      fullPage: true,
    });
  }

  console.log('✅ 所有视口测试完成');
  await browser.close();
})();

Inline Execution (Simple Tasks)

内联执行(简单任务)

For quick one-off tasks, you can execute code inline without creating files:
bash
undefined
对于快速一次性任务,你可以直接内联执行代码而无需创建文件:
bash
undefined

Take a quick screenshot

快速截图

cd $SKILL_DIR && node run.js " const browser = await chromium.launch({ headless: false }); const page = await browser.newPage(); await page.goto('http://localhost:3001'); await page.screenshot({ path: '/tmp/quick-screenshot.png', fullPage: true }); console.log('Screenshot saved'); await browser.close(); "

**When to use inline vs files:**

- **Inline**: Quick one-off tasks (screenshot, check if element exists, get page title)
- **Files**: Complex tests, responsive design checks, anything user might want to re-run
cd $SKILL_DIR && node run.js " const browser = await chromium.launch({ headless: false }); const page = await browser.newPage(); await page.goto('http://localhost:3001'); await page.screenshot({ path: '/tmp/quick-screenshot.png', fullPage: true }); console.log('截图已保存'); await browser.close(); "

**内联执行与文件执行的适用场景:**

- **内联执行**:快速一次性任务(截图、检查元素是否存在、获取页面标题)
- **文件执行**:复杂测试、响应式设计检查、用户可能需要重新运行的任务

Available Helpers

可用辅助函数

Optional utility functions in
lib/helpers.js
:
javascript
const helpers = require('./lib/helpers');

// Detect running dev servers (CRITICAL - use this first!)
const servers = await helpers.detectDevServers();
console.log('Found servers:', servers);

// Safe click with retry
await helpers.safeClick(page, 'button.submit', { retries: 3 });

// Safe type with clear
await helpers.safeType(page, '#username', 'testuser');

// Take timestamped screenshot
await helpers.takeScreenshot(page, 'test-result');

// Handle cookie banners
await helpers.handleCookieBanner(page);

// Extract table data
const data = await helpers.extractTableData(page, 'table.results');
See
lib/helpers.js
for full list.
lib/helpers.js
中的可选工具函数:
javascript
const helpers = require('./lib/helpers');

// 检测运行中的开发服务器(关键 - 请首先使用!)
const servers = await helpers.detectDevServers();
console.log('找到的服务器:', servers);

// 带重试的安全点击
await helpers.safeClick(page, 'button.submit', { retries: 3 });

// 带清空的安全输入
await helpers.safeType(page, '#username', 'testuser');

// 带时间戳的截图
await helpers.takeScreenshot(page, 'test-result');

// 处理Cookie横幅
await helpers.handleCookieBanner(page);

// 提取表格数据
const data = await helpers.extractTableData(page, 'table.results');
完整列表请查看
lib/helpers.js

Custom HTTP Headers

自定义HTTP头

Configure custom headers for all HTTP requests via environment variables. Useful for:
  • Identifying automated traffic to your backend
  • Getting LLM-optimized responses (e.g., plain text errors instead of styled HTML)
  • Adding authentication tokens globally
可通过环境变量为所有HTTP请求配置自定义头。适用于:
  • 向后端标识自动化流量
  • 获取LLM优化的响应(例如,纯文本错误而非样式化HTML)
  • 全局添加认证令牌

Configuration

配置方式

Single header (common case):
bash
PW_HEADER_NAME=X-Automated-By PW_HEADER_VALUE=playwright-skill \
  cd $SKILL_DIR && node run.js /tmp/my-script.js
Multiple headers (JSON format):
bash
PW_EXTRA_HEADERS='{"X-Automated-By":"playwright-skill","X-Debug":"true"}' \
  cd $SKILL_DIR && node run.js /tmp/my-script.js
单个头(常见场景):
bash
PW_HEADER_NAME=X-Automated-By PW_HEADER_VALUE=playwright-skill \
  cd $SKILL_DIR && node run.js /tmp/my-script.js
多个头(JSON格式):
bash
PW_EXTRA_HEADERS='{"X-Automated-By":"playwright-skill","X-Debug":"true"}' \
  cd $SKILL_DIR && node run.js /tmp/my-script.js

How It Works

工作原理

Headers are automatically applied when using
helpers.createContext()
:
javascript
const context = await helpers.createContext(browser);
const page = await context.newPage();
// All requests from this page include your custom headers
For scripts using raw Playwright API, use the injected
getContextOptionsWithHeaders()
:
javascript
const context = await browser.newContext(
  getContextOptionsWithHeaders({ viewport: { width: 1920, height: 1080 } }),
);
当使用
helpers.createContext()
时,头信息会自动应用:
javascript
const context = await helpers.createContext(browser);
const page = await context.newPage();
// 此页面的所有请求都会包含你的自定义头
对于使用原生Playwright API的脚本,使用注入的
getContextOptionsWithHeaders()
javascript
const context = await browser.newContext(
  getContextOptionsWithHeaders({ viewport: { width: 1920, height: 1080 } }),
);

Advanced Usage

高级用法

For comprehensive Playwright API documentation, see API_REFERENCE.md:
  • Selectors & Locators best practices
  • Network interception & API mocking
  • Authentication & session management
  • Visual regression testing
  • Mobile device emulation
  • Performance testing
  • Debugging techniques
  • CI/CD integration
如需完整的Playwright API文档,请查看API_REFERENCE.md
  • 选择器与定位器最佳实践
  • 网络拦截与API模拟
  • 认证与会话管理
  • 视觉回归测试
  • 移动设备模拟
  • 性能测试
  • 调试技巧
  • CI/CD集成

Tips

提示

  • CRITICAL: Detect servers FIRST - Always run
    detectDevServers()
    before writing test code for localhost testing
  • Custom headers - Use
    PW_HEADER_NAME
    /
    PW_HEADER_VALUE
    env vars to identify automated traffic to your backend
  • Use /tmp for test files - Write to
    /tmp/playwright-test-*.js
    , never to skill directory or user's project
  • Parameterize URLs - Put detected/provided URL in a
    TARGET_URL
    constant at the top of every script
  • DEFAULT: Visible browser - Always use
    headless: false
    unless user explicitly asks for headless mode
  • Headless mode - Only use
    headless: true
    when user specifically requests "headless" or "background" execution
  • Slow down: Use
    slowMo: 100
    to make actions visible and easier to follow
  • Wait strategies: Use
    waitForURL
    ,
    waitForSelector
    ,
    waitForLoadState
    instead of fixed timeouts
  • Error handling: Always use try-catch for robust automation
  • Console output: Use
    console.log()
    to track progress and show what's happening
  • 关键提示:先检测服务器 - 对于本地主机测试,务必在编写测试代码前运行
    detectDevServers()
  • 自定义头 - 使用
    PW_HEADER_NAME
    /
    PW_HEADER_VALUE
    环境变量向后端标识自动化流量
  • 使用/tmp目录存储测试文件 - 将文件写入
    /tmp/playwright-test-*.js
    ,切勿写入技能目录或用户的项目
  • 参数化URL - 将检测到的/用户提供的URL放在每个脚本顶部的
    TARGET_URL
    常量中
  • 默认使用可见浏览器 - 除非用户明确要求,否则始终使用
    headless: false
  • 无头模式 - 仅当用户明确请求“无头”或“后台”执行时才使用
    headless: true
  • 放慢速度:使用
    slowMo: 100
    使操作可见且易于跟踪
  • 等待策略:使用
    waitForURL
    waitForSelector
    waitForLoadState
    而非固定超时
  • 错误处理:始终使用try-catch实现健壮的自动化
  • 控制台输出:使用
    console.log()
    跟踪进度并显示当前操作

Troubleshooting

故障排除

Playwright not installed:
bash
cd $SKILL_DIR && npm run setup
Module not found: Ensure running from skill directory via
run.js
wrapper
Browser doesn't open: Check
headless: false
and ensure display available
Element not found: Add wait:
await page.waitForSelector('.element', { timeout: 10000 })
Playwright未安装:
bash
cd $SKILL_DIR && npm run setup
模块未找到: 确保通过
run.js
包装器从技能目录运行
浏览器无法打开: 检查是否设置了
headless: false
,并确保有可用的显示设备
元素未找到: 添加等待:
await page.waitForSelector('.element', { timeout: 10000 })

Example Usage

使用示例

User: "Test if the marketing page looks good"

Claude: I'll test the marketing page across multiple viewports. Let me first detect running servers...
[Runs: detectDevServers()]
[Output: Found server on port 3001]
I found your dev server running on http://localhost:3001

[Writes custom automation script to /tmp/playwright-test-marketing.js with URL parameterized]
[Runs: cd $SKILL_DIR && node run.js /tmp/playwright-test-marketing.js]
[Shows results with screenshots from /tmp/]
User: "Check if login redirects correctly"

Claude: I'll test the login flow. First, let me check for running servers...
[Runs: detectDevServers()]
[Output: Found servers on ports 3000 and 3001]
I found 2 dev servers. Which one should I test?
- http://localhost:3000
- http://localhost:3001

User: "Use 3001"

[Writes login automation to /tmp/playwright-test-login.js]
[Runs: cd $SKILL_DIR && node run.js /tmp/playwright-test-login.js]
[Reports: ✅ Login successful, redirected to /dashboard]
用户:"测试营销页面的显示效果"

Claude:我会在多个视口下测试营销页面。首先让我检测运行中的服务器...
[执行:detectDevServers()]
[输出:在端口3001找到服务器]
我找到你的开发服务器运行在http://localhost:3001

[将自定义自动化脚本写入带URL参数的/tmp/playwright-test-marketing.js]
[执行:cd $SKILL_DIR && node run.js /tmp/playwright-test-marketing.js]
[显示/tmp目录中的截图结果]
用户:"检查登录是否正确重定向"

Claude:我会测试登录流程。首先让我检查运行中的服务器...
[执行:detectDevServers()]
[输出:在端口3000和3001找到服务器]
我找到了2个开发服务器。你要测试哪一个?
- http://localhost:3000
- http://localhost:3001

用户:"使用3001"

[将登录自动化脚本写入/tmp/playwright-test-login.js]
[执行:cd $SKILL_DIR && node run.js /tmp/playwright-test-login.js]
[报告:✅ 登录成功,已重定向至/dashboard]

Notes

注意事项

  • Each automation is custom-written for your specific request
  • Not limited to pre-built scripts - any browser task possible
  • Auto-detects running dev servers to eliminate hardcoded URLs
  • Test scripts written to
    /tmp
    for automatic cleanup (no clutter)
  • Code executes reliably with proper module resolution via
    run.js
  • Progressive disclosure - API_REFERENCE.md loaded only when advanced features needed
  • 每个自动化脚本都是根据你的具体请求自定义编写的
  • 不限于预构建脚本 - 任何浏览器任务都可实现
  • 自动检测运行中的开发服务器,无需硬编码URL
  • 测试脚本写入/tmp目录以自动清理(无冗余文件)
  • 通过
    run.js
    确保代码可靠执行,解决模块解析问题
  • 渐进式披露 - 仅在需要高级功能时加载API_REFERENCE.md