
Playwright
Automate real-browser flows—navigation, forms, and assertions—with Playwright scripts your agent writes and runs locally.
Overview
Playwright is an agent skill most often used in Ship (also Validate, Operate) that teaches agents to write and run browser automation with @playwright/test patterns.
Install
npx skills add https://github.com/secondsky/claude-skills --skill playwrightWhat is this skill?
- Pins @playwright/test and playwright (~1.55–1.57) with a ready skill workspace
- Runnable patterns: launch Chromium, goto routes, fill inputs, submit forms
- Supports headed runs with slowMo for debugging flaky UI during solo development
- CLI-driven workflows agents can extend for contact pages, auth, and multi-step flows
- Node-based scripts suitable for CI hooks or one-off local repro commands
- @playwright/test ^1.55.0 workspace dependency
Adoption & trust: 593 installs on skills.sh; 165 GitHub stars; 1/3 security scanners passed (skills.sh audits).
What problem does it solve?
You cannot reliably verify multi-step UI flows with unit tests alone and keep re-clicking the same paths manually.
Who is it for?
Indie devs shipping web apps who want agent-generated E2E scripts against localhost or staging.
Skip if: Teams that only need API contract tests with no browser surface, or environments where installing browsers is blocked.
When should I use this skill?
You need browser-based verification, form flows, or UI repro scripts with Playwright in Node.
What do I get? / Deliverables
You get working Playwright scripts that navigate, interact, and assert against your app in a real browser session.
- Playwright script snippets
- Runnable local browser test command
- Selector-based interaction steps
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Browser verification is canonical in Ship when you need confidence before launch, even though you may also run checks during Build. Testing subphase covers E2E and UI regression; Playwright is the primary tool facet for that work.
Where it fits
Click through a landing prototype to confirm CTA and form wiring before full build.
Run a contact-form submit script against staging before tagging a release.
Reproduce a checkout bug in headed mode with slowMo while capturing selectors.
How it compares
Skill-wrapped Playwright recipes—not a replacement for your full CI matrix unless you wire scripts into pipelines yourself.
Common Questions / FAQ
Who is playwright for?
Solo builders using Claude Code, Cursor, or Codex who need quick browser automation for forms, flows, and smoke checks on web apps.
When should I use playwright?
In Ship for pre-release E2E checks, in Validate for prototype click-throughs, and in Operate when reproducing a user-reported UI bug in a headed browser.
Is playwright safe to install?
Check the Security Audits panel on this page; running the skill executes local Node scripts and launches browsers against URLs you choose.
SKILL.md
READMESKILL.md - Playwright
{ "lockfileVersion": 1, "configVersion": 1, "workspaces": { "": { "name": "playwright-skill", "dependencies": { "@playwright/test": "^1.55.0", "playwright": "^1.55.0", }, }, }, "packages": { "@playwright/test": ["@playwright/test@1.57.0", "", { "dependencies": { "playwright": "1.57.0" }, "bin": { "playwright": "cli.js" } }, "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA=="], "fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], "playwright": ["playwright@1.57.0", "", { "dependencies": { "playwright-core": "1.57.0" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw=="], "playwright-core": ["playwright-core@1.57.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ=="], } } // Example: Fill and submit a form const { chromium } = require('playwright'); const TARGET_URL = 'http://localhost:3000'; // Change as needed (async () => { const browser = await chromium.launch({ headless: false, slowMo: 50 }); const page = await browser.newPage(); await page.goto(`${TARGET_URL}/contact`); // Fill form fields await page.fill('input[name="name"]', 'John Doe'); await page.fill('input[name="email"]', 'john@example.com'); await page.fill('textarea[name="message"]', 'This is a test message'); // Submit form await page.click('button[type="submit"]'); // Verify submission try { await page.waitForSelector('.success-message', { timeout: 5000 }); console.log('✅ Form submitted successfully'); } catch (e) { console.log('❌ Form submission failed or success message not found'); } await browser.close(); })(); // Example: Check for broken links on a page const { chromium } = require('playwright'); const TARGET_URL = 'http://localhost:3000'; // Change as needed (async () => { const browser = await chromium.launch({ headless: false }); const page = await browser.newPage(); console.log(`Checking links on: ${TARGET_URL}\n`); await page.goto(TARGET_URL); // Get all links, then filter to http(s) only // Note: This excludes relative links (/about), mailto:, tel:, and #anchors const allLinks = await page.locator('a[href]').all(); const httpLinks = []; for (const link of allLinks) { const href = await link.getAttribute('href'); // Filter to only http(s) and protocol-relative links if (href && (href.startsWith('http://') || href.startsWith('https://') || href.startsWith('//'))) { httpLinks.push({ locator: link, href }); } } console.log(`Found ${httpLinks.length} external http(s) links to check\n`); const results = { working: 0, broken: [] }; for (const { locator: link, href } of httpLinks) { try { const response = await page.request.head(href); if (response.ok()) { results.working++; console.log(`✅ ${href}`); } else { results.broken.push({ url: href, status: response.status() }); console.log(`❌ ${href} (Status: ${response.status()})`); } } catch (e) { results.broken.push({ url: href, error: e.message }); console.log(`❌ ${href} (Error: ${e.message})`); } } console.log(`\n\n=== RESULTS ===`); console.log(`✅ Working links: ${results.working}`); console.log(`❌ Broken links: ${results.broken.length}`); if (results.broken.length > 0) { console.log('\nBroken link details:'); console.log(JSON.stringify(results.broken, null, 2)); } await browser.close(); })(); // Example: Test responsive design across multiple viewports const { chromium } = require('playwright'); const TARGET_URL = 'http://localhost:3000'; // Change as neede