# Tier: Browser Reel Capture 3-5 browser screenshots at key UI states and stitch into an animated GIF. **Best for:** Web apps, desktop apps accessible via localhost or CDP. **Output:** GIF (PNG screenshots stitched via ffmpeg two-pass palette) **Label:** "Demo" **Required tools:** agent-browser, ffmpeg ## Step 1: Connect to the Application **For web apps** -- verify the dev server is accessible: - Read `package.json` `scripts` for `dev`, `start`, `serve` commands - Check `Procfile`, `Procfile.dev`, or `bin/dev` if they exist - Check `Gemfile` for Rails (`bin/rails server`) or Sinatra - Check for running processes on common ports (3000, 5000, 8080) If the server is not running, tell the user what start command was detected and ask them to start it. Do not start it automatically (it may require environment variables, database setup, etc.). If the server cannot be reached after the user confirms it should be running, fall back to static screenshots tier. Once accessible, note the base URL (e.g., `http://localhost:3000`). **For Electron/desktop apps** -- connect via Chrome DevTools Protocol (CDP): 1. Check if the app is already running with CDP enabled by probing common ports: ```bash curl -s http://localhost:9222/json/version ``` If that returns a JSON response, the app is ready -- connect agent-browser to it: ```bash agent-browser connect 9222 ``` 2. If not running, the app needs to be launched with `--remote-debugging-port`. Detect the entry point from `package.json` (look for the `main` field or `electron` in scripts), then ask the user to launch it with: ``` your-electron-app --remote-debugging-port=9222 ``` If port 9222 is busy, try 9223-9230. 3. Poll until CDP is ready (timeout after 30 seconds): ```bash curl -s http://localhost:9222/json/version ``` 4. Connect agent-browser: ```bash agent-browser connect 9222 ``` **CDP advantages:** Screenshots come from the renderer's frame buffer, not macOS screen capture -- no Accessibility or Screen Recording permissions needed. **If CDP connection fails:** Fall back to static screenshots tier. Tell the user: "Could not connect to the app via CDP. Falling back to static screenshots." ## Step 2: Capture Screenshots Navigate to the relevant pages and capture 3-5 screenshots at key UI states: 1. **Initial/empty state** -- Before the feature is used 2. **Navigation** -- How the user reaches the feature (if not the landing page) 3. **Feature in action** -- The hero shot showing the feature working 4. **Result state** -- After interaction (data present, items created, success message) 5. **Detail view** (optional) -- Expanded item, settings panel, modal For each screenshot, write to the concrete `RUN_DIR` created by the parent skill: ```bash agent-browser open [URL] ``` ```bash agent-browser wait 2000 ``` ```bash agent-browser screenshot [RUN_DIR]/frame-01-initial.png ``` **Capture tips:** - Use URL navigation (`agent-browser open URL`) rather than clicking SPA elements (clicks often fail on React/Vue/Svelte SPAs) - Wait 2-3 seconds after navigation for the page to settle - Capture the full viewport (sidebar, header give reviewers context) ## Step 3: Stitch into GIF Use the capture pipeline script to normalize frame dimensions, stitch with two-pass palette, and auto-reduce if over 10 MB: ```bash python3 scripts/capture-demo.py stitch [RUN_DIR]/demo.gif [RUN_DIR]/frame-*.png ``` The script handles dimension normalization (via ffprobe + ffmpeg padding), concat demuxer stitching, palette generation, and automatic frame reduction if the GIF exceeds GitHub's 10 MB inline limit. Default is 3 seconds per frame. To adjust: ```bash python3 scripts/capture-demo.py stitch --duration 2.0 [RUN_DIR]/demo.gif [RUN_DIR]/frame-*.png ``` **If stitching fails:** Fall back to static screenshots tier using the individual PNGs already captured. If no PNGs were captured, report the failure. ## Step 4: Cleanup After successful GIF creation, remove individual PNG frames. Keep only the final GIF for upload. Proceed to `references/upload-and-approval.md`.