drive-local-webapp
Launch or connect to a local development web server and drive it with a reusable headless-Chromium command interface. Use when asked to render, smoke-test, interact with, verify, or screenshot a local frontend or HTML mockup.
Install
npx skills add https://github.com/ConnorGriffin/skills/tree/main/skills/tools/drive-local-webapp
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install connorgriffin-skills@llmmart
git clone https://github.com/ConnorGriffin/skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole connorgriffin/skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Drive a local web app
Use the bundled Playwright driver instead of writing a one-off browser script.
It keeps one page alive while reading commands from standard input and reports
each command as OK or FAIL.
One-time setup
Resolve this installed skill's directory, then run:
cd <drive-local-webapp-skill-directory>
npm ci
npx playwright install chromium
Node.js 20 or newer is recommended. Browser binaries are cached by Playwright. Verify the installation reproducibly:
npm run self-check
Workflow
Start the target application's normal development or demo server. Use throwaway fixtures, never production or personal data. Check that the chosen port is free before binding it.
Run
node scripts/driver.mjsfrom this skill directory and pipe one command per line:DRIVER_SCREENSHOT_DIR=/tmp/webapp-shots node scripts/driver.mjs <<'EOF' nav http://127.0.0.1:8766/ wait-for text=Dashboard click button:text-is("Settings") fill input[placeholder="API token"] :: demo-token click button:text-is("Save") screenshot console --errors EOFTreat any
FAILline or non-zero exit as a failed check. Treat a non-emptyCONSOLE_ERRORSarray as a failed check unless the error is explicitly expected.Inspect the screenshot itself. File existence does not prove the intended UI rendered.
If the host sandbox blocks Chromium process creation, rerun the same driver command with the client's narrowly scoped approval mechanism. Do not reinstall Chromium or alter the application to work around a host permission error.
Only navigate to a local page you trust or a URL the user explicitly placed in scope. Headless Chromium is not a security boundary: page JavaScript can make network requests and exercise the permissions available to the browser process. Do not use this driver as a general-purpose browser for untrusted sites.
Commands
nav <url>
wait-for <selector>
click <selector>
mouse-click <x>,<y>
fill <selector> :: <value>
set <selector> :: <value>
press <key>
wait <milliseconds>
eval <javascript-expression>
screenshot [absolute-path]
console --errors
Use :text-is("Label") for exact text. Playwright's :has-text() is
case-insensitive substring matching and can silently click the wrong control.
Use mouse-click for a target with no addressable element, such as a canvas, an
embedded map, or a region inside a chart. Prefer a selector wherever one exists;
coordinates go stale as soon as the layout moves.
Keep screenshots outside the target repository. The driver defaults to the
system temporary directory, or use DRIVER_SCREENSHOT_DIR. It refuses to
overwrite an existing screenshot path.
Common failures
- Selectors containing spaces require the literal
::separator forfillandset. - Hidden tab content may exist in the DOM; click the actual tab before waiting on its contents.
- Charts initialized inside
display:nonecontainers may have zero width. Activate the tab, wait, and verify the app resizes or lazily initializes the chart. - A client-side token gate may leave the screen loading without a console error. Inspect the application's setup UI and use a demo token.
screenshotcaptures the full page, butmouse-clickaddresses the visible viewport. On a page taller than the viewport, a point measured off a screenshot is not the point that gets clicked, and a point past the viewport still reportsOKwhile hitting nothing. Scroll the target into view first, and assert on the effect rather than on theOKline.
Files (skills)
-
agents
-
openai.yaml 208 B
interface: display_name: "Drive Local Web App" short_description: "Verify local web apps in headless Chromium" default_prompt: "Use $drive-local-webapp to smoke-test and screenshot this local web app."
-
-
scripts
-
driver.mjs 5.6 KB · in bundle
-
self-check.mjs 3 KB · in bundle
-
-
package-lock.json 1.7 KB
{ "name": "drive-local-webapp-skill", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "drive-local-webapp-skill", "version": "1.0.0", "dependencies": { "playwright": "1.61.1" } }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/playwright": { "version": "1.61.1", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", "license": "Apache-2.0", "dependencies": { "playwright-core": "1.61.1" }, "bin": { "playwright": "cli.js" }, "engines": { "node": ">=18" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { "version": "1.61.1", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { "node": ">=18" } } } } -
package.json 320 B
{ "name": "drive-local-webapp-skill", "private": true, "type": "module", "version": "1.0.0", "description": "Reusable Playwright command driver bundled with the drive-local-webapp skill.", "scripts": { "self-check": "node scripts/self-check.mjs" }, "dependencies": { "playwright": "1.61.1" } } -
SKILL.md 3.8 KB
--- name: drive-local-webapp description: Launch or connect to a local development web server and drive it with a reusable headless-Chromium command interface. Use when asked to render, smoke-test, interact with, verify, or screenshot a local frontend or HTML mockup. --- # Drive a local web app Use the bundled Playwright driver instead of writing a one-off browser script. It keeps one page alive while reading commands from standard input and reports each command as `OK` or `FAIL`. ## One-time setup Resolve this installed skill's directory, then run: ```sh cd <drive-local-webapp-skill-directory> npm ci npx playwright install chromium ``` Node.js 20 or newer is recommended. Browser binaries are cached by Playwright. Verify the installation reproducibly: ```sh npm run self-check ``` ## Workflow 1. Start the target application's normal development or demo server. Use throwaway fixtures, never production or personal data. Check that the chosen port is free before binding it. 2. Run `node scripts/driver.mjs` from this skill directory and pipe one command per line: ```sh DRIVER_SCREENSHOT_DIR=/tmp/webapp-shots node scripts/driver.mjs <<'EOF' nav http://127.0.0.1:8766/ wait-for text=Dashboard click button:text-is("Settings") fill input[placeholder="API token"] :: demo-token click button:text-is("Save") screenshot console --errors EOF ``` 3. Treat any `FAIL` line or non-zero exit as a failed check. Treat a non-empty `CONSOLE_ERRORS` array as a failed check unless the error is explicitly expected. 4. Inspect the screenshot itself. File existence does not prove the intended UI rendered. If the host sandbox blocks Chromium process creation, rerun the same driver command with the client's narrowly scoped approval mechanism. Do not reinstall Chromium or alter the application to work around a host permission error. Only navigate to a local page you trust or a URL the user explicitly placed in scope. Headless Chromium is not a security boundary: page JavaScript can make network requests and exercise the permissions available to the browser process. Do not use this driver as a general-purpose browser for untrusted sites. ## Commands ```text nav <url> wait-for <selector> click <selector> mouse-click <x>,<y> fill <selector> :: <value> set <selector> :: <value> press <key> wait <milliseconds> eval <javascript-expression> screenshot [absolute-path] console --errors ``` Use `:text-is("Label")` for exact text. Playwright's `:has-text()` is case-insensitive substring matching and can silently click the wrong control. Use `mouse-click` for a target with no addressable element, such as a canvas, an embedded map, or a region inside a chart. Prefer a selector wherever one exists; coordinates go stale as soon as the layout moves. Keep screenshots outside the target repository. The driver defaults to the system temporary directory, or use `DRIVER_SCREENSHOT_DIR`. It refuses to overwrite an existing screenshot path. ## Common failures - Selectors containing spaces require the literal ` :: ` separator for `fill` and `set`. - Hidden tab content may exist in the DOM; click the actual tab before waiting on its contents. - Charts initialized inside `display:none` containers may have zero width. Activate the tab, wait, and verify the app resizes or lazily initializes the chart. - A client-side token gate may leave the screen loading without a console error. Inspect the application's setup UI and use a demo token. - `screenshot` captures the full page, but `mouse-click` addresses the visible viewport. On a page taller than the viewport, a point measured off a screenshot is not the point that gets clicked, and a point past the viewport still reports `OK` while hitting nothing. Scroll the target into view first, and assert on the effect rather than on the `OK` line.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.