Skip to content
Development
Skill

/visual-diff-branches

Use when the question is how pages render on one git ref versus another: checking a design-system, tokens, typography or styling PR for visual regressions on your feature's pages, producing before/after screenshots for a designer, answering 'did this branch change how X looks',

From plugin
agent-skills
1240 skills

Claude Code

$ npx -y skills add Flagrare/agent-skills --skill visual-diff-branches --agent claude-code

SKILL.md

visual-diff-branches.SKILL.md
name: visual-diff-branches
description: "Use when the question is how pages render on one git ref versus another: checking a design-system, tokens, typography or styling PR for visual regressions on your feature's pages, producing before/after screenshots for a designer, answering 'did this branch change how X looks', or when a screenshot comparison is needed and no image library (ImageMagick, Pillow, sharp, pixelmatch) is installed. Triggers on 'compare main vs this branch', 'before and after screenshots', 'visual regression on this PR', 'what changed visually', 'side by side for design'."

Visual Diff Branches

Answer "what does this branch change on these pages" with evidence: the same pages captured on each ref, pixel-diffed to show *where*, and measured with computed styles to show *what*. Everything runs on the browser the project already has (Playwright's Chromium), so nothing gets installed.

Scripts live in `scripts/` next to this file. They resolve `@playwright/test` from the **project's** `node_modules`, so run them with the project root as the working directory and pass the scripts by absolute path. The only file you write per project is a `shots.mjs` config (contract in `references/config.md`, worked example in `references/shots.example.mjs`).

---

Step 1: Decide what "the branch" means

A PR branch is usually behind its base. Comparing the raw branch against main mixes the PR's own changes with every fix main landed since the branch forked, and those show up as regressions the PR did not cause. Decide up front and say which one you compared:

| Question | Compare | |---|---| | "What will land if this merges?" (the usual case) | a throwaway branch: `git checkout -B smoke/<name> origin/<branch> && git merge --no-edit origin/main` | | "What does the branch look like exactly as pushed?" | the branch itself |

Check `git rev-list --count origin/<branch>..origin/main` and quote the number in the report. If a difference appears on the raw branch but not on the merged one, it is a missing main fix, not a PR finding; say so and name the commit (`git log --oneline origin/<branch>..origin/main -- <file>`).

Tell the user before the first checkout. Their working tree is about to change branches under a running dev server.

Step 2: Write `shots.mjs`

One config per project, kept out of git (`.build/` or the scratchpad). It names the base URL, the saved login state, the locales and viewports, the shot list (a URL plus an optional `after(page)` that clicks into a flyout, picks a menu, opens an editor), and the measurement targets. See `references/config.md`.

Pick pages that exercise what the branch touches: a list with a table, a form with inputs and buttons, a flyout or modal, an empty state. Include every locale the product ships if the change is typographic; a font-size change can be harmless in one script and unreadable in another.

Probe each URL once before running the matrix. One URL that redirects to login or fires a logout call (a venue the saved session cannot open, for example) turns every later shot in the run into a login page. Drop it or switch to a URL the session can reach.

Step 3: Capture, one variant at a time

pnpm exec playwright test --project=setup          # or whatever refreshes the saved session
node <skill>/scripts/capture.mjs ./shots.mjs main ./shots
git checkout -B smoke/pr origin/feat/pr && git merge --no-edit origin/main
<skill>/scripts/wait-for-rebuild.sh <dev-server-log> <any-watched-source-file>
pnpm exec playwright test --project=setup
node <skill>/scripts/capture.mjs ./shots.mjs pr ./shots

Three things the loop above encodes, learned the hard way:

  • **Refresh the saved session before every variant.** Sessions expire in well under an hour; a run that outlives one silently produces login pages from that point on, all the same file size.
  • **Wait for a clean compile after a checkout.** The watcher usually compiles once mid-checkout (missing modules) and once clean. `wait-for-rebuild.sh` waits for a new compile line without errors and re-touches a file when the last one was dirty.
  • **Read the size column.** `capture.mjs` prints the rendered page size per shot. A shot that is viewport-height when its siblings are three screens tall was captured on a spinner; re-run it with `--only <name>`.

Run capture with the sandbox disabled when your agent sandbox blocks `localhost`.

Step 4: Measure, do not squint

Pixel diffs locate a change; they cannot tell a 3px radius from a pill, or 16px from 14px. Run the measurement pass on each variant and compare:

node <skill>/scripts/measure.mjs ./shots.mjs main ./shots
node <skill>/scripts/measure.mjs ./shots.mjs pr ./shots
node <skill>/scripts/compare-measures.mjs ./shots main pr

Targets are Playwright locators, so use text and roles (`getByText('Save changes')`, `getByRole('button', …)`) that survive markup changes. Mark containers with `box: true` to also record background, border, radius, padding, height and width. The compare output lists only rows that differ, with the base value first.

Every finding in the report should rest on a measured pair, not on how a screenshot looks. "Buttons look rounder" becomes "button radius 3px → 80px on Save, Cancel, New Modifier", which the author can act on and the reviewer can verify.

Step 5: Diff and compose

node <skill>/scripts/diff.mjs ./shots main pr
node <skill>/scripts/compose.mjs ./shots main pr ./for-design --labels "main (today)|design-system PR" \
     modifiers.en.1280.png:190,80,900,600 item-flyout.en.1280.png

`diff.mjs` writes `diff-pr/<file>.png` with changed pixels in red over a faded base and prints changed %, both sizes and the bounding box per file. Use the table to pick which shots deserve a composite; a 0.3% change confined to one row is a note, a 7% change across the page is a screenshot. Read at least two diff images before describing a variant as "only X changed". A localized red blob you did not expect

Read more
@flagrare
Ships withagent-skills

Thirty-eight skills that wrap around your development cycle in Claude Code. They turn tickets into ATDD plans, smoke-test features against a running app or service, hunt down bugs with runtime evidence, guard commits against doc drift, run seven-axis code

Stars on GitHub

Momentum

stars in total
12
Star history of Flagrare/agent-skills on GitHub, a chart by star-history.com

Other skills on agent-skills.

atdd-plan

atdd-plan

Produce an ATDD-first implementation plan in Claude Code's native plan mode, with named design patterns called out where they…

brag-doc

brag-doc

Generate a comprehensive, impact-framed brag-doc entry for a chosen time window (day, week, biweek, month, or custom). Pulls…

bug-bash

bug-bash

Programmatic bug bashing, ingest a prescribed test plan (Notion, markdown, pasted spec), drive a real running system (browser via…

career

career

Run the career skills that are due, in one pass, and return one short combined digest plus an updated board. It reads timestamps…

codebase-explore

codebase-explore

Explore the codebase to map conventions, reusable utilities, analogous features, and data flows relevant to a planned change.…

daily-code-review

daily-code-review

Generate a daily code review report showing stale PRs, items needing your attention, and active work for your team. Use whenever…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about visual-diff-branches.

Which coding agents can use visual-diff-branches?
visual-diff-branches installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.