Skip to content

Instantly share code, notes, and snippets.

@xadn
Last active March 13, 2026 18:10
Show Gist options
  • Select an option

  • Save xadn/b2a54c8d819e1adec16b39ee33e4e15c to your computer and use it in GitHub Desktop.

Select an option

Save xadn/b2a54c8d819e1adec16b39ee33e4e15c to your computer and use it in GitHub Desktop.
Claude Code skill: Record browser interactions as demo GIFs for PR demos
name description
demo-gif
Record concise demo GIFs for feature branches using browser automation. Use when asked to "record a demo", "make a gif", "capture the feature", "show the PR in action", or demonstrate UI changes for pull requests.

Demo GIF

Record browser interactions as GIF for PR demos using chrome-devtools MCP.

Workflow (Sequential - Do Not Skip Steps)

Step 1: Understand the Feature

Before touching the browser, understand what to demo:

  • Read the branch name and recent commits (gt log -5)
  • Check for Linear ticket context if branch name contains ticket ID
  • Identify the core user-visible change (what should the viewer notice?)

Step 2: Explore in Browser

Navigate to the feature and interact manually (no recording yet):

  • Open a new Chrome window and tab (new_page)
  • Find the UI location where the feature lives
  • Identify any required setup state (logged in, specific page, data needed)
  • Note the exact interaction sequence needed

Step 3: Define the Demo Plan

Before recording, explicitly state:

Demo plan:
- Starting URL: [url]
- Setup needed: [any prerequisites]
- Frame plan (each frame = one screenshot):
  1. [initial state - before action]
  2. [after action 1]
  3. [after action 2]
  ...
  N. [final result]
- Expected frame count: [N frames]
- Frame delays: [e.g., "hold first/last 2s, others 0.8s"]

Step 4: Practice Run

Execute the full interaction sequence WITHOUT capturing frames:

  • Verify all steps work as expected
  • Confirm the UI settles cleanly after each action
  • Adjust plan if needed

Step 5: Capture Frames

Only after successful practice run, capture:

# Create a temp directory for frames
mkdir -p /tmp/demo-gif/frames

Then for each step in the demo plan:

1. Take screenshot of initial state
   mcp__chrome-devtools__take_screenshot filePath="/tmp/demo-gif/frames/001.png"

2. Perform interaction
   mcp__chrome-devtools__click uid="..."
   # or press_key, type_text, etc.

3. Wait for UI to settle (use wait_for or a brief pause)

4. Take screenshot of result
   mcp__chrome-devtools__take_screenshot filePath="/tmp/demo-gif/frames/002.png"

5. Repeat for each interaction step, incrementing the frame number

Step 6: Assemble GIF

Use ffmpeg to stitch frames into an animated GIF:

# Standard assembly — 1.2s per frame, loop forever
ffmpeg -framerate 0.83 -i /tmp/demo-gif/frames/%03d.png \
  -vf "fps=10,split[s0][s1];[s0]palettegen=stats_mode=diff[p];[s1][p]paletteuse=dither=bayer" \
  -loop 0 /tmp/demo-gif/<branch-name>-demo.gif

For custom per-frame delays (e.g., hold first/last frames longer), use gifsicle to adjust after assembly:

# First assemble with uniform timing, then adjust specific frame delays
# Delay units: 1/100s (so -d200 = 2s, -d80 = 0.8s)
gifsicle /tmp/demo-gif/<branch-name>-demo.gif \
  -d200 "#0" \
  -d80 "#1" "#2" "#3" \
  -d200 "#4" \
  --loop -O3 \
  -o /tmp/demo-gif/<branch-name>-demo.gif

For frame holds (repeat a frame to hold longer without changing delay):

# Duplicate the last frame 3x to hold on the result
gifsicle /tmp/demo-gif/<branch-name>-demo.gif \
  "#0-3" "#3" "#3" "#3" \
  --loop -O3 \
  -o /tmp/demo-gif/<branch-name>-demo.gif

Step 7: Review and Open

# Open the directory in Finder (use Quick Look / spacebar to preview)
open /tmp/demo-gif/

Preview.app only shows still frames — use Quick Look (spacebar in Finder) to play the GIF.

Tool Reference

# Tab/page management
mcp__chrome-devtools__list_pages       # List open tabs
mcp__chrome-devtools__new_page         # Open new tab (with optional URL)
mcp__chrome-devtools__select_page      # Switch to a tab
mcp__chrome-devtools__navigate_page    # Navigate current tab to URL
mcp__chrome-devtools__close_page       # Close a tab

# Interaction
mcp__chrome-devtools__take_snapshot    # A11y tree snapshot (find element uids)
mcp__chrome-devtools__click            # Click element by uid
mcp__chrome-devtools__type_text        # Type text
mcp__chrome-devtools__press_key        # Press key (e.g., Enter, cmd+e)
mcp__chrome-devtools__fill             # Fill an input field
mcp__chrome-devtools__hover            # Hover over element
mcp__chrome-devtools__drag             # Drag element
mcp__chrome-devtools__wait_for         # Wait for element/condition
mcp__chrome-devtools__evaluate_script  # Run arbitrary JS

# Capture
mcp__chrome-devtools__take_screenshot  # Screenshot (filePath to save to disk)

Filename Convention

Use branch name or feature description:

  • andy-ai-2045-style-upload-demo.gif
  • image-panel-collapse-demo.gif

Tips

  • Keep it short: 5-10 frames covers most features
  • Show the "before": Hold on the initial state so viewers orient themselves
  • Hold the result: Duplicate the final frame so viewers see the end state
  • One feature per GIF: Don't combine unrelated changes
  • Keyboard shortcuts: Use press_key with cmd+e for agent panel, Enter to submit
  • Wait after actions: Use wait_for or take a snapshot to let UI settle before capturing
  • Target size: Keep under 10MB for GitHub/Graphite — use gifsicle --lossy=80 -O3 to compress
  • Always loop: PR GIFs should loop forever (-loop 0 in ffmpeg, --loop in gifsicle)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment