Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Run Playwright scripts that reuse OpenClaw browser's login state via CDP with automatic lock-based conflict prevention.
Run Playwright scripts that reuse OpenClaw browser's login state via CDP with automatic lock-based conflict prevention.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
OpenClaw's browser tool and external Playwright scripts cannot share the same CDP connection simultaneously. This skill provides a lock-based bridge: stop OpenClaw browser โ run Playwright with the same Chrome profile (cookies/login intact) โ release for OpenClaw to reconnect.
Chrome (CDP port) โ shared user-data-dir (~/.openclaw/browser/openclaw/user-data) โ mutually exclusive โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ OpenClaw โ OR โ Playwright script โ โ browser tool โ โ (zero token cost) โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ managed by browser-lock.sh
Install Playwright in the workspace (once): cd <workspace> && npm install playwright Note: npx playwright install is NOT needed. Playwright connects to the existing Chrome via CDP โ no local browser download required. Copy scripts/browser-lock.sh to your workspace scripts/ directory: chmod +x scripts/browser-lock.sh
The CDP port is dynamically assigned. Never hardcode it. Use discoverCdpUrl() (see below) or the shell equivalent in browser-lock.sh. Shell one-liner: ps aux | grep 'remote-debugging-port=' | grep -v grep | grep -o 'remote-debugging-port=[0-9]*' | head -1 | cut -d= -f2 Verify CDP is responding: curl -s --max-time 1 http://127.0.0.1:<port>/json/version
./scripts/browser-lock.sh run scripts/my-task.js [args...] ./scripts/browser-lock.sh run --timeout 120 scripts/my-task.js # custom timeout Default timeout: 300s. If the script exceeds it, the watchdog kills it and releases the lock. This automatically: checks lock โ stops OpenClaw browser โ starts Chrome with CDP โ runs script โ cleans up โ releases lock.
./scripts/browser-lock.sh acquire # stop OpenClaw browser, start Chrome node scripts/my-task.js # run script(s) ./scripts/browser-lock.sh release # kill Chrome, release lock
./scripts/browser-lock.sh status
Use scripts/playwright-template.js as starting point.
All scripts should use discoverCdpUrl() instead of hardcoding a port: const { execSync } = require('child_process'); /** * Discover the CDP URL by inspecting Chrome process args. * Falls back to CDP_PORT env var, then probes common ports. */ function discoverCdpUrl() { // Method 1: extract from running Chrome process try { const ps = execSync( "ps aux | grep 'remote-debugging-port=' | grep -v grep", { encoding: 'utf8', timeout: 3000 } ); const match = ps.match(/remote-debugging-port=(\d+)/); if (match) return `http://127.0.0.1:${match[1]}`; } catch {} // Method 2: CDP_PORT env var if (process.env.CDP_PORT) { return `http://127.0.0.1:${process.env.CDP_PORT}`; } // Method 3: probe common ports // 18800 is the typical OpenClaw default; others are common CDP conventions const { execSync: probe } = require('child_process'); for (const port of [18800, 9222, 9229]) { try { probe(`curl -s --max-time 1 http://127.0.0.1:${port}/json/version`, { encoding: 'utf8', timeout: 2000 }); return `http://127.0.0.1:${port}`; } catch {} } throw new Error('CDP port not found. Is Chrome running with --remote-debugging-port?'); }
const { chromium } = require('playwright'); async function main() { let browser; try { browser = await chromium.connectOverCDP(discoverCdpUrl()); } catch (e) { console.error('โ Cannot connect to Chrome CDP:', e.message); console.error(' Ensure browser-lock.sh acquire was called, or Chrome is running with --remote-debugging-port'); process.exit(1); } const context = browser.contexts()[0]; // reuse existing context (cookies!) const page = await context.newPage(); try { // ====== Your automation here ====== await page.goto('https://example.com'); console.log('Title:', await page.title()); // ================================== } catch (e) { console.error('โ Script error:', e.message); throw e; } finally { await page.close(); // close only your tab // NEVER call browser.close() โ it kills the entire Chrome } } main().then(() => process.exit(0)).catch(e => { console.error('โ', e.message); process.exit(1); }); Critical rules: browser.contexts()[0] โ reuse the existing context to inherit cookies/login page.close() only โ never browser.close() Always process.exit(0) on success โ Playwright keeps event loops alive otherwise Wrap connectOverCDP in try-catch โ fail fast with a clear message
Explore โ Use OpenClaw browser tool (snapshot/act) to figure out a new workflow Record โ Ask the agent to convert the steps into a Playwright script Replay โ Run via browser-lock.sh run โ zero token cost, deterministic
In cron tasks, call browser-lock.sh directly: cd /path/to/workspace && ./scripts/browser-lock.sh run scripts/publish-task.js The lock file (/tmp/openclaw-browser.lock) prevents concurrent browser access. If a lock is stale (owner process dead), it auto-recovers.
ProblemFixLock held by PID xxx./scripts/browser-lock.sh release to force-releasePlaywright connectOverCDP timeoutEnsure OpenClaw browser is stopped first (acquire does this)CDP port not foundChrome isn't running; call browser-lock.sh acquire firstopenclaw browser stop doesn't kill ChromeKnown issue; browser-lock.sh kills the process directlyScript hangs after completionAdd process.exit(0) at the endLogin expiredUse OpenClaw browser tool to re-login, then run scripts again
VarDefaultDescriptionCDP_PORTauto-discoverOverride CDP port (skips process detection)CHROME_BINauto-detectPath to Chrome/Chromium binaryHEADLESSautoSet true/1 to force headless; false/0 to force headed. Auto-detects on Linux without DISPLAY
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.