agentsclimarketplace

Playwright cli setup

Skill AgentiaPT/vela-slides/.claude/skills/playwright-cli-setup

Vela Slides - AI Powered presentation App and Agent Skill

Install
npx -y skills add AgentiaPT/vela-slides --skill playwright-cli-setup

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

THE DEFAULT tool for ad-hoc / interactive Vela browser work — explore or test the app, screenshot a state, reproduce a bug, poke a selector, drive presenter/gallery flows, verify a UX change, run bench/vela-interaction-bench.sh. Drives a live offline Vela render via Playwright CLI (@playwright/cli), a persistent warm browser you steer one command at a time (open, snapshot, click, press, eval), inspecting state + output between steps. Prefer this over the committed `vela-drive.js` scripts (skill: vela-live-render) — those are for repeatable, committed automation only (CI, benchmark, recorded demo), NOT one-off exploration. Also prefer over writing throwaway Playwright .js files. Covers container setup (blocked CDNs, file:// block, pinned Chromium) and per-agent session isolation for parallel browser tests.

SKILL.md

9.4 KB, as published. Nobody here has run it

Playwright CLI ↔ Vela setup (this container)

@playwright/cli keeps a persistent browser as a background session (-s=<name>) and you drive it one command at a time — open, goto, snapshot, click e15, press ArrowRight, eval "…" — reading state between steps instead of running a blind script. window globals survive across invocations, so a helper installed once (e.g. a timing harness) stays live. Output (snapshots, console logs) is written to .playwright-cli/ (gitignored); read only what you need.

It is a different package from playwright and from Playwright MCP. Prefer it here for interactive/exploratory driving; it's cheaper on context than MCP (nothing streams into the conversation unless you read a file).

Setup — do this once per fresh container

1. Restore the locked deps, then install the CLI isolated (see Supply-chain safety below for why it's not committed):

npm ci --ignore-scripts                                                   # locked tree first
npm install --no-save --no-audit --no-fund --ignore-scripts @playwright/[email protected]

2. Config is already committed at .playwright/cli.config.json (the default config path, read from the repo root). It solves the two things that otherwise fail:

{
  "allowUnrestrictedFileAccess": true,
  "browser": {
    "browserName": "chromium",
    "launchOptions": {
      "executablePath": "/opt/pw-browsers/chromium-1194/chrome-linux/chrome",
      "headless": true,
      "args": ["--no-sandbox"]
    }
  }
}

Recreate it if missing. Update executablePath if the image's Chromium moves (ls /opt/pw-browsers/).

Supply-chain safety (why @playwright/cli is NOT committed)

This repo pins its supply chain via a committed package-lock.json (exact versions + sha512), npm ci --ignore-scripts in CI, npm audit gating, and a 7-day release-cooldown (.npmrc: ignore-scripts=true, see docs/SECURITY.md).

@playwright/[email protected] transitively depends on a days-old alpha of playwright (nested in its own node_modules, so it does not override the repo's locked top-level playwright). Committing it would pull that fresh alpha into the audited, shipped dependency tree — against the cooldown policy. So it is deliberately kept out of package.json / package-lock.json and installed as an isolated, dev/test-only tool. The install is hardened accordingly:

  • @playwright/[email protected] — exact version pin, no range (no surprise upgrades).
  • --ignore-scripts — blocks pre/post-install hooks (belt-and-suspenders with .npmrc: ignore-scripts=true); the #1 npm supply-chain vector.
  • --no-save — never writes to package.json/package-lock.json; the audited, shipped tree stays exactly as locked. npm still verifies the registry sha512 on download.
  • Ephemeral & unshippednode_modules/ is gitignored; the CLI never enters the Vela artifact, a release, or CI's locked install.
  • Always run npm ci --ignore-scripts first so the top-level playwright/etc. match the lockfile (an ad-hoc npm install earlier can drift them).

Before bumping the pin, check the new version's transitive playwright dep (npm view @playwright/cli@<v> dependencies) and prefer a version that resolves a stable playwright once one ships.

Drive a Vela deck

# 1. Build an OFFLINE render (transpiled, deck injected via STARTUP_PATCH).
#    Do NOT serve.py / esm.sh here — the React/lucide CDNs are blocked.
node tools/vela-dev/scripts/render-offline.js examples/vela-demo.vela /tmp/vout

# 2. Open a persistent session on the render (file:// works via the config).
npx playwright-cli -s=vela open "file:///tmp/vout/render.html"

# 3. Wait for hydration (~2–4s; offline app.js transpiles then mounts).
npx playwright-cli -s=vela eval "({b:!!window.__velaBooted, blocks:document.querySelectorAll('[data-block-type]').length})" --raw

# 4. Drive it. Examples:
npx playwright-cli -s=vela press f            # enter presentation (auto-selects 1st module)
npx playwright-cli -s=vela press ArrowRight   # next slide
npx playwright-cli -s=vela screenshot --filename=/tmp/slide.png
npx playwright-cli -s=vela eval "(document.querySelector('[data-block-type=heading]')||{}).textContent" --raw

# 5. Housekeeping.
npx playwright-cli list
npx playwright-cli -s=vela close
npx playwright-cli kill-all        # nuke stale/zombie browsers

Tip: node_modules/.bin/playwright-cli skips npx resolution overhead in loops.

Parallel agents — isolating concurrent browser tests

Multiple agents can drive Vela at once, but they share one machine-wide session registry (~/.cache/...) and one per-cwd output dir. Verified isolation ladder, weakest → strongest:

axishowwhat it isolatesgotcha
session name-s=agentA vs -s=agentBthe browser + page state (independent — one advancing slides doesn't move the other)same registry & same .playwright-cli/ output dir
registryPWTEST_DAEMON_SESSION_DIR=/tmp/agentA-daemon (per agent)the whole session daemon — an agent's sessions are invisible to another's list/close-all/kill-allmust set it on every command for that agent
workspace/cwdrun each agent from its own dir / git worktreesession namespace and the .playwright-cli/ output dir (both keyed off findWorkspaceDir(cwd))needs a separate checkout

Recommended patterns

  • Best: give each parallel agent its own git worktree (the Agent tool's isolation: "worktree"). Different cwd ⇒ different workspace ⇒ separate session namespace and separate .playwright-cli/ output, for free. Add a unique -s=<name> per agent too.
  • Same cwd: give each agent a unique -s=<name> and a unique PWTEST_DAEMON_SESSION_DIR — otherwise one agent's close-all/kill-all kills every agent's browsers (the single biggest footgun). Output files still land in the shared .playwright-cli/ (timestamped names rarely collide, but they intermix).

Two things that make this easy here: the offline file:// render needs no port, so parallel sessions never collide on a port (unlike serving over HTTP); and each deck can render to its own /tmp/<agent>-render dir. Cost: each session is a full Chromium (~200-300 MB RAM) — cap concurrency to the box, and never use the global close-all/kill-all from a parallel agent unless its registry is isolated.

Vela-specific hooks & selectors (for eval / interaction)

whathow
boot donewindow.__velaBooted === true and #root innerText non-empty
headless UI batteryawait window.__velaRunUITests() (see part-uitest.jsx)
current slide blocks[data-block-type] elements (text signature changes on nav)
current heading[data-block-type=heading]
in presentation?<header> is removed while presenting
gallery open?[data-testid=gallery-close] present
gallery scroll rail[data-scroll-container]
enter/exit presentkey f (or F5); Escape exits
next / prev slideArrowRight / ArrowLeft
open gallerykey g

Note: window.__velaGetCurrentSlide is gated behind local mode (off in offline renders) — use the DOM signals above instead.

Gotchas already solved (don't rediscover)

  • file:// is blocked by default"Access to file: protocol is blocked". Fixed by allowUnrestrictedFileAccess: true in the config (or env PLAYWRIGHT_MCP_ALLOW_UNRESTRICTED_FILE_ACCESS=1). Config is read at open time — if you change it, close and re-open the session.
  • Bundled playwright-core wants a newer Chromium than the image ships (expects ~1229, image has 1194) → the CDN download is blocked, so the config's executablePath points at the pinned build. Don't run playwright install.
  • CDNs (esm.sh / React / lucide / Babel) are blocked → never use serve.py's default importmap HTML; always render-offline.js (vendored UMD + Node transpile).
  • One harmless console error on every load (ERR_INVALID_URL / font fetch) — ignore it; the app renders fully.
  • Don't pkill background jobs from a Bash tool here — the sandbox may SIGKILL the shell (exit 144). Use playwright-cli close / kill-all for browsers.

Ready-made benchmark

bench/vela-interaction-bench.sh uses exactly this setup to measure slide-nav / interaction latency and thumbnail-scroll FPS. See bench/README.md.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.