Claude Code Plugins

Community-maintained marketplace

Feedback
0
0

Browser automation with Playwright. Use for web testing, form filling, file uploads, screenshots. Daemon-based for persistent browser state.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name playwright-browser
description Browser automation with Playwright. Use for web testing, form filling, file uploads, screenshots. Daemon-based for persistent browser state.

Playwright Browser Skill

Automate browsers via CLI with a daemon that maintains browser state between commands.

Quick Start (Daemon Required)

# 1. Start the daemon (visible browser for user interaction)
npx playwright-skill-daemon --headless false

# 2. In another terminal, run commands
npx playwright-skill navigate "https://example.com"
npx playwright-skill snapshot
npx playwright-skill click e2

Important: The daemon must be running before using CLI commands. If not running, you'll see a clear error message with instructions.

Core Workflow

Step 1: Start Daemon

# Visible browser (recommended for testing with user interaction)
npx playwright-skill-daemon --headless false

# Headless (for automated testing)
npx playwright-skill-daemon --headless true

Step 2: Navigate and Snapshot

npx playwright-skill navigate "https://example.com/login"
npx playwright-skill snapshot
# Response includes element refs: e1, e2, e5, etc.

Step 3: Interact Using Refs

npx playwright-skill fill e5 "user@example.com"
npx playwright-skill fill e8 "password"
npx playwright-skill click e12

Commands by Category

Navigation

npx playwright-skill navigate <url>      # Go to URL
npx playwright-skill back                # Browser back
npx playwright-skill forward             # Browser forward
npx playwright-skill reload              # Reload page

Interaction (by ref from snapshot)

npx playwright-skill click <ref>         # Click element
npx playwright-skill fill <ref> <value>  # Fill input
npx playwright-skill type <ref> <text>   # Type text
npx playwright-skill select <ref> <val>  # Select dropdown option
npx playwright-skill press <key>         # Press keyboard key
npx playwright-skill hover <ref>         # Hover over element

Interaction (by CSS selector)

Use when refs aren't available (e.g., modal elements not in snapshot):

npx playwright-skill click-selector "button[type=submit]"
npx playwright-skill fill-selector "input[name=email]" "user@example.com"
npx playwright-skill upload-selector "input[type=file]" "/path/to/file.csv"

Inspection

npx playwright-skill snapshot            # Get accessibility tree with refs
npx playwright-skill screenshot          # Take screenshot
npx playwright-skill query <selector>    # Query DOM (read-only)

Query Command (Read-Only DOM Inspection)

Use query when snapshot doesn't capture elements (e.g., modals rendered as portals):

# Find elements matching selector
npx playwright-skill query "button[type=submit]"
# Returns: { count: 2, elements: [{ text: "Submit", visible: true }] }

# Check if element exists
npx playwright-skill query ".modal" --exists
# Returns: { exists: true, count: 1 }

# Get specific attribute
npx playwright-skill query "input[name=csrf]" --attr value
# Returns: { value: "abc123" }

File Upload (Hidden Inputs)

Filament and other frameworks use hidden file inputs. Use upload-selector:

# Open modal with file upload
npx playwright-skill click e198

# Upload to hidden file input
npx playwright-skill upload-selector "input[type=file]" "/path/to/file.csv"

# Click submit using selector (modal buttons may not have refs)
npx playwright-skill click-selector "button[type=submit]:visible"

Auth State

npx playwright-skill auth-save <name>    # Save cookies/state
npx playwright-skill auth-load <name>    # Restore saved state
npx playwright-skill auth-status         # Show current auth
npx playwright-skill auth-clear          # Clear auth state

Response Format

All commands return JSON:

{
  "id": "req-2025-12-22-1",
  "command": "navigate",
  "success": true,
  "action": "Navigated to https://example.com",
  "pageState": {
    "url": "https://example.com",
    "title": "Example",
    "authStatus": "authenticated",
    "hasErrors": false
  },
  "cacheRef": {
    "id": "cache-abc123",
    "available": ["snapshot", "console", "network", "html"]
  }
}

Common Patterns

Login Flow

npx playwright-skill navigate "https://app.example.com/login"
npx playwright-skill snapshot
npx playwright-skill fill e29 "user@example.com"
npx playwright-skill fill e41 "password"
npx playwright-skill click e61

Form with File Upload (Filament/Livewire)

# Navigate and open modal
npx playwright-skill navigate "https://app.example.com/customers"
npx playwright-skill click e198  # "Import" button

# Upload file to hidden input
npx playwright-skill upload-selector "input[type=file]" "/path/to/data.csv"

