{"id":"727cc506-256b-404f-a142-0a52e11a30fd","entityType":"agent","slug":"clawhub-athola-nm-scry-browser-recording","name":"browser-recording","canonicalUrl":"https://www.xpersona.co/agent/clawhub-athola-nm-scry-browser-recording","canonicalPath":"/agent/clawhub-athola-nm-scry-browser-recording","generatedAt":"2026-10-10T10:56:42.880Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T08:34:12.773Z","emptyReason":null},"description":"Records browser sessions via Playwright and converts video to GIF Skill: browser-recording Owner: athola Summary: Records browser sessions via Playwright and converts video to GIF Tags: latest:1.9.19 Version history: v1.9.19 | 2026-08-26T13:22:46.041Z | user Release v1.9.19 v1.9.17 | 2026-07-30T05:42:37.119Z | user Release v1.9.17 v1.9.16 | 2026-07-14T19:59:28.809Z | user Release v1.9.16 v1.9.14 | 2026-06-30T18:06:55.013Z | user Release v1.9.14 v1.9.13 | 2026-06-27T16:24:47.231Z |","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.6K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17emme0e2m3cpf7k2jvp3a84984b8z9:nm-scry-browser-recording","sourceUrl":"https://clawhub.ai/athola/nm-scry-browser-recording","homepage":"https://clawhub.ai/athola/skills/nm-scry-browser-recording","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/athola/nm-scry-browser-recording","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/athola/skills/nm-scry-browser-recording","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":64,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Records browser sessions via Playwright and converts video to GIF Skill: browser-recording Owner: athola Summary: Records browser sessions via Playwright and co"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:34:12.773Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:34:12.773Z","emptyReason":null},"stars":null,"forks":null,"downloads":1554,"packageName":null,"latestVersion":"1.9.19","tractionLabel":"1.6K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:34:12.773Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T08:34:12.773Z","lastCrawledAt":"2026-10-10T08:34:12.773Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T08:34:12.773Z","lastVerifiedAt":null,"highlights":[{"version":"1.9.19","createdAt":"2026-08-26T13:22:46.041Z","changelog":"Release v1.9.19","fileCount":5,"zipByteSize":7860},{"version":"1.9.17","createdAt":"2026-07-30T05:42:37.119Z","changelog":"Release v1.9.17","fileCount":5,"zipByteSize":7870},{"version":"1.9.16","createdAt":"2026-07-14T19:59:28.809Z","changelog":"Release v1.9.16","fileCount":5,"zipByteSize":7949},{"version":"1.9.14","createdAt":"2026-06-30T18:06:55.013Z","changelog":"Release v1.9.14","fileCount":5,"zipByteSize":7853},{"version":"1.9.13","createdAt":"2026-06-27T16:24:47.231Z","changelog":"Release v1.9.13","fileCount":5,"zipByteSize":7856},{"version":"1.9.12","createdAt":"2026-06-19T03:20:32.124Z","changelog":"Release v1.9.12","fileCount":5,"zipByteSize":7952},{"version":"1.0.2","createdAt":"2026-05-09T02:20:33.793Z","changelog":"Release v1.9.5","fileCount":5,"zipByteSize":8022},{"version":"1.0.1","createdAt":"2026-05-06T14:22:05.168Z","changelog":"Release v1.9.4","fileCount":4,"zipByteSize":6838}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17emme0e2m3cpf7k2jvp3a84984b8z9:nm-scry-browser-recording","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T10:56:42.877Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-athola-nm-scry-browser-recording/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-10T08:34:12.773Z","emptyReason":null},"readme":"Skill: browser-recording\n\nOwner: athola\n\nSummary: Records browser sessions via Playwright and converts video to GIF\n\nTags: latest:1.9.19\n\nVersion history:\n\nv1.9.19 | 2026-08-26T13:22:46.041Z | user\n\nRelease v1.9.19\n\nv1.9.17 | 2026-07-30T05:42:37.119Z | user\n\nRelease v1.9.17\n\nv1.9.16 | 2026-07-14T19:59:28.809Z | user\n\nRelease v1.9.16\n\nv1.9.14 | 2026-06-30T18:06:55.013Z | user\n\nRelease v1.9.14\n\nv1.9.13 | 2026-06-27T16:24:47.231Z | user\n\nRelease v1.9.13\n\nv1.9.12 | 2026-06-19T03:20:32.124Z | user\n\nRelease v1.9.12\n\nv1.0.2 | 2026-05-09T02:20:33.793Z | user\n\nRelease v1.9.5\n\nv1.0.1 | 2026-05-06T14:22:05.168Z | user\n\nRelease v1.9.4\n\nv1.0.0 | 2026-04-20T15:01:46.370Z | auto\n\nInitial release of the browser-recording skill for Playwright-based web UI video capture.\n\n- Record browser sessions using Playwright for web UI tutorials and documentation\n- Converts recorded videos (WebM) to GIFs via gif-generation skill\n- Validates Playwright installation, spec file presence, and video output\n- Supports cross-browser recording, CI/CD workflows, and automated test specs\n- Includes troubleshooting steps and example Playwright config/specs for best practices\n\nArchive index:\n\nArchive v1.9.19: 5 files, 7860 bytes\n\nFiles: modules/spec-execution.md (3911b), modules/video-capture.md (4559b), skill-card.md (1969b), SKILL.md (6459b), _meta.json (145b)\n\nFile v1.9.19:SKILL.md\n\n---\nname: browser-recording\ndescription: Records browser sessions via Playwright and converts video to GIF\nversion: 1.9.8\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\n  - creating web UI tutorials or demos showing browser interactions\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright --version\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nIf not installed, the user should run:\n```bash\nnpm install -D @playwright/test\nnpx playwright install chromium\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n### Step 2: Check Spec File\n\nVerify the Playwright spec file exists. Spec files should:\n- Be located in a `specs/` or `tests/` directory\n- Have `.spec.ts` or `.spec.js` extension\n- Include video configuration (see spec-execution module)\n\n### Step 3: Execute Recording\n\nRun the spec with video enabled:\n\n```bash\nnpx playwright test <spec-file> --config=playwright.config.ts\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\nThe config must enable video recording. See the spec-execution module for configuration details.\n\n### Step 4: Convert to GIF\n\nAfter recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:\n\n```\n**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Example Playwright Spec\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo workflow', async ({ page }) => {\n  // Navigate to the application\n  await page.goto('http://localhost:3000');\n\n  // Wait for page to be ready\n  await page.waitForLoadState('networkidle');\n\n  // Perform demo actions\n  await page.click('button[data-testid=\"start\"]');\n  await page.waitForTimeout(500); // Allow animation to complete\n\n  await page.fill('input[name=\"query\"]', 'example search');\n  await page.waitForTimeout(300);\n\n  await page.click('button[type=\"submit\"]');\n  await page.waitForSelector('.results');\n\n  // Final pause to show results\n  await page.waitForTimeout(1000);\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Playwright Configuration\n\nCreate or update `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: {\n      mode: 'on',\n      size: { width: 1280, height: 720 }\n    },\n    viewport: { width: 1280, height: 720 },\n    launchOptions: {\n      slowMo: 100 // Slow down actions for visibility\n    }\n  },\n  outputDir: './test-results',\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Exit Criteria\n\n- Playwright spec executed successfully (exit code 0)\n- Video file exists in output directory\n- Video has non-zero file size\n- GIF conversion completed (if requested)\n\n## Error Handling\n\n| Error | Resolution |\n|-------|------------|\n| Playwright not installed | Run `npm install -D @playwright/test` |\n| Browser not installed | Run `npx playwright install chromium` |\n| Spec file not found | Verify path and file extension |\n| Video not created | Check Playwright config has video enabled |\n| Empty video file | validate spec actions complete before test ends |\n\n## Output Locations\n\nDefault output paths:\n- Videos: `./test-results/<test-name>/video.webm`\n- Screenshots: `./test-results/<test-name>/screenshot.png`\n\n## Module Reference\n\n- See `modules/spec-execution.md` for detailed Playwright execution options\n- See `modules/video-capture.md` for video format and quality settings\n\n## See Also\n\n- scry:gif-generation: Convert video to optimized GIF\n\nFile v1.9.19:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-scry-browser-recording\",\n  \"version\": \"1.9.19\",\n  \"publishedAt\": 1787750566041\n}\n\nFile v1.9.19:modules/spec-execution.md\n\n# Spec Execution Module\n\nExecute Playwright specs with video recording enabled.\n\n## Playwright Configuration for Video\n\n### Minimal Config\n\nCreate `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: 'on',\n  },\n  outputDir: './test-results',\n});\n```\n\n### Full Recording Config\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: './specs',\n  outputDir: './test-results',\n\n  use: {\n    // Video settings\n    video: {\n      mode: 'on',           // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'\n      size: {\n        width: 1280,\n        height: 720\n      }\n    },\n\n    // Browser settings\n    viewport: { width: 1280, height: 720 },\n    headless: true,\n\n    // Slow down for visibility in recordings\n    launchOptions: {\n      slowMo: 100\n    },\n\n    // Browser context\n    contextOptions: {\n      recordVideo: {\n        dir: './test-results/videos',\n        size: { width: 1280, height: 720 }\n      }\n    }\n  },\n\n  // Disable retries for recording\n  retries: 0,\n\n  // Single worker for consistent recording\n  workers: 1,\n});\n```\n\n## Running Specs\n\n### Basic Execution\n\n```bash\nnpx playwright test specs/demo.spec.ts\n```\n\n### With Custom Config\n\n```bash\nnpx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts\n```\n\n### Common Options\n\n```bash\n# Run specific test by name\nnpx playwright test -g \"demo workflow\"\n\n# Run in headed mode (visible browser)\nnpx playwright test --headed\n\n# Use specific browser\nnpx playwright test --project=chromium\n\n# Set timeout\nnpx playwright test --timeout=60000\n\n# Output verbose logs\nnpx playwright test --debug\n```\n\n## Video Output Paths\n\nPlaywright creates videos at:\n```\n<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm\n```\n\nExample:\n```\ntest-results/demo-spec-ts-chromium/demo-workflow/video.webm\n```\n\n### Programmatic Video Path\n\nAccess video path in test:\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo', async ({ page }, testInfo) => {\n  // ... test actions ...\n\n  // After test, attach video path\n  const video = page.video();\n  if (video) {\n    const path = await video.path();\n    console.log('Video saved to:', path);\n  }\n});\n```\n\n## Error Handling\n\n### Common Issues\n\n**Browser not installed:**\n```bash\nnpx playwright install chromium\n```\n\n**Timeout errors:**\n```typescript\n// Increase action timeout\nawait page.click('button', { timeout: 10000 });\n\n// Or set global timeout in config\nuse: {\n  actionTimeout: 10000,\n}\n```\n\n**Video not created:**\n- validate `video: 'on'` in config\n- Check test actually runs (not skipped)\n- Verify outputDir is writable\n\n**Empty or corrupted video:**\n- Add `await page.waitForTimeout(500)` before test ends\n- validate page has loaded: `await page.waitForLoadState('networkidle')`\n\n### Exit Code Handling\n\n```bash\nnpx playwright test specs/demo.spec.ts\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"Recording completed successfully\"\n  # Find video file\n  VIDEO=$(find test-results -name \"video.webm\" -type f | head -1)\n  echo \"Video: $VIDEO\"\nelse\n  echo \"Recording failed with exit code $EXIT_CODE\"\n  exit $EXIT_CODE\nfi\n```\n\n## Best Practices for Recording Specs\n\n1. **Use explicit waits** - Avoid flaky recordings\n   ```typescript\n   await page.waitForSelector('.element');\n   await page.waitForLoadState('networkidle');\n   ```\n\n2. **Add pauses for visibility** - Give viewers time to see actions\n   ```typescript\n   await page.waitForTimeout(500);\n   ```\n\n3. **Use slowMo** - Slow down all actions\n   ```typescript\n   launchOptions: { slowMo: 100 }\n   ```\n\n4. **Consistent viewport** - Match video size to viewport\n   ```typescript\n   viewport: { width: 1280, height: 720 },\n   video: { size: { width: 1280, height: 720 } }\n   ```\n\n5. **Disable retries** - One clean recording\n   ```typescript\n   retries: 0\n   ```\n\nFile v1.9.19:modules/video-capture.md\n\n# Video Capture Module\n\nVideo format options, quality settings, and post-processing for Playwright recordings.\n\n## Video Format\n\nPlaywright records video in **WebM** format with VP8 codec. This format:\n- Has good compression\n- Supports transparency (if needed)\n- Works well with ffmpeg for conversion\n- Is natively supported by most browsers\n\n## Resolution Settings\n\n### Common Resolutions\n\n| Resolution | Use Case | Aspect Ratio |\n|------------|----------|--------------|\n| 1920x1080 | Full HD, detailed demos | 16:9 |\n| 1280x720 | Standard tutorials | 16:9 |\n| 1024x768 | Compact demos | 4:3 |\n| 800x600 | Small GIF output | 4:3 |\n\n### Playwright Video Size Configuration\n\n```typescript\n// In playwright.config.ts\nuse: {\n  video: {\n    mode: 'on',\n    size: { width: 1280, height: 720 }\n  },\n  viewport: { width: 1280, height: 720 }\n}\n```\n\n**Important:** Match `video.size` to `viewport` for best quality.\n\n### Per-Test Video Settings\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  video: {\n    mode: 'on',\n    size: { width: 1920, height: 1080 }\n  },\n  viewport: { width: 1920, height: 1080 }\n});\n\ntest('high-res demo', async ({ page }) => {\n  // Test runs at 1080p\n});\n```\n\n## Quality Considerations\n\n### Frame Rate\n\nPlaywright records at approximately 25 fps. This is sufficient for UI demos.\n\n### Bitrate\n\nWebM videos from Playwright use variable bitrate. Typical sizes:\n- 720p, 30 seconds: 2-5 MB\n- 1080p, 30 seconds: 5-10 MB\n\n### Minimizing File Size\n\n1. **Smaller viewport** - Reduce dimensions\n2. **Shorter duration** - Trim unnecessary pauses\n3. **Simple animations** - Fewer visual changes = smaller file\n\n## Playwright Video Configuration in Tests\n\n### Enable Video for Specific Tests\n\n```typescript\nimport { test } from '@playwright/test';\n\n// Enable video for this test file\ntest.describe.configure({ mode: 'serial' });\n\ntest.use({\n  video: 'on',\n  viewport: { width: 1280, height: 720 }\n});\n\ntest('recorded demo', async ({ page }) => {\n  await page.goto('https://example.com');\n  await page.waitForTimeout(1000);\n});\n```\n\n### Conditional Recording\n\n```typescript\nimport { test } from '@playwright/test';\n\nconst RECORD = process.env.RECORD === 'true';\n\ntest.use({\n  video: RECORD ? 'on' : 'off'\n});\n\ntest('conditionally recorded', async ({ page }) => {\n  // Only records when RECORD=true\n});\n```\n\n### Custom Video Directory\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  contextOptions: {\n    recordVideo: {\n      dir: './custom-video-output',\n      size: { width: 1280, height: 720 }\n    }\n  }\n});\n```\n\n## Post-Processing with ffmpeg\n\n### Convert WebM to MP4\n\n```bash\nffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4\n```\n\n### Extract Specific Time Range\n\n```bash\n# Extract from 0:05 to 0:15\nffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm\n```\n\n### Change Resolution\n\n```bash\n# Scale to 800px width, maintain aspect ratio\nffmpeg -i video.webm -vf \"scale=800:-1\" scaled.webm\n```\n\n### Speed Up Video\n\n```bash\n# 2x speed\nffmpeg -i video.webm -filter:v \"setpts=0.5*PTS\" faster.webm\n```\n\n### Add Padding/Borders\n\n```bash\n# Add 10px black border\nffmpeg -i video.webm -vf \"pad=width+20:height+20:10:10:black\" padded.webm\n```\n\n### Combine Multiple Videos\n\n```bash\n# Create file list\necho \"file 'video1.webm'\" > list.txt\necho \"file 'video2.webm'\" >> list.txt\n\n# Concatenate\nffmpeg -f concat -safe 0 -i list.txt -c copy combined.webm\n```\n\n## Converting to GIF\n\nFor GIF conversion, use the `scry:gif-generation` skill which handles:\n- Palette generation for optimal colors\n- Frame rate reduction (10-15 fps typical)\n- Width scaling\n- Dithering for quality\n\nQuick ffmpeg conversion (basic):\n\n```bash\n# Simple conversion (larger file, lower quality)\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1\" output.gif\n\n# Better quality with palette\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" output.gif\n```\n\n## Troubleshooting\n\n### Video is black or frozen\n\n- validate page has visible content before recording starts\n- Add `await page.waitForLoadState('domcontentloaded')`\n- Check for CSS that hides content initially\n\n### Video cuts off early\n\n- Test might be finishing before video flushes\n- Add `await page.waitForTimeout(500)` at end of test\n- validate `await page.close()` is not called (Playwright handles cleanup)\n\n### Video too large\n\n- Reduce resolution\n- Shorten test duration\n- Use post-processing to compress\n\n### Choppy playback\n\n- Normal at high resolutions\n- Consider reducing to 720p\n- Final GIF will be smoother at lower fps\n\nFile v1.9.19:skill-card.md\n\n## Description:\n\nRecords browser sessions via Playwright and converts video to GIF.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[athola](https://clawhub.ai/user/athola)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and technical writers use this skill to automate browser interactions with Playwright and produce WebM or GIF recordings for tutorials, documentation, and web application demos.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Browser recordings and GIFs can capture sensitive account data or private page content.\n\nMitigation: Record against sanitized demo or test accounts and review generated media before sharing.\n\nRisk: Untrusted Playwright specs or configs can drive browser actions outside the intended demo flow.\n\nMitigation: Use trusted specs and configs, review commands before execution, and keep dependencies pinned with a lockfile.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/athola/skills/nm-scry-browser-recording)\n- [clawdis homepage](https://github.com/athola/claude-night-market/tree/master/plugins/scry)\n- [Spec Execution Module](artifact/modules/spec-execution.md)\n- [Video Capture Module](artifact/modules/video-capture.md)\n\n## Skill Output:\n\n**Output Type(s):** [guidance, shell commands, code, configuration, markdown]\n\n**Output Format:** [Markdown with inline bash and TypeScript code blocks]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include Playwright spec and configuration snippets, recording file paths, and GIF conversion guidance.]\n\n## Skill Version(s):\n\n1.9.19 (source: server release metadata; artifact frontmatter lists 1.9.8)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.9.17: 5 files, 7870 bytes\n\nFiles: modules/spec-execution.md (3911b), modules/video-capture.md (4559b), skill-card.md (2131b), SKILL.md (6459b), _meta.json (145b)\n\nFile v1.9.17:SKILL.md\n\n---\nname: browser-recording\ndescription: Records browser sessions via Playwright and converts video to GIF\nversion: 1.9.8\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\n  - creating web UI tutorials or demos showing browser interactions\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright --version\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nIf not installed, the user should run:\n```bash\nnpm install -D @playwright/test\nnpx playwright install chromium\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n### Step 2: Check Spec File\n\nVerify the Playwright spec file exists. Spec files should:\n- Be located in a `specs/` or `tests/` directory\n- Have `.spec.ts` or `.spec.js` extension\n- Include video configuration (see spec-execution module)\n\n### Step 3: Execute Recording\n\nRun the spec with video enabled:\n\n```bash\nnpx playwright test <spec-file> --config=playwright.config.ts\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\nThe config must enable video recording. See the spec-execution module for configuration details.\n\n### Step 4: Convert to GIF\n\nAfter recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:\n\n```\n**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Example Playwright Spec\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo workflow', async ({ page }) => {\n  // Navigate to the application\n  await page.goto('http://localhost:3000');\n\n  // Wait for page to be ready\n  await page.waitForLoadState('networkidle');\n\n  // Perform demo actions\n  await page.click('button[data-testid=\"start\"]');\n  await page.waitForTimeout(500); // Allow animation to complete\n\n  await page.fill('input[name=\"query\"]', 'example search');\n  await page.waitForTimeout(300);\n\n  await page.click('button[type=\"submit\"]');\n  await page.waitForSelector('.results');\n\n  // Final pause to show results\n  await page.waitForTimeout(1000);\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Playwright Configuration\n\nCreate or update `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: {\n      mode: 'on',\n      size: { width: 1280, height: 720 }\n    },\n    viewport: { width: 1280, height: 720 },\n    launchOptions: {\n      slowMo: 100 // Slow down actions for visibility\n    }\n  },\n  outputDir: './test-results',\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Exit Criteria\n\n- Playwright spec executed successfully (exit code 0)\n- Video file exists in output directory\n- Video has non-zero file size\n- GIF conversion completed (if requested)\n\n## Error Handling\n\n| Error | Resolution |\n|-------|------------|\n| Playwright not installed | Run `npm install -D @playwright/test` |\n| Browser not installed | Run `npx playwright install chromium` |\n| Spec file not found | Verify path and file extension |\n| Video not created | Check Playwright config has video enabled |\n| Empty video file | validate spec actions complete before test ends |\n\n## Output Locations\n\nDefault output paths:\n- Videos: `./test-results/<test-name>/video.webm`\n- Screenshots: `./test-results/<test-name>/screenshot.png`\n\n## Module Reference\n\n- See `modules/spec-execution.md` for detailed Playwright execution options\n- See `modules/video-capture.md` for video format and quality settings\n\n## See Also\n\n- scry:gif-generation: Convert video to optimized GIF\n\nFile v1.9.17:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-scry-browser-recording\",\n  \"version\": \"1.9.17\",\n  \"publishedAt\": 1785390157119\n}\n\nFile v1.9.17:modules/spec-execution.md\n\n# Spec Execution Module\n\nExecute Playwright specs with video recording enabled.\n\n## Playwright Configuration for Video\n\n### Minimal Config\n\nCreate `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: 'on',\n  },\n  outputDir: './test-results',\n});\n```\n\n### Full Recording Config\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: './specs',\n  outputDir: './test-results',\n\n  use: {\n    // Video settings\n    video: {\n      mode: 'on',           // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'\n      size: {\n        width: 1280,\n        height: 720\n      }\n    },\n\n    // Browser settings\n    viewport: { width: 1280, height: 720 },\n    headless: true,\n\n    // Slow down for visibility in recordings\n    launchOptions: {\n      slowMo: 100\n    },\n\n    // Browser context\n    contextOptions: {\n      recordVideo: {\n        dir: './test-results/videos',\n        size: { width: 1280, height: 720 }\n      }\n    }\n  },\n\n  // Disable retries for recording\n  retries: 0,\n\n  // Single worker for consistent recording\n  workers: 1,\n});\n```\n\n## Running Specs\n\n### Basic Execution\n\n```bash\nnpx playwright test specs/demo.spec.ts\n```\n\n### With Custom Config\n\n```bash\nnpx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts\n```\n\n### Common Options\n\n```bash\n# Run specific test by name\nnpx playwright test -g \"demo workflow\"\n\n# Run in headed mode (visible browser)\nnpx playwright test --headed\n\n# Use specific browser\nnpx playwright test --project=chromium\n\n# Set timeout\nnpx playwright test --timeout=60000\n\n# Output verbose logs\nnpx playwright test --debug\n```\n\n## Video Output Paths\n\nPlaywright creates videos at:\n```\n<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm\n```\n\nExample:\n```\ntest-results/demo-spec-ts-chromium/demo-workflow/video.webm\n```\n\n### Programmatic Video Path\n\nAccess video path in test:\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo', async ({ page }, testInfo) => {\n  // ... test actions ...\n\n  // After test, attach video path\n  const video = page.video();\n  if (video) {\n    const path = await video.path();\n    console.log('Video saved to:', path);\n  }\n});\n```\n\n## Error Handling\n\n### Common Issues\n\n**Browser not installed:**\n```bash\nnpx playwright install chromium\n```\n\n**Timeout errors:**\n```typescript\n// Increase action timeout\nawait page.click('button', { timeout: 10000 });\n\n// Or set global timeout in config\nuse: {\n  actionTimeout: 10000,\n}\n```\n\n**Video not created:**\n- validate `video: 'on'` in config\n- Check test actually runs (not skipped)\n- Verify outputDir is writable\n\n**Empty or corrupted video:**\n- Add `await page.waitForTimeout(500)` before test ends\n- validate page has loaded: `await page.waitForLoadState('networkidle')`\n\n### Exit Code Handling\n\n```bash\nnpx playwright test specs/demo.spec.ts\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"Recording completed successfully\"\n  # Find video file\n  VIDEO=$(find test-results -name \"video.webm\" -type f | head -1)\n  echo \"Video: $VIDEO\"\nelse\n  echo \"Recording failed with exit code $EXIT_CODE\"\n  exit $EXIT_CODE\nfi\n```\n\n## Best Practices for Recording Specs\n\n1. **Use explicit waits** - Avoid flaky recordings\n   ```typescript\n   await page.waitForSelector('.element');\n   await page.waitForLoadState('networkidle');\n   ```\n\n2. **Add pauses for visibility** - Give viewers time to see actions\n   ```typescript\n   await page.waitForTimeout(500);\n   ```\n\n3. **Use slowMo** - Slow down all actions\n   ```typescript\n   launchOptions: { slowMo: 100 }\n   ```\n\n4. **Consistent viewport** - Match video size to viewport\n   ```typescript\n   viewport: { width: 1280, height: 720 },\n   video: { size: { width: 1280, height: 720 } }\n   ```\n\n5. **Disable retries** - One clean recording\n   ```typescript\n   retries: 0\n   ```\n\nFile v1.9.17:modules/video-capture.md\n\n# Video Capture Module\n\nVideo format options, quality settings, and post-processing for Playwright recordings.\n\n## Video Format\n\nPlaywright records video in **WebM** format with VP8 codec. This format:\n- Has good compression\n- Supports transparency (if needed)\n- Works well with ffmpeg for conversion\n- Is natively supported by most browsers\n\n## Resolution Settings\n\n### Common Resolutions\n\n| Resolution | Use Case | Aspect Ratio |\n|------------|----------|--------------|\n| 1920x1080 | Full HD, detailed demos | 16:9 |\n| 1280x720 | Standard tutorials | 16:9 |\n| 1024x768 | Compact demos | 4:3 |\n| 800x600 | Small GIF output | 4:3 |\n\n### Playwright Video Size Configuration\n\n```typescript\n// In playwright.config.ts\nuse: {\n  video: {\n    mode: 'on',\n    size: { width: 1280, height: 720 }\n  },\n  viewport: { width: 1280, height: 720 }\n}\n```\n\n**Important:** Match `video.size` to `viewport` for best quality.\n\n### Per-Test Video Settings\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  video: {\n    mode: 'on',\n    size: { width: 1920, height: 1080 }\n  },\n  viewport: { width: 1920, height: 1080 }\n});\n\ntest('high-res demo', async ({ page }) => {\n  // Test runs at 1080p\n});\n```\n\n## Quality Considerations\n\n### Frame Rate\n\nPlaywright records at approximately 25 fps. This is sufficient for UI demos.\n\n### Bitrate\n\nWebM videos from Playwright use variable bitrate. Typical sizes:\n- 720p, 30 seconds: 2-5 MB\n- 1080p, 30 seconds: 5-10 MB\n\n### Minimizing File Size\n\n1. **Smaller viewport** - Reduce dimensions\n2. **Shorter duration** - Trim unnecessary pauses\n3. **Simple animations** - Fewer visual changes = smaller file\n\n## Playwright Video Configuration in Tests\n\n### Enable Video for Specific Tests\n\n```typescript\nimport { test } from '@playwright/test';\n\n// Enable video for this test file\ntest.describe.configure({ mode: 'serial' });\n\ntest.use({\n  video: 'on',\n  viewport: { width: 1280, height: 720 }\n});\n\ntest('recorded demo', async ({ page }) => {\n  await page.goto('https://example.com');\n  await page.waitForTimeout(1000);\n});\n```\n\n### Conditional Recording\n\n```typescript\nimport { test } from '@playwright/test';\n\nconst RECORD = process.env.RECORD === 'true';\n\ntest.use({\n  video: RECORD ? 'on' : 'off'\n});\n\ntest('conditionally recorded', async ({ page }) => {\n  // Only records when RECORD=true\n});\n```\n\n### Custom Video Directory\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  contextOptions: {\n    recordVideo: {\n      dir: './custom-video-output',\n      size: { width: 1280, height: 720 }\n    }\n  }\n});\n```\n\n## Post-Processing with ffmpeg\n\n### Convert WebM to MP4\n\n```bash\nffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4\n```\n\n### Extract Specific Time Range\n\n```bash\n# Extract from 0:05 to 0:15\nffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm\n```\n\n### Change Resolution\n\n```bash\n# Scale to 800px width, maintain aspect ratio\nffmpeg -i video.webm -vf \"scale=800:-1\" scaled.webm\n```\n\n### Speed Up Video\n\n```bash\n# 2x speed\nffmpeg -i video.webm -filter:v \"setpts=0.5*PTS\" faster.webm\n```\n\n### Add Padding/Borders\n\n```bash\n# Add 10px black border\nffmpeg -i video.webm -vf \"pad=width+20:height+20:10:10:black\" padded.webm\n```\n\n### Combine Multiple Videos\n\n```bash\n# Create file list\necho \"file 'video1.webm'\" > list.txt\necho \"file 'video2.webm'\" >> list.txt\n\n# Concatenate\nffmpeg -f concat -safe 0 -i list.txt -c copy combined.webm\n```\n\n## Converting to GIF\n\nFor GIF conversion, use the `scry:gif-generation` skill which handles:\n- Palette generation for optimal colors\n- Frame rate reduction (10-15 fps typical)\n- Width scaling\n- Dithering for quality\n\nQuick ffmpeg conversion (basic):\n\n```bash\n# Simple conversion (larger file, lower quality)\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1\" output.gif\n\n# Better quality with palette\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" output.gif\n```\n\n## Troubleshooting\n\n### Video is black or frozen\n\n- validate page has visible content before recording starts\n- Add `await page.waitForLoadState('domcontentloaded')`\n- Check for CSS that hides content initially\n\n### Video cuts off early\n\n- Test might be finishing before video flushes\n- Add `await page.waitForTimeout(500)` at end of test\n- validate `await page.close()` is not called (Playwright handles cleanup)\n\n### Video too large\n\n- Reduce resolution\n- Shorten test duration\n- Use post-processing to compress\n\n### Choppy playback\n\n- Normal at high resolutions\n- Consider reducing to 720p\n- Final GIF will be smoother at lower fps\n\nFile v1.9.17:skill-card.md\n\n## Description: <br>\nRecords browser sessions via Playwright and converts video to GIF. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[athola](https://clawhub.ai/user/athola) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and documentation authors use this skill to automate browser interactions with Playwright, capture WebM recordings, and prepare GIF demos for tutorials or product documentation. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Browser recordings can capture secrets, personal data, or customer information visible in the session. <br>\nMitigation: Use demo accounts or sanitized test data, avoid entering secrets or production customer data during recording, and review generated WebM/GIF files before sharing. <br>\nRisk: Generated recording files may be retained or shared after the workflow completes. <br>\nMitigation: Review, redact, or delete generated WebM/GIF files according to the intended audience and retention requirements. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/athola/skills/nm-scry-browser-recording) <br>\n- [Source homepage](https://github.com/athola/claude-night-market/tree/master/plugins/scry) <br>\n- [Spec Execution Module](modules/spec-execution.md) <br>\n- [Video Capture Module](modules/video-capture.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown guidance with inline shell commands and TypeScript configuration snippets] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May identify generated WebM paths and provide GIF conversion guidance.] <br>\n\n## Skill Version(s): <br>\n1.9.17 (source: ClawHub release metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.9.16: 5 files, 7949 bytes\n\nFiles: modules/spec-execution.md (3911b), modules/video-capture.md (4559b), skill-card.md (2276b), SKILL.md (6459b), _meta.json (145b)\n\nFile v1.9.16:SKILL.md\n\n---\nname: browser-recording\ndescription: Records browser sessions via Playwright and converts video to GIF\nversion: 1.9.8\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\n  - creating web UI tutorials or demos showing browser interactions\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright --version\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nIf not installed, the user should run:\n```bash\nnpm install -D @playwright/test\nnpx playwright install chromium\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n### Step 2: Check Spec File\n\nVerify the Playwright spec file exists. Spec files should:\n- Be located in a `specs/` or `tests/` directory\n- Have `.spec.ts` or `.spec.js` extension\n- Include video configuration (see spec-execution module)\n\n### Step 3: Execute Recording\n\nRun the spec with video enabled:\n\n```bash\nnpx playwright test <spec-file> --config=playwright.config.ts\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\nThe config must enable video recording. See the spec-execution module for configuration details.\n\n### Step 4: Convert to GIF\n\nAfter recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:\n\n```\n**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Example Playwright Spec\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo workflow', async ({ page }) => {\n  // Navigate to the application\n  await page.goto('http://localhost:3000');\n\n  // Wait for page to be ready\n  await page.waitForLoadState('networkidle');\n\n  // Perform demo actions\n  await page.click('button[data-testid=\"start\"]');\n  await page.waitForTimeout(500); // Allow animation to complete\n\n  await page.fill('input[name=\"query\"]', 'example search');\n  await page.waitForTimeout(300);\n\n  await page.click('button[type=\"submit\"]');\n  await page.waitForSelector('.results');\n\n  // Final pause to show results\n  await page.waitForTimeout(1000);\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Playwright Configuration\n\nCreate or update `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: {\n      mode: 'on',\n      size: { width: 1280, height: 720 }\n    },\n    viewport: { width: 1280, height: 720 },\n    launchOptions: {\n      slowMo: 100 // Slow down actions for visibility\n    }\n  },\n  outputDir: './test-results',\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Exit Criteria\n\n- Playwright spec executed successfully (exit code 0)\n- Video file exists in output directory\n- Video has non-zero file size\n- GIF conversion completed (if requested)\n\n## Error Handling\n\n| Error | Resolution |\n|-------|------------|\n| Playwright not installed | Run `npm install -D @playwright/test` |\n| Browser not installed | Run `npx playwright install chromium` |\n| Spec file not found | Verify path and file extension |\n| Video not created | Check Playwright config has video enabled |\n| Empty video file | validate spec actions complete before test ends |\n\n## Output Locations\n\nDefault output paths:\n- Videos: `./test-results/<test-name>/video.webm`\n- Screenshots: `./test-results/<test-name>/screenshot.png`\n\n## Module Reference\n\n- See `modules/spec-execution.md` for detailed Playwright execution options\n- See `modules/video-capture.md` for video format and quality settings\n\n## See Also\n\n- scry:gif-generation: Convert video to optimized GIF\n\nFile v1.9.16:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-scry-browser-recording\",\n  \"version\": \"1.9.16\",\n  \"publishedAt\": 1784059168809\n}\n\nFile v1.9.16:modules/spec-execution.md\n\n# Spec Execution Module\n\nExecute Playwright specs with video recording enabled.\n\n## Playwright Configuration for Video\n\n### Minimal Config\n\nCreate `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: 'on',\n  },\n  outputDir: './test-results',\n});\n```\n\n### Full Recording Config\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: './specs',\n  outputDir: './test-results',\n\n  use: {\n    // Video settings\n    video: {\n      mode: 'on',           // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'\n      size: {\n        width: 1280,\n        height: 720\n      }\n    },\n\n    // Browser settings\n    viewport: { width: 1280, height: 720 },\n    headless: true,\n\n    // Slow down for visibility in recordings\n    launchOptions: {\n      slowMo: 100\n    },\n\n    // Browser context\n    contextOptions: {\n      recordVideo: {\n        dir: './test-results/videos',\n        size: { width: 1280, height: 720 }\n      }\n    }\n  },\n\n  // Disable retries for recording\n  retries: 0,\n\n  // Single worker for consistent recording\n  workers: 1,\n});\n```\n\n## Running Specs\n\n### Basic Execution\n\n```bash\nnpx playwright test specs/demo.spec.ts\n```\n\n### With Custom Config\n\n```bash\nnpx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts\n```\n\n### Common Options\n\n```bash\n# Run specific test by name\nnpx playwright test -g \"demo workflow\"\n\n# Run in headed mode (visible browser)\nnpx playwright test --headed\n\n# Use specific browser\nnpx playwright test --project=chromium\n\n# Set timeout\nnpx playwright test --timeout=60000\n\n# Output verbose logs\nnpx playwright test --debug\n```\n\n## Video Output Paths\n\nPlaywright creates videos at:\n```\n<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm\n```\n\nExample:\n```\ntest-results/demo-spec-ts-chromium/demo-workflow/video.webm\n```\n\n### Programmatic Video Path\n\nAccess video path in test:\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo', async ({ page }, testInfo) => {\n  // ... test actions ...\n\n  // After test, attach video path\n  const video = page.video();\n  if (video) {\n    const path = await video.path();\n    console.log('Video saved to:', path);\n  }\n});\n```\n\n## Error Handling\n\n### Common Issues\n\n**Browser not installed:**\n```bash\nnpx playwright install chromium\n```\n\n**Timeout errors:**\n```typescript\n// Increase action timeout\nawait page.click('button', { timeout: 10000 });\n\n// Or set global timeout in config\nuse: {\n  actionTimeout: 10000,\n}\n```\n\n**Video not created:**\n- validate `video: 'on'` in config\n- Check test actually runs (not skipped)\n- Verify outputDir is writable\n\n**Empty or corrupted video:**\n- Add `await page.waitForTimeout(500)` before test ends\n- validate page has loaded: `await page.waitForLoadState('networkidle')`\n\n### Exit Code Handling\n\n```bash\nnpx playwright test specs/demo.spec.ts\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"Recording completed successfully\"\n  # Find video file\n  VIDEO=$(find test-results -name \"video.webm\" -type f | head -1)\n  echo \"Video: $VIDEO\"\nelse\n  echo \"Recording failed with exit code $EXIT_CODE\"\n  exit $EXIT_CODE\nfi\n```\n\n## Best Practices for Recording Specs\n\n1. **Use explicit waits** - Avoid flaky recordings\n   ```typescript\n   await page.waitForSelector('.element');\n   await page.waitForLoadState('networkidle');\n   ```\n\n2. **Add pauses for visibility** - Give viewers time to see actions\n   ```typescript\n   await page.waitForTimeout(500);\n   ```\n\n3. **Use slowMo** - Slow down all actions\n   ```typescript\n   launchOptions: { slowMo: 100 }\n   ```\n\n4. **Consistent viewport** - Match video size to viewport\n   ```typescript\n   viewport: { width: 1280, height: 720 },\n   video: { size: { width: 1280, height: 720 } }\n   ```\n\n5. **Disable retries** - One clean recording\n   ```typescript\n   retries: 0\n   ```\n\nFile v1.9.16:modules/video-capture.md\n\n# Video Capture Module\n\nVideo format options, quality settings, and post-processing for Playwright recordings.\n\n## Video Format\n\nPlaywright records video in **WebM** format with VP8 codec. This format:\n- Has good compression\n- Supports transparency (if needed)\n- Works well with ffmpeg for conversion\n- Is natively supported by most browsers\n\n## Resolution Settings\n\n### Common Resolutions\n\n| Resolution | Use Case | Aspect Ratio |\n|------------|----------|--------------|\n| 1920x1080 | Full HD, detailed demos | 16:9 |\n| 1280x720 | Standard tutorials | 16:9 |\n| 1024x768 | Compact demos | 4:3 |\n| 800x600 | Small GIF output | 4:3 |\n\n### Playwright Video Size Configuration\n\n```typescript\n// In playwright.config.ts\nuse: {\n  video: {\n    mode: 'on',\n    size: { width: 1280, height: 720 }\n  },\n  viewport: { width: 1280, height: 720 }\n}\n```\n\n**Important:** Match `video.size` to `viewport` for best quality.\n\n### Per-Test Video Settings\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  video: {\n    mode: 'on',\n    size: { width: 1920, height: 1080 }\n  },\n  viewport: { width: 1920, height: 1080 }\n});\n\ntest('high-res demo', async ({ page }) => {\n  // Test runs at 1080p\n});\n```\n\n## Quality Considerations\n\n### Frame Rate\n\nPlaywright records at approximately 25 fps. This is sufficient for UI demos.\n\n### Bitrate\n\nWebM videos from Playwright use variable bitrate. Typical sizes:\n- 720p, 30 seconds: 2-5 MB\n- 1080p, 30 seconds: 5-10 MB\n\n### Minimizing File Size\n\n1. **Smaller viewport** - Reduce dimensions\n2. **Shorter duration** - Trim unnecessary pauses\n3. **Simple animations** - Fewer visual changes = smaller file\n\n## Playwright Video Configuration in Tests\n\n### Enable Video for Specific Tests\n\n```typescript\nimport { test } from '@playwright/test';\n\n// Enable video for this test file\ntest.describe.configure({ mode: 'serial' });\n\ntest.use({\n  video: 'on',\n  viewport: { width: 1280, height: 720 }\n});\n\ntest('recorded demo', async ({ page }) => {\n  await page.goto('https://example.com');\n  await page.waitForTimeout(1000);\n});\n```\n\n### Conditional Recording\n\n```typescript\nimport { test } from '@playwright/test';\n\nconst RECORD = process.env.RECORD === 'true';\n\ntest.use({\n  video: RECORD ? 'on' : 'off'\n});\n\ntest('conditionally recorded', async ({ page }) => {\n  // Only records when RECORD=true\n});\n```\n\n### Custom Video Directory\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  contextOptions: {\n    recordVideo: {\n      dir: './custom-video-output',\n      size: { width: 1280, height: 720 }\n    }\n  }\n});\n```\n\n## Post-Processing with ffmpeg\n\n### Convert WebM to MP4\n\n```bash\nffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4\n```\n\n### Extract Specific Time Range\n\n```bash\n# Extract from 0:05 to 0:15\nffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm\n```\n\n### Change Resolution\n\n```bash\n# Scale to 800px width, maintain aspect ratio\nffmpeg -i video.webm -vf \"scale=800:-1\" scaled.webm\n```\n\n### Speed Up Video\n\n```bash\n# 2x speed\nffmpeg -i video.webm -filter:v \"setpts=0.5*PTS\" faster.webm\n```\n\n### Add Padding/Borders\n\n```bash\n# Add 10px black border\nffmpeg -i video.webm -vf \"pad=width+20:height+20:10:10:black\" padded.webm\n```\n\n### Combine Multiple Videos\n\n```bash\n# Create file list\necho \"file 'video1.webm'\" > list.txt\necho \"file 'video2.webm'\" >> list.txt\n\n# Concatenate\nffmpeg -f concat -safe 0 -i list.txt -c copy combined.webm\n```\n\n## Converting to GIF\n\nFor GIF conversion, use the `scry:gif-generation` skill which handles:\n- Palette generation for optimal colors\n- Frame rate reduction (10-15 fps typical)\n- Width scaling\n- Dithering for quality\n\nQuick ffmpeg conversion (basic):\n\n```bash\n# Simple conversion (larger file, lower quality)\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1\" output.gif\n\n# Better quality with palette\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" output.gif\n```\n\n## Troubleshooting\n\n### Video is black or frozen\n\n- validate page has visible content before recording starts\n- Add `await page.waitForLoadState('domcontentloaded')`\n- Check for CSS that hides content initially\n\n### Video cuts off early\n\n- Test might be finishing before video flushes\n- Add `await page.waitForTimeout(500)` at end of test\n- validate `await page.close()` is not called (Playwright handles cleanup)\n\n### Video too large\n\n- Reduce resolution\n- Shorten test duration\n- Use post-processing to compress\n\n### Choppy playback\n\n- Normal at high resolutions\n- Consider reducing to 720p\n- Final GIF will be smoother at lower fps\n\nFile v1.9.16:skill-card.md\n\n## Description: <br>\nRecords browser sessions via Playwright and converts video to GIF. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[athola](https://clawhub.ai/user/athola) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and engineers use this skill to record automated browser interactions with Playwright for UI demos, tutorials, and documentation, then locate WebM output and convert it to GIF when needed. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Browser recordings may capture sensitive page content and are saved to disk as WebM or GIF files. <br>\nMitigation: Use test accounts and sanitized data, store generated recordings in an appropriate location, and review videos before sharing. <br>\nRisk: Automated browser specs can exercise live web applications and create misleading demos if pages are not fully loaded or actions are flaky. <br>\nMitigation: Use explicit waits, stable test data, and validate the generated recording before using it as documentation or a tutorial asset. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/athola/skills/nm-scry-browser-recording) <br>\n- [Source homepage](https://github.com/athola/claude-night-market/tree/master/plugins/scry) <br>\n- [Spec execution module](modules/spec-execution.md) <br>\n- [Video capture module](modules/video-capture.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [guidance, markdown, code, shell commands, configuration] <br>\n**Output Format:** [Markdown guidance with bash and TypeScript code blocks] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Produces Playwright commands, configuration examples, and output path guidance; recordings are WebM files that may be converted to GIF by a dependent gif-generation skill.] <br>\n\n## Skill Version(s): <br>\n1.9.16 (source: ClawHub release evidence; artifact frontmatter reports 1.9.8) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.9.14: 5 files, 7853 bytes\n\nFiles: modules/spec-execution.md (3911b), modules/video-capture.md (4559b), skill-card.md (2058b), SKILL.md (6459b), _meta.json (145b)\n\nFile v1.9.14:SKILL.md\n\n---\nname: browser-recording\ndescription: Records browser sessions via Playwright and converts video to GIF\nversion: 1.9.8\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\n  - creating web UI tutorials or demos showing browser interactions\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright --version\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nIf not installed, the user should run:\n```bash\nnpm install -D @playwright/test\nnpx playwright install chromium\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n### Step 2: Check Spec File\n\nVerify the Playwright spec file exists. Spec files should:\n- Be located in a `specs/` or `tests/` directory\n- Have `.spec.ts` or `.spec.js` extension\n- Include video configuration (see spec-execution module)\n\n### Step 3: Execute Recording\n\nRun the spec with video enabled:\n\n```bash\nnpx playwright test <spec-file> --config=playwright.config.ts\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\nThe config must enable video recording. See the spec-execution module for configuration details.\n\n### Step 4: Convert to GIF\n\nAfter recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:\n\n```\n**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Example Playwright Spec\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo workflow', async ({ page }) => {\n  // Navigate to the application\n  await page.goto('http://localhost:3000');\n\n  // Wait for page to be ready\n  await page.waitForLoadState('networkidle');\n\n  // Perform demo actions\n  await page.click('button[data-testid=\"start\"]');\n  await page.waitForTimeout(500); // Allow animation to complete\n\n  await page.fill('input[name=\"query\"]', 'example search');\n  await page.waitForTimeout(300);\n\n  await page.click('button[type=\"submit\"]');\n  await page.waitForSelector('.results');\n\n  // Final pause to show results\n  await page.waitForTimeout(1000);\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Playwright Configuration\n\nCreate or update `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: {\n      mode: 'on',\n      size: { width: 1280, height: 720 }\n    },\n    viewport: { width: 1280, height: 720 },\n    launchOptions: {\n      slowMo: 100 // Slow down actions for visibility\n    }\n  },\n  outputDir: './test-results',\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Exit Criteria\n\n- Playwright spec executed successfully (exit code 0)\n- Video file exists in output directory\n- Video has non-zero file size\n- GIF conversion completed (if requested)\n\n## Error Handling\n\n| Error | Resolution |\n|-------|------------|\n| Playwright not installed | Run `npm install -D @playwright/test` |\n| Browser not installed | Run `npx playwright install chromium` |\n| Spec file not found | Verify path and file extension |\n| Video not created | Check Playwright config has video enabled |\n| Empty video file | validate spec actions complete before test ends |\n\n## Output Locations\n\nDefault output paths:\n- Videos: `./test-results/<test-name>/video.webm`\n- Screenshots: `./test-results/<test-name>/screenshot.png`\n\n## Module Reference\n\n- See `modules/spec-execution.md` for detailed Playwright execution options\n- See `modules/video-capture.md` for video format and quality settings\n\n## See Also\n\n- scry:gif-generation: Convert video to optimized GIF\n\nFile v1.9.14:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-scry-browser-recording\",\n  \"version\": \"1.9.14\",\n  \"publishedAt\": 1782842815013\n}\n\nFile v1.9.14:modules/spec-execution.md\n\n# Spec Execution Module\n\nExecute Playwright specs with video recording enabled.\n\n## Playwright Configuration for Video\n\n### Minimal Config\n\nCreate `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: 'on',\n  },\n  outputDir: './test-results',\n});\n```\n\n### Full Recording Config\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: './specs',\n  outputDir: './test-results',\n\n  use: {\n    // Video settings\n    video: {\n      mode: 'on',           // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'\n      size: {\n        width: 1280,\n        height: 720\n      }\n    },\n\n    // Browser settings\n    viewport: { width: 1280, height: 720 },\n    headless: true,\n\n    // Slow down for visibility in recordings\n    launchOptions: {\n      slowMo: 100\n    },\n\n    // Browser context\n    contextOptions: {\n      recordVideo: {\n        dir: './test-results/videos',\n        size: { width: 1280, height: 720 }\n      }\n    }\n  },\n\n  // Disable retries for recording\n  retries: 0,\n\n  // Single worker for consistent recording\n  workers: 1,\n});\n```\n\n## Running Specs\n\n### Basic Execution\n\n```bash\nnpx playwright test specs/demo.spec.ts\n```\n\n### With Custom Config\n\n```bash\nnpx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts\n```\n\n### Common Options\n\n```bash\n# Run specific test by name\nnpx playwright test -g \"demo workflow\"\n\n# Run in headed mode (visible browser)\nnpx playwright test --headed\n\n# Use specific browser\nnpx playwright test --project=chromium\n\n# Set timeout\nnpx playwright test --timeout=60000\n\n# Output verbose logs\nnpx playwright test --debug\n```\n\n## Video Output Paths\n\nPlaywright creates videos at:\n```\n<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm\n```\n\nExample:\n```\ntest-results/demo-spec-ts-chromium/demo-workflow/video.webm\n```\n\n### Programmatic Video Path\n\nAccess video path in test:\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo', async ({ page }, testInfo) => {\n  // ... test actions ...\n\n  // After test, attach video path\n  const video = page.video();\n  if (video) {\n    const path = await video.path();\n    console.log('Video saved to:', path);\n  }\n});\n```\n\n## Error Handling\n\n### Common Issues\n\n**Browser not installed:**\n```bash\nnpx playwright install chromium\n```\n\n**Timeout errors:**\n```typescript\n// Increase action timeout\nawait page.click('button', { timeout: 10000 });\n\n// Or set global timeout in config\nuse: {\n  actionTimeout: 10000,\n}\n```\n\n**Video not created:**\n- validate `video: 'on'` in config\n- Check test actually runs (not skipped)\n- Verify outputDir is writable\n\n**Empty or corrupted video:**\n- Add `await page.waitForTimeout(500)` before test ends\n- validate page has loaded: `await page.waitForLoadState('networkidle')`\n\n### Exit Code Handling\n\n```bash\nnpx playwright test specs/demo.spec.ts\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"Recording completed successfully\"\n  # Find video file\n  VIDEO=$(find test-results -name \"video.webm\" -type f | head -1)\n  echo \"Video: $VIDEO\"\nelse\n  echo \"Recording failed with exit code $EXIT_CODE\"\n  exit $EXIT_CODE\nfi\n```\n\n## Best Practices for Recording Specs\n\n1. **Use explicit waits** - Avoid flaky recordings\n   ```typescript\n   await page.waitForSelector('.element');\n   await page.waitForLoadState('networkidle');\n   ```\n\n2. **Add pauses for visibility** - Give viewers time to see actions\n   ```typescript\n   await page.waitForTimeout(500);\n   ```\n\n3. **Use slowMo** - Slow down all actions\n   ```typescript\n   launchOptions: { slowMo: 100 }\n   ```\n\n4. **Consistent viewport** - Match video size to viewport\n   ```typescript\n   viewport: { width: 1280, height: 720 },\n   video: { size: { width: 1280, height: 720 } }\n   ```\n\n5. **Disable retries** - One clean recording\n   ```typescript\n   retries: 0\n   ```\n\nFile v1.9.14:modules/video-capture.md\n\n# Video Capture Module\n\nVideo format options, quality settings, and post-processing for Playwright recordings.\n\n## Video Format\n\nPlaywright records video in **WebM** format with VP8 codec. This format:\n- Has good compression\n- Supports transparency (if needed)\n- Works well with ffmpeg for conversion\n- Is natively supported by most browsers\n\n## Resolution Settings\n\n### Common Resolutions\n\n| Resolution | Use Case | Aspect Ratio |\n|------------|----------|--------------|\n| 1920x1080 | Full HD, detailed demos | 16:9 |\n| 1280x720 | Standard tutorials | 16:9 |\n| 1024x768 | Compact demos | 4:3 |\n| 800x600 | Small GIF output | 4:3 |\n\n### Playwright Video Size Configuration\n\n```typescript\n// In playwright.config.ts\nuse: {\n  video: {\n    mode: 'on',\n    size: { width: 1280, height: 720 }\n  },\n  viewport: { width: 1280, height: 720 }\n}\n```\n\n**Important:** Match `video.size` to `viewport` for best quality.\n\n### Per-Test Video Settings\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  video: {\n    mode: 'on',\n    size: { width: 1920, height: 1080 }\n  },\n  viewport: { width: 1920, height: 1080 }\n});\n\ntest('high-res demo', async ({ page }) => {\n  // Test runs at 1080p\n});\n```\n\n## Quality Considerations\n\n### Frame Rate\n\nPlaywright records at approximately 25 fps. This is sufficient for UI demos.\n\n### Bitrate\n\nWebM videos from Playwright use variable bitrate. Typical sizes:\n- 720p, 30 seconds: 2-5 MB\n- 1080p, 30 seconds: 5-10 MB\n\n### Minimizing File Size\n\n1. **Smaller viewport** - Reduce dimensions\n2. **Shorter duration** - Trim unnecessary pauses\n3. **Simple animations** - Fewer visual changes = smaller file\n\n## Playwright Video Configuration in Tests\n\n### Enable Video for Specific Tests\n\n```typescript\nimport { test } from '@playwright/test';\n\n// Enable video for this test file\ntest.describe.configure({ mode: 'serial' });\n\ntest.use({\n  video: 'on',\n  viewport: { width: 1280, height: 720 }\n});\n\ntest('recorded demo', async ({ page }) => {\n  await page.goto('https://example.com');\n  await page.waitForTimeout(1000);\n});\n```\n\n### Conditional Recording\n\n```typescript\nimport { test } from '@playwright/test';\n\nconst RECORD = process.env.RECORD === 'true';\n\ntest.use({\n  video: RECORD ? 'on' : 'off'\n});\n\ntest('conditionally recorded', async ({ page }) => {\n  // Only records when RECORD=true\n});\n```\n\n### Custom Video Directory\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  contextOptions: {\n    recordVideo: {\n      dir: './custom-video-output',\n      size: { width: 1280, height: 720 }\n    }\n  }\n});\n```\n\n## Post-Processing with ffmpeg\n\n### Convert WebM to MP4\n\n```bash\nffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4\n```\n\n### Extract Specific Time Range\n\n```bash\n# Extract from 0:05 to 0:15\nffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm\n```\n\n### Change Resolution\n\n```bash\n# Scale to 800px width, maintain aspect ratio\nffmpeg -i video.webm -vf \"scale=800:-1\" scaled.webm\n```\n\n### Speed Up Video\n\n```bash\n# 2x speed\nffmpeg -i video.webm -filter:v \"setpts=0.5*PTS\" faster.webm\n```\n\n### Add Padding/Borders\n\n```bash\n# Add 10px black border\nffmpeg -i video.webm -vf \"pad=width+20:height+20:10:10:black\" padded.webm\n```\n\n### Combine Multiple Videos\n\n```bash\n# Create file list\necho \"file 'video1.webm'\" > list.txt\necho \"file 'video2.webm'\" >> list.txt\n\n# Concatenate\nffmpeg -f concat -safe 0 -i list.txt -c copy combined.webm\n```\n\n## Converting to GIF\n\nFor GIF conversion, use the `scry:gif-generation` skill which handles:\n- Palette generation for optimal colors\n- Frame rate reduction (10-15 fps typical)\n- Width scaling\n- Dithering for quality\n\nQuick ffmpeg conversion (basic):\n\n```bash\n# Simple conversion (larger file, lower quality)\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1\" output.gif\n\n# Better quality with palette\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" output.gif\n```\n\n## Troubleshooting\n\n### Video is black or frozen\n\n- validate page has visible content before recording starts\n- Add `await page.waitForLoadState('domcontentloaded')`\n- Check for CSS that hides content initially\n\n### Video cuts off early\n\n- Test might be finishing before video flushes\n- Add `await page.waitForTimeout(500)` at end of test\n- validate `await page.close()` is not called (Playwright handles cleanup)\n\n### Video too large\n\n- Reduce resolution\n- Shorten test duration\n- Use post-processing to compress\n\n### Choppy playback\n\n- Normal at high resolutions\n- Consider reducing to 720p\n- Final GIF will be smoother at lower fps\n\nFile v1.9.14:skill-card.md\n\n## Description: <br>\nRecords browser sessions via Playwright and converts video to GIF. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[athola](https://clawhub.ai/user/athola) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and technical writers use this skill to automate Playwright browser sessions, capture WebM recordings of web UI workflows, and prepare GIFs for tutorials or documentation. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Browser recordings may capture login pages, payment flows, customer data, or other sensitive on-screen information. <br>\nMitigation: Use test accounts or sanitized environments, avoid sensitive flows, and review generated videos and GIFs before sharing. <br>\nRisk: Generated recordings may persist after the documentation task is complete. <br>\nMitigation: Delete generated media when it is no longer needed. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/athola/skills/nm-scry-browser-recording) <br>\n- [clawdis homepage](https://github.com/athola/claude-night-market/tree/master/plugins/scry) <br>\n- [Spec Execution Module](modules/spec-execution.md) <br>\n- [Video Capture Module](modules/video-capture.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Shell commands, Configuration, Code, Guidance] <br>\n**Output Format:** [Markdown with inline bash and TypeScript code blocks] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Guides Playwright video capture and optional GIF conversion; generated media should be reviewed before sharing.] <br>\n\n## Skill Version(s): <br>\n1.9.14 (source: server release metadata; artifact frontmatter reports 1.9.8) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.9.13: 5 files, 7856 bytes\n\nFiles: modules/spec-execution.md (3911b), modules/video-capture.md (4559b), skill-card.md (2039b), SKILL.md (6459b), _meta.json (145b)\n\nFile v1.9.13:SKILL.md\n\n---\nname: browser-recording\ndescription: Records browser sessions via Playwright and converts video to GIF\nversion: 1.9.8\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\n  - creating web UI tutorials or demos showing browser interactions\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright --version\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nIf not installed, the user should run:\n```bash\nnpm install -D @playwright/test\nnpx playwright install chromium\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n### Step 2: Check Spec File\n\nVerify the Playwright spec file exists. Spec files should:\n- Be located in a `specs/` or `tests/` directory\n- Have `.spec.ts` or `.spec.js` extension\n- Include video configuration (see spec-execution module)\n\n### Step 3: Execute Recording\n\nRun the spec with video enabled:\n\n```bash\nnpx playwright test <spec-file> --config=playwright.config.ts\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\nThe config must enable video recording. See the spec-execution module for configuration details.\n\n### Step 4: Convert to GIF\n\nAfter recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:\n\n```\n**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Example Playwright Spec\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo workflow', async ({ page }) => {\n  // Navigate to the application\n  await page.goto('http://localhost:3000');\n\n  // Wait for page to be ready\n  await page.waitForLoadState('networkidle');\n\n  // Perform demo actions\n  await page.click('button[data-testid=\"start\"]');\n  await page.waitForTimeout(500); // Allow animation to complete\n\n  await page.fill('input[name=\"query\"]', 'example search');\n  await page.waitForTimeout(300);\n\n  await page.click('button[type=\"submit\"]');\n  await page.waitForSelector('.results');\n\n  // Final pause to show results\n  await page.waitForTimeout(1000);\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Playwright Configuration\n\nCreate or update `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: {\n      mode: 'on',\n      size: { width: 1280, height: 720 }\n    },\n    viewport: { width: 1280, height: 720 },\n    launchOptions: {\n      slowMo: 100 // Slow down actions for visibility\n    }\n  },\n  outputDir: './test-results',\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Exit Criteria\n\n- Playwright spec executed successfully (exit code 0)\n- Video file exists in output directory\n- Video has non-zero file size\n- GIF conversion completed (if requested)\n\n## Error Handling\n\n| Error | Resolution |\n|-------|------------|\n| Playwright not installed | Run `npm install -D @playwright/test` |\n| Browser not installed | Run `npx playwright install chromium` |\n| Spec file not found | Verify path and file extension |\n| Video not created | Check Playwright config has video enabled |\n| Empty video file | validate spec actions complete before test ends |\n\n## Output Locations\n\nDefault output paths:\n- Videos: `./test-results/<test-name>/video.webm`\n- Screenshots: `./test-results/<test-name>/screenshot.png`\n\n## Module Reference\n\n- See `modules/spec-execution.md` for detailed Playwright execution options\n- See `modules/video-capture.md` for video format and quality settings\n\n## See Also\n\n- scry:gif-generation: Convert video to optimized GIF\n\nFile v1.9.13:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-scry-browser-recording\",\n  \"version\": \"1.9.13\",\n  \"publishedAt\": 1782577487231\n}\n\nFile v1.9.13:modules/spec-execution.md\n\n# Spec Execution Module\n\nExecute Playwright specs with video recording enabled.\n\n## Playwright Configuration for Video\n\n### Minimal Config\n\nCreate `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: 'on',\n  },\n  outputDir: './test-results',\n});\n```\n\n### Full Recording Config\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: './specs',\n  outputDir: './test-results',\n\n  use: {\n    // Video settings\n    video: {\n      mode: 'on',           // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'\n      size: {\n        width: 1280,\n        height: 720\n      }\n    },\n\n    // Browser settings\n    viewport: { width: 1280, height: 720 },\n    headless: true,\n\n    // Slow down for visibility in recordings\n    launchOptions: {\n      slowMo: 100\n    },\n\n    // Browser context\n    contextOptions: {\n      recordVideo: {\n        dir: './test-results/videos',\n        size: { width: 1280, height: 720 }\n      }\n    }\n  },\n\n  // Disable retries for recording\n  retries: 0,\n\n  // Single worker for consistent recording\n  workers: 1,\n});\n```\n\n## Running Specs\n\n### Basic Execution\n\n```bash\nnpx playwright test specs/demo.spec.ts\n```\n\n### With Custom Config\n\n```bash\nnpx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts\n```\n\n### Common Options\n\n```bash\n# Run specific test by name\nnpx playwright test -g \"demo workflow\"\n\n# Run in headed mode (visible browser)\nnpx playwright test --headed\n\n# Use specific browser\nnpx playwright test --project=chromium\n\n# Set timeout\nnpx playwright test --timeout=60000\n\n# Output verbose logs\nnpx playwright test --debug\n```\n\n## Video Output Paths\n\nPlaywright creates videos at:\n```\n<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm\n```\n\nExample:\n```\ntest-results/demo-spec-ts-chromium/demo-workflow/video.webm\n```\n\n### Programmatic Video Path\n\nAccess video path in test:\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo', async ({ page }, testInfo) => {\n  // ... test actions ...\n\n  // After test, attach video path\n  const video = page.video();\n  if (video) {\n    const path = await video.path();\n    console.log('Video saved to:', path);\n  }\n});\n```\n\n## Error Handling\n\n### Common Issues\n\n**Browser not installed:**\n```bash\nnpx playwright install chromium\n```\n\n**Timeout errors:**\n```typescript\n// Increase action timeout\nawait page.click('button', { timeout: 10000 });\n\n// Or set global timeout in config\nuse: {\n  actionTimeout: 10000,\n}\n```\n\n**Video not created:**\n- validate `video: 'on'` in config\n- Check test actually runs (not skipped)\n- Verify outputDir is writable\n\n**Empty or corrupted video:**\n- Add `await page.waitForTimeout(500)` before test ends\n- validate page has loaded: `await page.waitForLoadState('networkidle')`\n\n### Exit Code Handling\n\n```bash\nnpx playwright test specs/demo.spec.ts\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"Recording completed successfully\"\n  # Find video file\n  VIDEO=$(find test-results -name \"video.webm\" -type f | head -1)\n  echo \"Video: $VIDEO\"\nelse\n  echo \"Recording failed with exit code $EXIT_CODE\"\n  exit $EXIT_CODE\nfi\n```\n\n## Best Practices for Recording Specs\n\n1. **Use explicit waits** - Avoid flaky recordings\n   ```typescript\n   await page.waitForSelector('.element');\n   await page.waitForLoadState('networkidle');\n   ```\n\n2. **Add pauses for visibility** - Give viewers time to see actions\n   ```typescript\n   await page.waitForTimeout(500);\n   ```\n\n3. **Use slowMo** - Slow down all actions\n   ```typescript\n   launchOptions: { slowMo: 100 }\n   ```\n\n4. **Consistent viewport** - Match video size to viewport\n   ```typescript\n   viewport: { width: 1280, height: 720 },\n   video: { size: { width: 1280, height: 720 } }\n   ```\n\n5. **Disable retries** - One clean recording\n   ```typescript\n   retries: 0\n   ```\n\nFile v1.9.13:modules/video-capture.md\n\n# Video Capture Module\n\nVideo format options, quality settings, and post-processing for Playwright recordings.\n\n## Video Format\n\nPlaywright records video in **WebM** format with VP8 codec. This format:\n- Has good compression\n- Supports transparency (if needed)\n- Works well with ffmpeg for conversion\n- Is natively supported by most browsers\n\n## Resolution Settings\n\n### Common Resolutions\n\n| Resolution | Use Case | Aspect Ratio |\n|------------|----------|--------------|\n| 1920x1080 | Full HD, detailed demos | 16:9 |\n| 1280x720 | Standard tutorials | 16:9 |\n| 1024x768 | Compact demos | 4:3 |\n| 800x600 | Small GIF output | 4:3 |\n\n### Playwright Video Size Configuration\n\n```typescript\n// In playwright.config.ts\nuse: {\n  video: {\n    mode: 'on',\n    size: { width: 1280, height: 720 }\n  },\n  viewport: { width: 1280, height: 720 }\n}\n```\n\n**Important:** Match `video.size` to `viewport` for best quality.\n\n### Per-Test Video Settings\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  video: {\n    mode: 'on',\n    size: { width: 1920, height: 1080 }\n  },\n  viewport: { width: 1920, height: 1080 }\n});\n\ntest('high-res demo', async ({ page }) => {\n  // Test runs at 1080p\n});\n```\n\n## Quality Considerations\n\n### Frame Rate\n\nPlaywright records at approximately 25 fps. This is sufficient for UI demos.\n\n### Bitrate\n\nWebM videos from Playwright use variable bitrate. Typical sizes:\n- 720p, 30 seconds: 2-5 MB\n- 1080p, 30 seconds: 5-10 MB\n\n### Minimizing File Size\n\n1. **Smaller viewport** - Reduce dimensions\n2. **Shorter duration** - Trim unnecessary pauses\n3. **Simple animations** - Fewer visual changes = smaller file\n\n## Playwright Video Configuration in Tests\n\n### Enable Video for Specific Tests\n\n```typescript\nimport { test } from '@playwright/test';\n\n// Enable video for this test file\ntest.describe.configure({ mode: 'serial' });\n\ntest.use({\n  video: 'on',\n  viewport: { width: 1280, height: 720 }\n});\n\ntest('recorded demo', async ({ page }) => {\n  await page.goto('https://example.com');\n  await page.waitForTimeout(1000);\n});\n```\n\n### Conditional Recording\n\n```typescript\nimport { test } from '@playwright/test';\n\nconst RECORD = process.env.RECORD === 'true';\n\ntest.use({\n  video: RECORD ? 'on' : 'off'\n});\n\ntest('conditionally recorded', async ({ page }) => {\n  // Only records when RECORD=true\n});\n```\n\n### Custom Video Directory\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  contextOptions: {\n    recordVideo: {\n      dir: './custom-video-output',\n      size: { width: 1280, height: 720 }\n    }\n  }\n});\n```\n\n## Post-Processing with ffmpeg\n\n### Convert WebM to MP4\n\n```bash\nffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4\n```\n\n### Extract Specific Time Range\n\n```bash\n# Extract from 0:05 to 0:15\nffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm\n```\n\n### Change Resolution\n\n```bash\n# Scale to 800px width, maintain aspect ratio\nffmpeg -i video.webm -vf \"scale=800:-1\" scaled.webm\n```\n\n### Speed Up Video\n\n```bash\n# 2x speed\nffmpeg -i video.webm -filter:v \"setpts=0.5*PTS\" faster.webm\n```\n\n### Add Padding/Borders\n\n```bash\n# Add 10px black border\nffmpeg -i video.webm -vf \"pad=width+20:height+20:10:10:black\" padded.webm\n```\n\n### Combine Multiple Videos\n\n```bash\n# Create file list\necho \"file 'video1.webm'\" > list.txt\necho \"file 'video2.webm'\" >> list.txt\n\n# Concatenate\nffmpeg -f concat -safe 0 -i list.txt -c copy combined.webm\n```\n\n## Converting to GIF\n\nFor GIF conversion, use the `scry:gif-generation` skill which handles:\n- Palette generation for optimal colors\n- Frame rate reduction (10-15 fps typical)\n- Width scaling\n- Dithering for quality\n\nQuick ffmpeg conversion (basic):\n\n```bash\n# Simple conversion (larger file, lower quality)\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1\" output.gif\n\n# Better quality with palette\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" output.gif\n```\n\n## Troubleshooting\n\n### Video is black or frozen\n\n- validate page has visible content before recording starts\n- Add `await page.waitForLoadState('domcontentloaded')`\n- Check for CSS that hides content initially\n\n### Video cuts off early\n\n- Test might be finishing before video flushes\n- Add `await page.waitForTimeout(500)` at end of test\n- validate `await page.close()` is not called (Playwright handles cleanup)\n\n### Video too large\n\n- Reduce resolution\n- Shorten test duration\n- Use post-processing to compress\n\n### Choppy playback\n\n- Normal at high resolutions\n- Consider reducing to 720p\n- Final GIF will be smoother at lower fps\n\nFile v1.9.13:skill-card.md\n\n## Description: <br>\nRecords browser sessions via Playwright and converts video to GIF. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[athola](https://clawhub.ai/user/athola) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and documentation teams use this skill to run Playwright-based browser recordings for web UI tutorials and demos, locate WebM output, and convert recordings to GIF when needed. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Browser recordings can capture sensitive application data and save WebM or GIF artifacts locally. <br>\nMitigation: Use sanitized test accounts and non-production data, review generated media before sharing, and delete output directories when no longer needed. <br>\nRisk: The skill is intended for explicit browser demo recording tasks and may be overly broad if invoked for unrelated browser work. <br>\nMitigation: Invoke it only for deliberate recording workflows and narrow triggers or task wording where possible. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/athola/skills/nm-scry-browser-recording) <br>\n- [Metadata homepage](https://github.com/athola/claude-night-market/tree/master/plugins/scry) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [guidance, shell commands, configuration, code] <br>\n**Output Format:** [Markdown guidance with shell command and TypeScript examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Guides the agent through Playwright validation, recording execution, WebM output discovery, and optional GIF conversion.] <br>\n\n## Skill Version(s): <br>\n1.9.13 (source: server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.9.12: 5 files, 7952 bytes\n\nFiles: modules/spec-execution.md (3911b), modules/video-capture.md (4559b), skill-card.md (2229b), SKILL.md (6459b), _meta.json (145b)\n\nFile v1.9.12:SKILL.md\n\n---\nname: browser-recording\ndescription: Records browser sessions via Playwright and converts video to GIF\nversion: 1.9.8\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\n  - creating web UI tutorials or demos showing browser interactions\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright --version\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nIf not installed, the user should run:\n```bash\nnpm install -D @playwright/test\nnpx playwright install chromium\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n### Step 2: Check Spec File\n\nVerify the Playwright spec file exists. Spec files should:\n- Be located in a `specs/` or `tests/` directory\n- Have `.spec.ts` or `.spec.js` extension\n- Include video configuration (see spec-execution module)\n\n### Step 3: Execute Recording\n\nRun the spec with video enabled:\n\n```bash\nnpx playwright test <spec-file> --config=playwright.config.ts\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\nThe config must enable video recording. See the spec-execution module for configuration details.\n\n### Step 4: Convert to GIF\n\nAfter recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:\n\n```\n**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Example Playwright Spec\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo workflow', async ({ page }) => {\n  // Navigate to the application\n  await page.goto('http://localhost:3000');\n\n  // Wait for page to be ready\n  await page.waitForLoadState('networkidle');\n\n  // Perform demo actions\n  await page.click('button[data-testid=\"start\"]');\n  await page.waitForTimeout(500); // Allow animation to complete\n\n  await page.fill('input[name=\"query\"]', 'example search');\n  await page.waitForTimeout(300);\n\n  await page.click('button[type=\"submit\"]');\n  await page.waitForSelector('.results');\n\n  // Final pause to show results\n  await page.waitForTimeout(1000);\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Playwright Configuration\n\nCreate or update `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: {\n      mode: 'on',\n      size: { width: 1280, height: 720 }\n    },\n    viewport: { width: 1280, height: 720 },\n    launchOptions: {\n      slowMo: 100 // Slow down actions for visibility\n    }\n  },\n  outputDir: './test-results',\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Exit Criteria\n\n- Playwright spec executed successfully (exit code 0)\n- Video file exists in output directory\n- Video has non-zero file size\n- GIF conversion completed (if requested)\n\n## Error Handling\n\n| Error | Resolution |\n|-------|------------|\n| Playwright not installed | Run `npm install -D @playwright/test` |\n| Browser not installed | Run `npx playwright install chromium` |\n| Spec file not found | Verify path and file extension |\n| Video not created | Check Playwright config has video enabled |\n| Empty video file | validate spec actions complete before test ends |\n\n## Output Locations\n\nDefault output paths:\n- Videos: `./test-results/<test-name>/video.webm`\n- Screenshots: `./test-results/<test-name>/screenshot.png`\n\n## Module Reference\n\n- See `modules/spec-execution.md` for detailed Playwright execution options\n- See `modules/video-capture.md` for video format and quality settings\n\n## See Also\n\n- scry:gif-generation: Convert video to optimized GIF\n\nFile v1.9.12:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-scry-browser-recording\",\n  \"version\": \"1.9.12\",\n  \"publishedAt\": 1781839232124\n}\n\nFile v1.9.12:modules/spec-execution.md\n\n# Spec Execution Module\n\nExecute Playwright specs with video recording enabled.\n\n## Playwright Configuration for Video\n\n### Minimal Config\n\nCreate `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: 'on',\n  },\n  outputDir: './test-results',\n});\n```\n\n### Full Recording Config\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: './specs',\n  outputDir: './test-results',\n\n  use: {\n    // Video settings\n    video: {\n      mode: 'on',           // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'\n      size: {\n        width: 1280,\n        height: 720\n      }\n    },\n\n    // Browser settings\n    viewport: { width: 1280, height: 720 },\n    headless: true,\n\n    // Slow down for visibility in recordings\n    launchOptions: {\n      slowMo: 100\n    },\n\n    // Browser context\n    contextOptions: {\n      recordVideo: {\n        dir: './test-results/videos',\n        size: { width: 1280, height: 720 }\n      }\n    }\n  },\n\n  // Disable retries for recording\n  retries: 0,\n\n  // Single worker for consistent recording\n  workers: 1,\n});\n```\n\n## Running Specs\n\n### Basic Execution\n\n```bash\nnpx playwright test specs/demo.spec.ts\n```\n\n### With Custom Config\n\n```bash\nnpx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts\n```\n\n### Common Options\n\n```bash\n# Run specific test by name\nnpx playwright test -g \"demo workflow\"\n\n# Run in headed mode (visible browser)\nnpx playwright test --headed\n\n# Use specific browser\nnpx playwright test --project=chromium\n\n# Set timeout\nnpx playwright test --timeout=60000\n\n# Output verbose logs\nnpx playwright test --debug\n```\n\n## Video Output Paths\n\nPlaywright creates videos at:\n```\n<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm\n```\n\nExample:\n```\ntest-results/demo-spec-ts-chromium/demo-workflow/video.webm\n```\n\n### Programmatic Video Path\n\nAccess video path in test:\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo', async ({ page }, testInfo) => {\n  // ... test actions ...\n\n  // After test, attach video path\n  const video = page.video();\n  if (video) {\n    const path = await video.path();\n    console.log('Video saved to:', path);\n  }\n});\n```\n\n## Error Handling\n\n### Common Issues\n\n**Browser not installed:**\n```bash\nnpx playwright install chromium\n```\n\n**Timeout errors:**\n```typescript\n// Increase action timeout\nawait page.click('button', { timeout: 10000 });\n\n// Or set global timeout in config\nuse: {\n  actionTimeout: 10000,\n}\n```\n\n**Video not created:**\n- validate `video: 'on'` in config\n- Check test actually runs (not skipped)\n- Verify outputDir is writable\n\n**Empty or corrupted video:**\n- Add `await page.waitForTimeout(500)` before test ends\n- validate page has loaded: `await page.waitForLoadState('networkidle')`\n\n### Exit Code Handling\n\n```bash\nnpx playwright test specs/demo.spec.ts\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"Recording completed successfully\"\n  # Find video file\n  VIDEO=$(find test-results -name \"video.webm\" -type f | head -1)\n  echo \"Video: $VIDEO\"\nelse\n  echo \"Recording failed with exit code $EXIT_CODE\"\n  exit $EXIT_CODE\nfi\n```\n\n## Best Practices for Recording Specs\n\n1. **Use explicit waits** - Avoid flaky recordings\n   ```typescript\n   await page.waitForSelector('.element');\n   await page.waitForLoadState('networkidle');\n   ```\n\n2. **Add pauses for visibility** - Give viewers time to see actions\n   ```typescript\n   await page.waitForTimeout(500);\n   ```\n\n3. **Use slowMo** - Slow down all actions\n   ```typescript\n   launchOptions: { slowMo: 100 }\n   ```\n\n4. **Consistent viewport** - Match video size to viewport\n   ```typescript\n   viewport: { width: 1280, height: 720 },\n   video: { size: { width: 1280, height: 720 } }\n   ```\n\n5. **Disable retries** - One clean recording\n   ```typescript\n   retries: 0\n   ```\n\nFile v1.9.12:modules/video-capture.md\n\n# Video Capture Module\n\nVideo format options, quality settings, and post-processing for Playwright recordings.\n\n## Video Format\n\nPlaywright records video in **WebM** format with VP8 codec. This format:\n- Has good compression\n- Supports transparency (if needed)\n- Works well with ffmpeg for conversion\n- Is natively supported by most browsers\n\n## Resolution Settings\n\n### Common Resolutions\n\n| Resolution | Use Case | Aspect Ratio |\n|------------|----------|--------------|\n| 1920x1080 | Full HD, detailed demos | 16:9 |\n| 1280x720 | Standard tutorials | 16:9 |\n| 1024x768 | Compact demos | 4:3 |\n| 800x600 | Small GIF output | 4:3 |\n\n### Playwright Video Size Configuration\n\n```typescript\n// In playwright.config.ts\nuse: {\n  video: {\n    mode: 'on',\n    size: { width: 1280, height: 720 }\n  },\n  viewport: { width: 1280, height: 720 }\n}\n```\n\n**Important:** Match `video.size` to `viewport` for best quality.\n\n### Per-Test Video Settings\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  video: {\n    mode: 'on',\n    size: { width: 1920, height: 1080 }\n  },\n  viewport: { width: 1920, height: 1080 }\n});\n\ntest('high-res demo', async ({ page }) => {\n  // Test runs at 1080p\n});\n```\n\n## Quality Considerations\n\n### Frame Rate\n\nPlaywright records at approximately 25 fps. This is sufficient for UI demos.\n\n### Bitrate\n\nWebM videos from Playwright use variable bitrate. Typical sizes:\n- 720p, 30 seconds: 2-5 MB\n- 1080p, 30 seconds: 5-10 MB\n\n### Minimizing File Size\n\n1. **Smaller viewport** - Reduce dimensions\n2. **Shorter duration** - Trim unnecessary pauses\n3. **Simple animations** - Fewer visual changes = smaller file\n\n## Playwright Video Configuration in Tests\n\n### Enable Video for Specific Tests\n\n```typescript\nimport { test } from '@playwright/test';\n\n// Enable video for this test file\ntest.describe.configure({ mode: 'serial' });\n\ntest.use({\n  video: 'on',\n  viewport: { width: 1280, height: 720 }\n});\n\ntest('recorded demo', async ({ page }) => {\n  await page.goto('https://example.com');\n  await page.waitForTimeout(1000);\n});\n```\n\n### Conditional Recording\n\n```typescript\nimport { test } from '@playwright/test';\n\nconst RECORD = process.env.RECORD === 'true';\n\ntest.use({\n  video: RECORD ? 'on' : 'off'\n});\n\ntest('conditionally recorded', async ({ page }) => {\n  // Only records when RECORD=true\n});\n```\n\n### Custom Video Directory\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  contextOptions: {\n    recordVideo: {\n      dir: './custom-video-output',\n      size: { width: 1280, height: 720 }\n    }\n  }\n});\n```\n\n## Post-Processing with ffmpeg\n\n### Convert WebM to MP4\n\n```bash\nffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4\n```\n\n### Extract Specific Time Range\n\n```bash\n# Extract from 0:05 to 0:15\nffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm\n```\n\n### Change Resolution\n\n```bash\n# Scale to 800px width, maintain aspect ratio\nffmpeg -i video.webm -vf \"scale=800:-1\" scaled.webm\n```\n\n### Speed Up Video\n\n```bash\n# 2x speed\nffmpeg -i video.webm -filter:v \"setpts=0.5*PTS\" faster.webm\n```\n\n### Add Padding/Borders\n\n```bash\n# Add 10px black border\nffmpeg -i video.webm -vf \"pad=width+20:height+20:10:10:black\" padded.webm\n```\n\n### Combine Multiple Videos\n\n```bash\n# Create file list\necho \"file 'video1.webm'\" > list.txt\necho \"file 'video2.webm'\" >> list.txt\n\n# Concatenate\nffmpeg -f concat -safe 0 -i list.txt -c copy combined.webm\n```\n\n## Converting to GIF\n\nFor GIF conversion, use the `scry:gif-generation` skill which handles:\n- Palette generation for optimal colors\n- Frame rate reduction (10-15 fps typical)\n- Width scaling\n- Dithering for quality\n\nQuick ffmpeg conversion (basic):\n\n```bash\n# Simple conversion (larger file, lower quality)\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1\" output.gif\n\n# Better quality with palette\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" output.gif\n```\n\n## Troubleshooting\n\n### Video is black or frozen\n\n- validate page has visible content before recording starts\n- Add `await page.waitForLoadState('domcontentloaded')`\n- Check for CSS that hides content initially\n\n### Video cuts off early\n\n- Test might be finishing before video flushes\n- Add `await page.waitForTimeout(500)` at end of test\n- validate `await page.close()` is not called (Playwright handles cleanup)\n\n### Video too large\n\n- Reduce resolution\n- Shorten test duration\n- Use post-processing to compress\n\n### Choppy playback\n\n- Normal at high resolutions\n- Consider reducing to 720p\n- Final GIF will be smoother at lower fps\n\nFile v1.9.12:skill-card.md\n\n## Description: <br>\nRecords browser sessions via Playwright and converts video to GIF. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[athola](https://clawhub.ai/user/athola) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and engineers use this skill to record automated browser interactions with Playwright and create WebM or GIF assets for web UI tutorials, demos, and documentation. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Browser recordings may capture credentials, tokens, customer data, or internal dashboard content visible in the page. <br>\nMitigation: Use test accounts or sanitized demo data, avoid sensitive pages, and review videos and GIFs before sharing. <br>\nRisk: Generated recordings can be misleading if the Playwright spec is flaky, too fast, or ends before the page reaches the intended state. <br>\nMitigation: Use explicit waits, stable viewports, and final pauses, then verify that the output video exists and has non-zero size. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/athola/nm-scry-browser-recording) <br>\n- [Scry source plugin homepage](https://github.com/athola/claude-night-market/tree/master/plugins/scry) <br>\n- [modules/spec-execution.md](artifact/modules/spec-execution.md) <br>\n- [modules/video-capture.md](artifact/modules/video-capture.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [guidance, markdown, code, shell commands, configuration] <br>\n**Output Format:** [Markdown with TypeScript configuration examples and shell command snippets] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Guides agents to produce Playwright recording steps, video output paths, and optional GIF conversion instructions.] <br>\n\n## Skill Version(s): <br>\n1.9.12 (source: server release metadata; artifact frontmatter lists 1.9.8) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.0.2: 5 files, 8022 bytes\n\nFiles: modules/spec-execution.md (3911b), modules/video-capture.md (4559b), skill-card.md (2209b), SKILL.md (6660b), _meta.json (144b)\n\nFile v1.0.2:SKILL.md\n\n---\nname: browser-recording\ndescription: Record browser sessions using Playwright for web UI tutorials, converts\nversion: 1.9.5\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright --version\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nIf not installed, the user should run:\n```bash\nnpm install -D @playwright/test\nnpx playwright install chromium\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n### Step 2: Check Spec File\n\nVerify the Playwright spec file exists. Spec files should:\n- Be located in a `specs/` or `tests/` directory\n- Have `.spec.ts` or `.spec.js` extension\n- Include video configuration (see spec-execution module)\n\n### Step 3: Execute Recording\n\nRun the spec with video enabled:\n\n```bash\nnpx playwright test <spec-file> --config=playwright.config.ts\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\nThe config must enable video recording. See the spec-execution module for configuration details.\n\n### Step 4: Convert to GIF\n\nAfter recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:\n\n```\n**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Example Playwright Spec\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo workflow', async ({ page }) => {\n  // Navigate to the application\n  await page.goto('http://localhost:3000');\n\n  // Wait for page to be ready\n  await page.waitForLoadState('networkidle');\n\n  // Perform demo actions\n  await page.click('button[data-testid=\"start\"]');\n  await page.waitForTimeout(500); // Allow animation to complete\n\n  await page.fill('input[name=\"query\"]', 'example search');\n  await page.waitForTimeout(300);\n\n  await page.click('button[type=\"submit\"]');\n  await page.waitForSelector('.results');\n\n  // Final pause to show results\n  await page.waitForTimeout(1000);\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Playwright Configuration\n\nCreate or update `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: {\n      mode: 'on',\n      size: { width: 1280, height: 720 }\n    },\n    viewport: { width: 1280, height: 720 },\n    launchOptions: {\n      slowMo: 100 // Slow down actions for visibility\n    }\n  },\n  outputDir: './test-results',\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Exit Criteria\n\n- Playwright spec executed successfully (exit code 0)\n- Video file exists in output directory\n- Video has non-zero file size\n- GIF conversion completed (if requested)\n\n## Error Handling\n\n| Error | Resolution |\n|-------|------------|\n| Playwright not installed | Run `npm install -D @playwright/test` |\n| Browser not installed | Run `npx playwright install chromium` |\n| Spec file not found | Verify path and file extension |\n| Video not created | Check Playwright config has video enabled |\n| Empty video file | validate spec actions complete before test ends |\n\n## Output Locations\n\nDefault output paths:\n- Videos: `./test-results/<test-name>/video.webm`\n- Screenshots: `./test-results/<test-name>/screenshot.png`\n\n## Module Reference\n\n- See `modules/spec-execution.md` for detailed Playwright execution options\n- See `modules/video-capture.md` for video format and quality settings\n\n## See Also\n\n- scry:gif-generation: Convert video to optimized GIF\n## Troubleshooting\n\n### Common Issues\n\n**Command not found**\nEnsure all dependencies are installed and in PATH\n\n**Permission errors**\nCheck file permissions and run with appropriate privileges\n\n**Unexpected behavior**\nEnable verbose logging with `--verbose` flag\n\nFile v1.0.2:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-scry-browser-recording\",\n  \"version\": \"1.0.2\",\n  \"publishedAt\": 1778293233793\n}\n\nFile v1.0.2:modules/spec-execution.md\n\n# Spec Execution Module\n\nExecute Playwright specs with video recording enabled.\n\n## Playwright Configuration for Video\n\n### Minimal Config\n\nCreate `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: 'on',\n  },\n  outputDir: './test-results',\n});\n```\n\n### Full Recording Config\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: './specs',\n  outputDir: './test-results',\n\n  use: {\n    // Video settings\n    video: {\n      mode: 'on',           // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'\n      size: {\n        width: 1280,\n        height: 720\n      }\n    },\n\n    // Browser settings\n    viewport: { width: 1280, height: 720 },\n    headless: true,\n\n    // Slow down for visibility in recordings\n    launchOptions: {\n      slowMo: 100\n    },\n\n    // Browser context\n    contextOptions: {\n      recordVideo: {\n        dir: './test-results/videos',\n        size: { width: 1280, height: 720 }\n      }\n    }\n  },\n\n  // Disable retries for recording\n  retries: 0,\n\n  // Single worker for consistent recording\n  workers: 1,\n});\n```\n\n## Running Specs\n\n### Basic Execution\n\n```bash\nnpx playwright test specs/demo.spec.ts\n```\n\n### With Custom Config\n\n```bash\nnpx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts\n```\n\n### Common Options\n\n```bash\n# Run specific test by name\nnpx playwright test -g \"demo workflow\"\n\n# Run in headed mode (visible browser)\nnpx playwright test --headed\n\n# Use specific browser\nnpx playwright test --project=chromium\n\n# Set timeout\nnpx playwright test --timeout=60000\n\n# Output verbose logs\nnpx playwright test --debug\n```\n\n## Video Output Paths\n\nPlaywright creates videos at:\n```\n<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm\n```\n\nExample:\n```\ntest-results/demo-spec-ts-chromium/demo-workflow/video.webm\n```\n\n### Programmatic Video Path\n\nAccess video path in test:\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo', async ({ page }, testInfo) => {\n  // ... test actions ...\n\n  // After test, attach video path\n  const video = page.video();\n  if (video) {\n    const path = await video.path();\n    console.log('Video saved to:', path);\n  }\n});\n```\n\n## Error Handling\n\n### Common Issues\n\n**Browser not installed:**\n```bash\nnpx playwright install chromium\n```\n\n**Timeout errors:**\n```typescript\n// Increase action timeout\nawait page.click('button', { timeout: 10000 });\n\n// Or set global timeout in config\nuse: {\n  actionTimeout: 10000,\n}\n```\n\n**Video not created:**\n- validate `video: 'on'` in config\n- Check test actually runs (not skipped)\n- Verify outputDir is writable\n\n**Empty or corrupted video:**\n- Add `await page.waitForTimeout(500)` before test ends\n- validate page has loaded: `await page.waitForLoadState('networkidle')`\n\n### Exit Code Handling\n\n```bash\nnpx playwright test specs/demo.spec.ts\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"Recording completed successfully\"\n  # Find video file\n  VIDEO=$(find test-results -name \"video.webm\" -type f | head -1)\n  echo \"Video: $VIDEO\"\nelse\n  echo \"Recording failed with exit code $EXIT_CODE\"\n  exit $EXIT_CODE\nfi\n```\n\n## Best Practices for Recording Specs\n\n1. **Use explicit waits** - Avoid flaky recordings\n   ```typescript\n   await page.waitForSelector('.element');\n   await page.waitForLoadState('networkidle');\n   ```\n\n2. **Add pauses for visibility** - Give viewers time to see actions\n   ```typescript\n   await page.waitForTimeout(500);\n   ```\n\n3. **Use slowMo** - Slow down all actions\n   ```typescript\n   launchOptions: { slowMo: 100 }\n   ```\n\n4. **Consistent viewport** - Match video size to viewport\n   ```typescript\n   viewport: { width: 1280, height: 720 },\n   video: { size: { width: 1280, height: 720 } }\n   ```\n\n5. **Disable retries** - One clean recording\n   ```typescript\n   retries: 0\n   ```\n\nFile v1.0.2:modules/video-capture.md\n\n# Video Capture Module\n\nVideo format options, quality settings, and post-processing for Playwright recordings.\n\n## Video Format\n\nPlaywright records video in **WebM** format with VP8 codec. This format:\n- Has good compression\n- Supports transparency (if needed)\n- Works well with ffmpeg for conversion\n- Is natively supported by most browsers\n\n## Resolution Settings\n\n### Common Resolutions\n\n| Resolution | Use Case | Aspect Ratio |\n|------------|----------|--------------|\n| 1920x1080 | Full HD, detailed demos | 16:9 |\n| 1280x720 | Standard tutorials | 16:9 |\n| 1024x768 | Compact demos | 4:3 |\n| 800x600 | Small GIF output | 4:3 |\n\n### Playwright Video Size Configuration\n\n```typescript\n// In playwright.config.ts\nuse: {\n  video: {\n    mode: 'on',\n    size: { width: 1280, height: 720 }\n  },\n  viewport: { width: 1280, height: 720 }\n}\n```\n\n**Important:** Match `video.size` to `viewport` for best quality.\n\n### Per-Test Video Settings\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  video: {\n    mode: 'on',\n    size: { width: 1920, height: 1080 }\n  },\n  viewport: { width: 1920, height: 1080 }\n});\n\ntest('high-res demo', async ({ page }) => {\n  // Test runs at 1080p\n});\n```\n\n## Quality Considerations\n\n### Frame Rate\n\nPlaywright records at approximately 25 fps. This is sufficient for UI demos.\n\n### Bitrate\n\nWebM videos from Playwright use variable bitrate. Typical sizes:\n- 720p, 30 seconds: 2-5 MB\n- 1080p, 30 seconds: 5-10 MB\n\n### Minimizing File Size\n\n1. **Smaller viewport** - Reduce dimensions\n2. **Shorter duration** - Trim unnecessary pauses\n3. **Simple animations** - Fewer visual changes = smaller file\n\n## Playwright Video Configuration in Tests\n\n### Enable Video for Specific Tests\n\n```typescript\nimport { test } from '@playwright/test';\n\n// Enable video for this test file\ntest.describe.configure({ mode: 'serial' });\n\ntest.use({\n  video: 'on',\n  viewport: { width: 1280, height: 720 }\n});\n\ntest('recorded demo', async ({ page }) => {\n  await page.goto('https://example.com');\n  await page.waitForTimeout(1000);\n});\n```\n\n### Conditional Recording\n\n```typescript\nimport { test } from '@playwright/test';\n\nconst RECORD = process.env.RECORD === 'true';\n\ntest.use({\n  video: RECORD ? 'on' : 'off'\n});\n\ntest('conditionally recorded', async ({ page }) => {\n  // Only records when RECORD=true\n});\n```\n\n### Custom Video Directory\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  contextOptions: {\n    recordVideo: {\n      dir: './custom-video-output',\n      size: { width: 1280, height: 720 }\n    }\n  }\n});\n```\n\n## Post-Processing with ffmpeg\n\n### Convert WebM to MP4\n\n```bash\nffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4\n```\n\n### Extract Specific Time Range\n\n```bash\n# Extract from 0:05 to 0:15\nffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm\n```\n\n### Change Resolution\n\n```bash\n# Scale to 800px width, maintain aspect ratio\nffmpeg -i video.webm -vf \"scale=800:-1\" scaled.webm\n```\n\n### Speed Up Video\n\n```bash\n# 2x speed\nffmpeg -i video.webm -filter:v \"setpts=0.5*PTS\" faster.webm\n```\n\n### Add Padding/Borders\n\n```bash\n# Add 10px black border\nffmpeg -i video.webm -vf \"pad=width+20:height+20:10:10:black\" padded.webm\n```\n\n### Combine Multiple Videos\n\n```bash\n# Create file list\necho \"file 'video1.webm'\" > list.txt\necho \"file 'video2.webm'\" >> list.txt\n\n# Concatenate\nffmpeg -f concat -safe 0 -i list.txt -c copy combined.webm\n```\n\n## Converting to GIF\n\nFor GIF conversion, use the `scry:gif-generation` skill which handles:\n- Palette generation for optimal colors\n- Frame rate reduction (10-15 fps typical)\n- Width scaling\n- Dithering for quality\n\nQuick ffmpeg conversion (basic):\n\n```bash\n# Simple conversion (larger file, lower quality)\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1\" output.gif\n\n# Better quality with palette\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" output.gif\n```\n\n## Troubleshooting\n\n### Video is black or frozen\n\n- validate page has visible content before recording starts\n- Add `await page.waitForLoadState('domcontentloaded')`\n- Check for CSS that hides content initially\n\n### Video cuts off early\n\n- Test might be finishing before video flushes\n- Add `await page.waitForTimeout(500)` at end of test\n- validate `await page.close()` is not called (Playwright handles cleanup)\n\n### Video too large\n\n- Reduce resolution\n- Shorten test duration\n- Use post-processing to compress\n\n### Choppy playback\n\n- Normal at high resolutions\n- Consider reducing to 720p\n- Final GIF will be smoother at lower fps\n\nFile v1.0.2:skill-card.md\n\n## Description: <br>\nRecord browser sessions with Playwright to create video captures of web UI interactions for tutorials and documentation. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[athola](https://clawhub.ai/user/athola) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and technical writers use this skill to record automated browser workflows with Playwright, verify the resulting WebM capture, and prepare tutorial-ready GIF or video artifacts. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Browser recordings can capture secrets, private dashboards, or sensitive test data. <br>\nMitigation: Use sanitized test accounts, avoid recording secrets, review videos and GIFs before sharing, and delete raw recordings when they are no longer needed. <br>\nRisk: Recording workflows create local video or GIF artifacts that may persist in project output directories. <br>\nMitigation: Confirm the intended output directory, review generated media before distribution, and remove temporary recording artifacts after use. <br>\n\n\n## Reference(s): <br>\n- [ClawHub release page](https://clawhub.ai/athola/nm-scry-browser-recording) <br>\n- [claude-night-market scry plugin](https://github.com/athola/claude-night-market/tree/master/plugins/scry) <br>\n- [Spec execution module](modules/spec-execution.md) <br>\n- [Video capture module](modules/video-capture.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Guidance, Shell commands, Code, Configuration] <br>\n**Output Format:** [Markdown with inline bash and TypeScript code blocks] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Produces Playwright recording instructions and file-location guidance for local WebM video and optional GIF artifacts.] <br>\n\n## Skill Version(s): <br>\n1.0.2 (source: ClawHub release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.0.1: 4 files, 6838 bytes\n\nFiles: modules/spec-execution.md (3911b), modules/video-capture.md (4559b), SKILL.md (6660b), _meta.json (144b)\n\nFile v1.0.1:SKILL.md\n\n---\nname: browser-recording\ndescription: Record browser sessions using Playwright for web UI tutorials, converts\nversion: 1.9.4\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright --version\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nIf not installed, the user should run:\n```bash\nnpm install -D @playwright/test\nnpx playwright install chromium\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n### Step 2: Check Spec File\n\nVerify the Playwright spec file exists. Spec files should:\n- Be located in a `specs/` or `tests/` directory\n- Have `.spec.ts` or `.spec.js` extension\n- Include video configuration (see spec-execution module)\n\n### Step 3: Execute Recording\n\nRun the spec with video enabled:\n\n```bash\nnpx playwright test <spec-file> --config=playwright.config.ts\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\nThe config must enable video recording. See the spec-execution module for configuration details.\n\n### Step 4: Convert to GIF\n\nAfter recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:\n\n```\n**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Example Playwright Spec\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo workflow', async ({ page }) => {\n  // Navigate to the application\n  await page.goto('http://localhost:3000');\n\n  // Wait for page to be ready\n  await page.waitForLoadState('networkidle');\n\n  // Perform demo actions\n  await page.click('button[data-testid=\"start\"]');\n  await page.waitForTimeout(500); // Allow animation to complete\n\n  await page.fill('input[name=\"query\"]', 'example search');\n  await page.waitForTimeout(300);\n\n  await page.click('button[type=\"submit\"]');\n  await page.waitForSelector('.results');\n\n  // Final pause to show results\n  await page.waitForTimeout(1000);\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Playwright Configuration\n\nCreate or update `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: {\n      mode: 'on',\n      size: { width: 1280, height: 720 }\n    },\n    viewport: { width: 1280, height: 720 },\n    launchOptions: {\n      slowMo: 100 // Slow down actions for visibility\n    }\n  },\n  outputDir: './test-results',\n});\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n## Exit Criteria\n\n- Playwright spec executed successfully (exit code 0)\n- Video file exists in output directory\n- Video has non-zero file size\n- GIF conversion completed (if requested)\n\n## Error Handling\n\n| Error | Resolution |\n|-------|------------|\n| Playwright not installed | Run `npm install -D @playwright/test` |\n| Browser not installed | Run `npx playwright install chromium` |\n| Spec file not found | Verify path and file extension |\n| Video not created | Check Playwright config has video enabled |\n| Empty video file | validate spec actions complete before test ends |\n\n## Output Locations\n\nDefault output paths:\n- Videos: `./test-results/<test-name>/video.webm`\n- Screenshots: `./test-results/<test-name>/screenshot.png`\n\n## Module Reference\n\n- See `modules/spec-execution.md` for detailed Playwright execution options\n- See `modules/video-capture.md` for video format and quality settings\n\n## See Also\n\n- scry:gif-generation: Convert video to optimized GIF\n## Troubleshooting\n\n### Common Issues\n\n**Command not found**\nEnsure all dependencies are installed and in PATH\n\n**Permission errors**\nCheck file permissions and run with appropriate privileges\n\n**Unexpected behavior**\nEnable verbose logging with `--verbose` flag\n\nFile v1.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-scry-browser-recording\",\n  \"version\": \"1.0.1\",\n  \"publishedAt\": 1778077325168\n}\n\nFile v1.0.1:modules/spec-execution.md\n\n# Spec Execution Module\n\nExecute Playwright specs with video recording enabled.\n\n## Playwright Configuration for Video\n\n### Minimal Config\n\nCreate `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: 'on',\n  },\n  outputDir: './test-results',\n});\n```\n\n### Full Recording Config\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: './specs',\n  outputDir: './test-results',\n\n  use: {\n    // Video settings\n    video: {\n      mode: 'on',           // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'\n      size: {\n        width: 1280,\n        height: 720\n      }\n    },\n\n    // Browser settings\n    viewport: { width: 1280, height: 720 },\n    headless: true,\n\n    // Slow down for visibility in recordings\n    launchOptions: {\n      slowMo: 100\n    },\n\n    // Browser context\n    contextOptions: {\n      recordVideo: {\n        dir: './test-results/videos',\n        size: { width: 1280, height: 720 }\n      }\n    }\n  },\n\n  // Disable retries for recording\n  retries: 0,\n\n  // Single worker for consistent recording\n  workers: 1,\n});\n```\n\n## Running Specs\n\n### Basic Execution\n\n```bash\nnpx playwright test specs/demo.spec.ts\n```\n\n### With Custom Config\n\n```bash\nnpx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts\n```\n\n### Common Options\n\n```bash\n# Run specific test by name\nnpx playwright test -g \"demo workflow\"\n\n# Run in headed mode (visible browser)\nnpx playwright test --headed\n\n# Use specific browser\nnpx playwright test --project=chromium\n\n# Set timeout\nnpx playwright test --timeout=60000\n\n# Output verbose logs\nnpx playwright test --debug\n```\n\n## Video Output Paths\n\nPlaywright creates videos at:\n```\n<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm\n```\n\nExample:\n```\ntest-results/demo-spec-ts-chromium/demo-workflow/video.webm\n```\n\n### Programmatic Video Path\n\nAccess video path in test:\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo', async ({ page }, testInfo) => {\n  // ... test actions ...\n\n  // After test, attach video path\n  const video = page.video();\n  if (video) {\n    const path = await video.path();\n    console.log('Video saved to:', path);\n  }\n});\n```\n\n## Error Handling\n\n### Common Issues\n\n**Browser not installed:**\n```bash\nnpx playwright install chromium\n```\n\n**Timeout errors:**\n```typescript\n// Increase action timeout\nawait page.click('button', { timeout: 10000 });\n\n// Or set global timeout in config\nuse: {\n  actionTimeout: 10000,\n}\n```\n\n**Video not created:**\n- validate `video: 'on'` in config\n- Check test actually runs (not skipped)\n- Verify outputDir is writable\n\n**Empty or corrupted video:**\n- Add `await page.waitForTimeout(500)` before test ends\n- validate page has loaded: `await page.waitForLoadState('networkidle')`\n\n### Exit Code Handling\n\n```bash\nnpx playwright test specs/demo.spec.ts\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"Recording completed successfully\"\n  # Find video file\n  VIDEO=$(find test-results -name \"video.webm\" -type f | head -1)\n  echo \"Video: $VIDEO\"\nelse\n  echo \"Recording failed with exit code $EXIT_CODE\"\n  exit $EXIT_CODE\nfi\n```\n\n## Best Practices for Recording Specs\n\n1. **Use explicit waits** - Avoid flaky recordings\n   ```typescript\n   await page.waitForSelector('.element');\n   await page.waitForLoadState('networkidle');\n   ```\n\n2. **Add pauses for visibility** - Give viewers time to see actions\n   ```typescript\n   await page.waitForTimeout(500);\n   ```\n\n3. **Use slowMo** - Slow down all actions\n   ```typescript\n   launchOptions: { slowMo: 100 }\n   ```\n\n4. **Consistent viewport** - Match video size to viewport\n   ```typescript\n   viewport: { width: 1280, height: 720 },\n   video: { size: { width: 1280, height: 720 } }\n   ```\n\n5. **Disable retries** - One clean recording\n   ```typescript\n   retries: 0\n   ```\n\nFile v1.0.1:modules/video-capture.md\n\n# Video Capture Module\n\nVideo format options, quality settings, and post-processing for Playwright recordings.\n\n## Video Format\n\nPlaywright records video in **WebM** format with VP8 codec. This format:\n- Has good compression\n- Supports transparency (if needed)\n- Works well with ffmpeg for conversion\n- Is natively supported by most browsers\n\n## Resolution Settings\n\n### Common Resolutions\n\n| Resolution | Use Case | Aspect Ratio |\n|------------|----------|--------------|\n| 1920x1080 | Full HD, detailed demos | 16:9 |\n| 1280x720 | Standard tutorials | 16:9 |\n| 1024x768 | Compact demos | 4:3 |\n| 800x600 | Small GIF output | 4:3 |\n\n### Playwright Video Size Configuration\n\n```typescript\n// In playwright.config.ts\nuse: {\n  video: {\n    mode: 'on',\n    size: { width: 1280, height: 720 }\n  },\n  viewport: { width: 1280, height: 720 }\n}\n```\n\n**Important:** Match `video.size` to `viewport` for best quality.\n\n### Per-Test Video Settings\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  video: {\n    mode: 'on',\n    size: { width: 1920, height: 1080 }\n  },\n  viewport: { width: 1920, height: 1080 }\n});\n\ntest('high-res demo', async ({ page }) => {\n  // Test runs at 1080p\n});\n```\n\n## Quality Considerations\n\n### Frame Rate\n\nPlaywright records at approximately 25 fps. This is sufficient for UI demos.\n\n### Bitrate\n\nWebM videos from Playwright use variable bitrate. Typical sizes:\n- 720p, 30 seconds: 2-5 MB\n- 1080p, 30 seconds: 5-10 MB\n\n### Minimizing File Size\n\n1. **Smaller viewport** - Reduce dimensions\n2. **Shorter duration** - Trim unnecessary pauses\n3. **Simple animations** - Fewer visual changes = smaller file\n\n## Playwright Video Configuration in Tests\n\n### Enable Video for Specific Tests\n\n```typescript\nimport { test } from '@playwright/test';\n\n// Enable video for this test file\ntest.describe.configure({ mode: 'serial' });\n\ntest.use({\n  video: 'on',\n  viewport: { width: 1280, height: 720 }\n});\n\ntest('recorded demo', async ({ page }) => {\n  await page.goto('https://example.com');\n  await page.waitForTimeout(1000);\n});\n```\n\n### Conditional Recording\n\n```typescript\nimport { test } from '@playwright/test';\n\nconst RECORD = process.env.RECORD === 'true';\n\ntest.use({\n  video: RECORD ? 'on' : 'off'\n});\n\ntest('conditionally recorded', async ({ page }) => {\n  // Only records when RECORD=true\n});\n```\n\n### Custom Video Directory\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  contextOptions: {\n    recordVideo: {\n      dir: './custom-video-output',\n      size: { width: 1280, height: 720 }\n    }\n  }\n});\n```\n\n## Post-Processing with ffmpeg\n\n### Convert WebM to MP4\n\n```bash\nffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4\n```\n\n### Extract Specific Time Range\n\n```bash\n# Extract from 0:05 to 0:15\nffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm\n```\n\n### Change Resolution\n\n```bash\n# Scale to 800px width, maintain aspect ratio\nffmpeg -i video.webm -vf \"scale=800:-1\" scaled.webm\n```\n\n### Speed Up Video\n\n```bash\n# 2x speed\nffmpeg -i video.webm -filter:v \"setpts=0.5*PTS\" faster.webm\n```\n\n### Add Padding/Borders\n\n```bash\n# Add 10px black border\nffmpeg -i video.webm -vf \"pad=width+20:height+20:10:10:black\" padded.webm\n```\n\n### Combine Multiple Videos\n\n```bash\n# Create file list\necho \"file 'video1.webm'\" > list.txt\necho \"file 'video2.webm'\" >> list.txt\n\n# Concatenate\nffmpeg -f concat -safe 0 -i list.txt -c copy combined.webm\n```\n\n## Converting to GIF\n\nFor GIF conversion, use the `scry:gif-generation` skill which handles:\n- Palette generation for optimal colors\n- Frame rate reduction (10-15 fps typical)\n- Width scaling\n- Dithering for quality\n\nQuick ffmpeg conversion (basic):\n\n```bash\n# Simple conversion (larger file, lower quality)\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1\" output.gif\n\n# Better quality with palette\nffmpeg -i video.webm -vf \"fps=10,scale=800:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" output.gif\n```\n\n## Troubleshooting\n\n### Video is black or frozen\n\n- validate page has visible content before recording starts\n- Add `await page.waitForLoadState('domcontentloaded')`\n- Check for CSS that hides content initially\n\n### Video cuts off early\n\n- Test might be finishing before video flushes\n- Add `await page.waitForTimeout(500)` at end of test\n- validate `await page.close()` is not called (Playwright handles cleanup)\n\n### Video too large\n\n- Reduce resolution\n- Shorten test duration\n- Use post-processing to compress\n\n### Choppy playback\n\n- Normal at high resolutions\n- Consider reducing to 720p\n- Final GIF will be smoother at lower fps\n\nArchive v1.0.0: 4 files, 6837 bytes\n\nFiles: modules/spec-execution.md (3911b), modules/video-capture.md (4559b), SKILL.md (6660b), _meta.json (144b)\n\nFile v1.0.0:SKILL.md\n\n---\nname: browser-recording\ndescription: Record browser sessions using Playwright for web UI tutorials, converts\nversion: 1.8.2\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright --version\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\nIf not installed, the user should run:\n```bash\nnpm install -D @playwright/test\nnpx playwright install chromium\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\n### Step 2: Check Spec File\n\nVerify the Playwright spec file exists. Spec files should:\n- Be located in a `specs/` or `tests/` directory\n- Have `.spec.ts` or `.spec.js` extension\n- Include video configuration (see spec-execution module)\n\n### Step 3: Execute Recording\n\nRun the spec with video enabled:\n\n```bash\nnpx playwright test <spec-file> --config=playwright.config.ts\n```\n**Verification:** Run `pytest -v` to verify tests pass.\n\nThe config must enable video recording. See the spec-execution module for configuration details.\n\n### Step 4: Convert to GIF\n\nAfter recording completes, use the gif-generation skill to convert the WebM video to an optimized GIF:\n\n```\n**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)\n```\n**Verification:** Run the command with `--hel","readmeExcerpt":"Skill: browser-recording Owner: athola Summary: Records browser sessions via Playwright and converts video to GIF Tags: latest:1.9.19 Version history: v1.9.19 | 2026-08-26T13:22:46.041Z | user Release v1.9.19 v1.9.17 | 2026-07-30T05:42:37.119Z | user Release v1.9.17 v1.9.16 | 2026-07-14T19:59:28.809Z | user Release v1.9.16 v1.9.14 | 2026-06-30T18:06:55.013Z | user Release v1.9.14 v1.9.13 | 2026-06-27T16:24:47.231Z | ","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill"},{"language":"bash","snippet":"npx playwright --version"},{"language":"bash","snippet":"npm install -D @playwright/test\nnpx playwright install chromium"},{"language":"bash","snippet":"npx playwright test <spec-file> --config=playwright.config.ts"},{"language":"text","snippet":"**Verification:** Run the command with `--help` flag to verify availability.\nInvoke scry:gif-generation with:\n- input: <path-to-webm>\n- output: <desired-gif-path>\n- fps: 10 (recommended for tutorials)\n- width: 800 (adjust based on content)"},{"language":"typescript","snippet":"import { test, expect } from '@playwright/test';\n\ntest('demo workflow', async ({ page }) => {\n  // Navigate to the application\n  await page.goto('http://localhost:3000');\n\n  // Wait for page to be ready\n  await page.waitForLoadState('networkidle');\n\n  // Perform demo actions\n  await page.click('button[data-testid=\"start\"]');\n  await page.waitForTimeout(500); // Allow animation to complete\n\n  await page.fill('input[name=\"query\"]', 'example search');\n  await page.waitForTimeout(300);\n\n  await page.click('button[type=\"submit\"]');\n  await page.waitForSelector('.results');\n\n  // Final pause to show results\n  await page.waitForTimeout(1000);\n});"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: browser-recording\ndescription: Records browser sessions via Playwright and converts video to GIF\nversion: 1.9.8\ntriggers:\n  - playwright\n  - browser\n  - recording\n  - video\n  - web\n  - tutorial\n  - creating web UI tutorials or demos showing browser interactions\nmetadata: {\"openclaw\": {\"homepage\": \"https://github.com/athola/claude-night-market/tree/master/plugins/scry\", \"emoji\": \"\\ud83e\\udd9e\", \"requires\": {\"config\": [\"night-market.scry:gif-generation\"]}}}\nsource: claude-night-market\nsource_plugin: scry\n---\n\n> **Night Market Skill** — ported from [claude-night-market/scry](https://github.com/athola/claude-night-market/tree/master/plugins/scry). For the full experience with agents, hooks, and commands, install the Claude Code plugin.\n\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Required TodoWrite Items](#required-todowrite-items)\n- [Process](#process)\n- [Step 1: Validate Playwright Installation](#step-1:-validate-playwright-installation)\n- [Step 2: Check Spec File](#step-2:-check-spec-file)\n- [Step 3: Execute Recording](#step-3:-execute-recording)\n- [Step 4: Convert to GIF](#step-4:-convert-to-gif)\n- [Example Playwright Spec](#example-playwright-spec)\n- [Playwright Configuration](#playwright-configuration)\n- [Exit Criteria](#exit-criteria)\n- [Error Handling](#error-handling)\n- [Output Locations](#output-locations)\n- [See Also](#see-also)\n\n\n# Browser Recording Skill\n\nRecord browser sessions using Playwright to create video captures of web UI interactions for tutorials and documentation.\n\n\n## When To Use\n\n- Recording browser sessions with Playwright\n- Creating web application demo recordings\n\n## When NOT To Use\n\n- Terminal-only workflows - use scry:vhs-recording instead\n- Static screenshots - use standard screenshot tools\n\n## Overview\n\nThis skill uses Playwright's built-in video recording to capture browser interactions. The workflow:\n\n1. Validate Playwright installation\n2. Execute a Playwright spec with video recording enabled\n3. Retrieve the recorded video (WebM format)\n4. Convert to GIF using the gif-generation skill\n\n> **💡 Note**: Claude Code 2.0.72+ includes native Chrome integration for interactive browser control. This skill (Playwright) is designed for **automated recording workflows, CI/CD, and cross-browser support**. For interactive debugging and live testing, consider using native Chrome integration. Both approaches complement each other - develop interactively with Chrome, then automate with Playwright specs.\n\n## Required TodoWrite Items\n\nWhen invoking this skill, create todos for:\n\n```\n- [ ] Validate Playwright is installed and configured\n- [ ] Check spec file exists at specified path\n- [ ] Execute Playwright spec with video recording\n- [ ] Locate and verify video output\n- [ ] Convert video to GIF using gif-generation skill\n```\n**Verification:** Run the command with `--help` flag to verify availability.\n\n## Process\n\n### Step 1: Validate Playwright Installation\n\nCheck that Playwright is available:\n\n```bash\nnpx playwright"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7d107jg9jv602h9ytsegydq184a42s\",\n  \"slug\": \"nm-scry-browser-recording\",\n  \"version\": \"1.9.19\",\n  \"publishedAt\": 1787750566041\n}"},{"path":"modules/spec-execution.md","content":"# Spec Execution Module\n\nExecute Playwright specs with video recording enabled.\n\n## Playwright Configuration for Video\n\n### Minimal Config\n\nCreate `playwright.config.ts`:\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    video: 'on',\n  },\n  outputDir: './test-results',\n});\n```\n\n### Full Recording Config\n\n```typescript\nimport { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: './specs',\n  outputDir: './test-results',\n\n  use: {\n    // Video settings\n    video: {\n      mode: 'on',           // 'on' | 'off' | 'retain-on-failure' | 'on-first-retry'\n      size: {\n        width: 1280,\n        height: 720\n      }\n    },\n\n    // Browser settings\n    viewport: { width: 1280, height: 720 },\n    headless: true,\n\n    // Slow down for visibility in recordings\n    launchOptions: {\n      slowMo: 100\n    },\n\n    // Browser context\n    contextOptions: {\n      recordVideo: {\n        dir: './test-results/videos',\n        size: { width: 1280, height: 720 }\n      }\n    }\n  },\n\n  // Disable retries for recording\n  retries: 0,\n\n  // Single worker for consistent recording\n  workers: 1,\n});\n```\n\n## Running Specs\n\n### Basic Execution\n\n```bash\nnpx playwright test specs/demo.spec.ts\n```\n\n### With Custom Config\n\n```bash\nnpx playwright test specs/demo.spec.ts --config=playwright.recording.config.ts\n```\n\n### Common Options\n\n```bash\n# Run specific test by name\nnpx playwright test -g \"demo workflow\"\n\n# Run in headed mode (visible browser)\nnpx playwright test --headed\n\n# Use specific browser\nnpx playwright test --project=chromium\n\n# Set timeout\nnpx playwright test --timeout=60000\n\n# Output verbose logs\nnpx playwright test --debug\n```\n\n## Video Output Paths\n\nPlaywright creates videos at:\n```\n<outputDir>/<test-file-name>-<browser>/<test-name>/video.webm\n```\n\nExample:\n```\ntest-results/demo-spec-ts-chromium/demo-workflow/video.webm\n```\n\n### Programmatic Video Path\n\nAccess video path in test:\n\n```typescript\nimport { test, expect } from '@playwright/test';\n\ntest('demo', async ({ page }, testInfo) => {\n  // ... test actions ...\n\n  // After test, attach video path\n  const video = page.video();\n  if (video) {\n    const path = await video.path();\n    console.log('Video saved to:', path);\n  }\n});\n```\n\n## Error Handling\n\n### Common Issues\n\n**Browser not installed:**\n```bash\nnpx playwright install chromium\n```\n\n**Timeout errors:**\n```typescript\n// Increase action timeout\nawait page.click('button', { timeout: 10000 });\n\n// Or set global timeout in config\nuse: {\n  actionTimeout: 10000,\n}\n```\n\n**Video not created:**\n- validate `video: 'on'` in config\n- Check test actually runs (not skipped)\n- Verify outputDir is writable\n\n**Empty or corrupted video:**\n- Add `await page.waitForTimeout(500)` before test ends\n- validate page has loaded: `await page.waitForLoadState('networkidle')`\n\n### Exit Code Handling\n\n```bash\nnpx playwright test specs/demo.spec.ts\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"Recordi"},{"path":"modules/video-capture.md","content":"# Video Capture Module\n\nVideo format options, quality settings, and post-processing for Playwright recordings.\n\n## Video Format\n\nPlaywright records video in **WebM** format with VP8 codec. This format:\n- Has good compression\n- Supports transparency (if needed)\n- Works well with ffmpeg for conversion\n- Is natively supported by most browsers\n\n## Resolution Settings\n\n### Common Resolutions\n\n| Resolution | Use Case | Aspect Ratio |\n|------------|----------|--------------|\n| 1920x1080 | Full HD, detailed demos | 16:9 |\n| 1280x720 | Standard tutorials | 16:9 |\n| 1024x768 | Compact demos | 4:3 |\n| 800x600 | Small GIF output | 4:3 |\n\n### Playwright Video Size Configuration\n\n```typescript\n// In playwright.config.ts\nuse: {\n  video: {\n    mode: 'on',\n    size: { width: 1280, height: 720 }\n  },\n  viewport: { width: 1280, height: 720 }\n}\n```\n\n**Important:** Match `video.size` to `viewport` for best quality.\n\n### Per-Test Video Settings\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  video: {\n    mode: 'on',\n    size: { width: 1920, height: 1080 }\n  },\n  viewport: { width: 1920, height: 1080 }\n});\n\ntest('high-res demo', async ({ page }) => {\n  // Test runs at 1080p\n});\n```\n\n## Quality Considerations\n\n### Frame Rate\n\nPlaywright records at approximately 25 fps. This is sufficient for UI demos.\n\n### Bitrate\n\nWebM videos from Playwright use variable bitrate. Typical sizes:\n- 720p, 30 seconds: 2-5 MB\n- 1080p, 30 seconds: 5-10 MB\n\n### Minimizing File Size\n\n1. **Smaller viewport** - Reduce dimensions\n2. **Shorter duration** - Trim unnecessary pauses\n3. **Simple animations** - Fewer visual changes = smaller file\n\n## Playwright Video Configuration in Tests\n\n### Enable Video for Specific Tests\n\n```typescript\nimport { test } from '@playwright/test';\n\n// Enable video for this test file\ntest.describe.configure({ mode: 'serial' });\n\ntest.use({\n  video: 'on',\n  viewport: { width: 1280, height: 720 }\n});\n\ntest('recorded demo', async ({ page }) => {\n  await page.goto('https://example.com');\n  await page.waitForTimeout(1000);\n});\n```\n\n### Conditional Recording\n\n```typescript\nimport { test } from '@playwright/test';\n\nconst RECORD = process.env.RECORD === 'true';\n\ntest.use({\n  video: RECORD ? 'on' : 'off'\n});\n\ntest('conditionally recorded', async ({ page }) => {\n  // Only records when RECORD=true\n});\n```\n\n### Custom Video Directory\n\n```typescript\nimport { test } from '@playwright/test';\n\ntest.use({\n  contextOptions: {\n    recordVideo: {\n      dir: './custom-video-output',\n      size: { width: 1280, height: 720 }\n    }\n  }\n});\n```\n\n## Post-Processing with ffmpeg\n\n### Convert WebM to MP4\n\n```bash\nffmpeg -i video.webm -c:v libx264 -crf 23 output.mp4\n```\n\n### Extract Specific Time Range\n\n```bash\n# Extract from 0:05 to 0:15\nffmpeg -i video.webm -ss 00:00:05 -to 00:00:15 -c copy trimmed.webm\n```\n\n### Change Resolution\n\n```bash\n# Scale to 800px width, maintain aspect ratio\nffmpeg -i video.webm -vf \"scale=800:-1\" scaled.webm\n```\n\n### Speed Up Video\n\n```bash\n# 2x spe"},{"path":"skill-card.md","content":"## Description:\n\nRecords browser sessions via Playwright and converts video to GIF.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[athola](https://clawhub.ai/user/athola)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and technical writers use this skill to automate browser interactions with Playwright and produce WebM or GIF recordings for tutorials, documentation, and web application demos.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Browser recordings and GIFs can capture sensitive account data or private page content.\n\nMitigation: Record against sanitized demo or test accounts and review generated media before sharing.\n\nRisk: Untrusted Playwright specs or configs can drive browser actions outside the intended demo flow.\n\nMitigation: Use trusted specs and configs, review commands before execution, and keep dependencies pinned with a lockfile.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/athola/skills/nm-scry-browser-recording)\n- [clawdis homepage](https://github.com/athola/claude-night-market/tree/master/plugins/scry)\n- [Spec Execution Module](artifact/modules/spec-execution.md)\n- [Video Capture Module](artifact/modules/video-capture.md)\n\n## Skill Output:\n\n**Output Type(s):** [guidance, shell commands, code, configuration, markdown]\n\n**Output Format:** [Markdown with inline bash and TypeScript code blocks]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include Playwright spec and configuration snippets, recording file paths, and GIF conversion guidance.]\n\n## Skill Version(s):\n\n1.9.19 (source: server release metadata; artifact frontmatter lists 1.9.8)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Records browser sessions via Playwright and converts video to GIF Skill: browser-recording Owner: athola Summary: Records browser sessions via Playwright and converts video to GIF Tags: latest:1.9.19 Version history: v1.9.19 | 2026-08-26T13:22:46.041Z | user Release v1.9.19 v1.9.17 | 2026-07-30T05:42:37.119Z | user Release v1.9.17 v1.9.16 | 2026-07-14T19:59:28.809Z | user Release v1.9.16 v1.9.14 | 2026-06-30T18:06:55.013Z | user Release v1.9.14 v1.9.13 | 2026-06-27T16:24:47.231Z |","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1369,"uniquenessScore":51,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T08:34:12.773Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T08:34:12.773Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T10:56:42.880Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}