The Problem

Browser automation requires writing and executing Playwright scripts on-the-fly, but teams often lack a lightweight mechanism for Claude to generate and run custom automation without context switching or pre-built script limitations. This creates bottlenecks for testing, validation, and ad-hoc browser interactions.

What This Does

This repository implements a Claude Code Skill that enables model-invoked browser automation via Playwright. The skill lives at skills/playwright-skill/ and is consumed through Claude's plugin framework. Core functionality is defined in skills/playwright-skill/lib/helpers.js (15 functions including launchBrowser, createPage, safeClick, safeType, and waitForPageReady) and skills/playwright-skill/run.js (6 functions including checkPlaywrightInstalled, installPlaywright, getCodeToExecute, wrapCodeIfNeeded, and cleanupOldTempFiles). Execution starts at main in run.js:182, which orchestrates the flow from code retrieval to browser launch and cleanup. The internal call graph shows main as the hub with 8 outgoing edges to its helper functions, while authenticate and createContext serve as secondary entry points with fewer dependencies.

How It Is Wired

Execution flows from the main entry point in run.js through a traced path: main calls getCodeToExecute to retrieve automation code, then installPlaywright if needed, followed by checkPlaywrightInstalled, and finally delegates to helper functions like launchBrowser and createPage from lib/helpers.js. The graph contains 9 resolved call edges total, with no circular dependencies. main reaches 5 functions and is itself called from 1 place. The eval() call in lib/helpers.js executes a runtime-computed string, creating a code-injection surface where the origin of the evaluated value determines the exploit reach. The dependency graph shows skills/playwright-skill/run as the most connected module (Ca 0, Ce 1, instability 1), while lib/helpers has inverse connectivity (Ca 1, Ce 0, instability 0), making run.js the single point through which all automation flows.

How To Use It

Setup:

# Plugin installation (recommended)
/plugin marketplace add lackeyjb/playwright-skill
/plugin install playwright-skill@playwright-skill
cd ~/.claude/plugins/marketplaces/playwright-skill/skills/playwright-skill
npm run setup

# Or standalone global
git clone https://github.com/lackeyjb/playwright-skill.git /tmp/playwright-skill-temp
mkdir -p ~/.claude/skills
cp -r /tmp/playwright-skill-temp/skills/playwright-skill ~/.claude/skills/
cd ~/.claude/skills/playwright-skill
npm run setup
rm -rf /tmp/playwright-skill-temp

Configuration: No configuration file is present. Environment variables are read via getExtraHeadersFromEnv in lib/helpers.js, but no required vars are documented beyond what the function resolves at runtime.

Running it: Invoke via Claude Code after installation; the skill is available through /help. No separate CLI or server start command is provided beyond the plugin integration.

Real-World Use

A QA engineer asks Claude to "verify the login flow on the staging environment." Claude invokes the skill, writes a custom Playwright script that navigates to the staging URL, fills credentials, submits the form, and asserts the dashboard is visible. The script executes in a visible browser (headless: false by default), and the engineer observes the automation in real-time. After execution, cleanupOldTempFiles removes any temporary artifacts. This replaces a manual Selenium script write-run-debug cycle with model-generated, on-demand automation.

Code Health & Issues

  • [HIGH] Commit a lockfile beside the manifest - skills/playwright-skill/package.json has dependencies declared without a lockfile, enabling non-reproducible builds where the tested artifact may differ from the shipped one.
  • [HIGH] Remove eval over a runtime value - skills/playwright-skill/lib/helpers.js contains eval() over a computed value, executing arbitrary code reachable from the string's origin.
  • [MEDIUM] Enable Dependabot or Renovate - 1 manifest exists with no update bot configured; published advisories remain unpatched until manual audit.

The Bottom Line

The skill delivers a functional, minimal browser-automation mechanism that integrates cleanly with Claude Code's plugin system. The code is small enough to audit directly, and the call graph is simple enough to reason about. However, the missing lockfile and the eval() usage are production-grade risks that should be addressed before the skill is shared beyond a trusted internal context. Teams comfortable with model-generated code and willing to pin dependencies will find this useful; others should pin dependencies and replace the eval before deploying to shared environments.