# Query to verify submit button exists
npx playwright-skill query "button[type=submit]"

# Click submit using Playwright's native method
npx playwright-skill click-selector "button[type=submit]:visible"

When Refs Don't Work (Modals/Overlays)

Modal elements render as portals and may not appear in snapshot. Use selectors:

# 1. Query to find elements (read-only)
npx playwright-skill query ".fi-modal button"

# 2. Click using selector
npx playwright-skill click-selector "button:has-text('Submit')"

Troubleshooting

Issue Solution
"Daemon not running" Start with npx playwright-skill-daemon --headless false
Element ref not found Take fresh snapshot, page may have changed
Modal buttons not in snapshot Use query + click-selector instead
File upload not working Use upload-selector for hidden inputs
Livewire action not firing Use click-selector (native Playwright click)

Worktree Detection (Multi-Worktree Projects)

This skill supports projects with multiple git worktrees. It auto-detects which worktree you're in and uses the appropriate configuration.

Initial Setup

On first use, if configuration files don't exist, the agent will prompt you to create them:

  1. ./skill/worktrees.json - Maps worktree directories to base URLs and credentials
  2. ./skill/.secrets.json - Stores passwords (gitignored, never committed)

Both files are gitignored and project-specific. Example templates are provided:

# Copy example files and customize
cp ./skill/worktrees.example.json ./skill/worktrees.json
cp ./skill/secrets.example.json ./skill/.secrets.json

# Edit with your project's URLs and credentials

See worktrees.example.json and secrets.example.json for templates.

How It Works

  1. Detection: The skill reads your current working directory to determine which worktree you're in
  2. Configuration: Each worktree maps to a baseUrl, credentials, and tenant settings in ./skill/worktrees.json
  3. Usage: When you run commands, use the worktree-specific base URL

Example Worktree Configuration

{
  "worktrees": {
    "my-app": {
      "baseUrl": "https://my-app.test",
      "branch": "develop",
      "description": "Main development",
      "auth": {
        "defaultUser": "admin@example.com",
        "roles": {
          "admin": "admin@example.com",
          "user": "user@example.com"
        }
      }
    },
    "my-app-staging": {
      "baseUrl": "https://staging.my-app.test",
      "branch": "main",
      "description": "Staging environment"
    }
  }
}

Detecting Current Worktree

Before running tests, verify which worktree you're in:

# Check current directory
pwd
# e.g., /path/to/project/my-app

# The last directory component (my-app) determines the worktree

Using Worktree-Specific URLs

Always use the correct base URL for your worktree:

# If in my-app worktree:
npx playwright-skill navigate "https://my-app.test/dashboard"

# If in my-app-staging worktree:
npx playwright-skill navigate "https://staging.my-app.test/dashboard"

Credentials Configuration

Usernames are stored in ./skill/worktrees.json. Passwords are stored separately in ./skill/.secrets.json (gitignored):

{
  "passwords": {
    "admin@example.com": "yourPassword",
    "user@example.com": "password"
  }
}

Getting Credentials Programmatically

To get the correct credentials for the current worktree:

# 1. Detect worktree from current directory
WORKTREE=$(basename $(pwd))

# 2. Read base URL and credentials from config
cat ./skill/worktrees.json | jq ".worktrees[\"$WORKTREE\"]"

# 3. For passwords (if secrets file exists)
cat ./skill/.secrets.json | jq '.passwords'

Multi-Tenant Panel URLs

For multi-tenant apps, panel URLs can include a tenant slug:

{
  "tenant": {
    "slug": "acme-corp",
    "panels": {
      "admin": "/admin",
      "office": "/office/acme-corp",
      "user": "/app/acme-corp"
    }
  }
}
# Admin panel (no tenant in URL)
npx playwright-skill navigate "https://my-app.test/admin"

# Office panel (tenant in URL)
npx playwright-skill navigate "https://my-app.test/office/acme-corp"

Architecture

┌─────────────────────────────────────────┐
│           CLI Commands                   │
│  npx playwright-skill <command>          │
└─────────────────────────────────────────┘
                    │
          Unix Socket (/tmp/playwright-skill.sock)
                    │
                    ▼
┌─────────────────────────────────────────┐
│              Daemon                      │
│  - Owns browser instance                 │
│  - Maintains page state                  │
│  - 30 min idle timeout                   │
└─────────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────┐
│           Chromium Browser               │
│  - Visible when --headless false         │
│  - User can interact directly            │
└─────────────────────────────────────────┘

Reference Documentation: