Skip to content
Agentmart
Submit a tool

pr-visual-diff

Capture before/after screenshots of UI views with Playwright and embed them in a PR.

Skill by jesdi

IndexedMIT
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/jesdi-pr-visual-diff

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Capture before/after screenshots of UI views with Playwright and embed them in a PR. Use this skill whenever creating or preparing a pull request that touches frontend code (components, views, styles, layout, Tailwind classes) — even if the user just says "open a PR" or "create the PR" after UI work, and especially if they mention screenshots, visual diff, before/after, or "show what changed". Also use when the user asks to add screenshots to an existing PR.

Use cases: design, frontend, testing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Node.js package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/pr-visual-diff

What's inside

Skill name
pr-visual-diff
Description
Capture before/after screenshots of UI views with Playwright and embed them in a PR. Use this skill whenever creating or preparing a pull request that touches frontend code (components, views, styles, layout, Tailwind classes) — even if the user just says "open a PR" or "create the PR" after UI work, and especially if they mention screenshots, visual diff, before/after, or "show what changed". Also use when the user asks to add screenshots to an existing PR.
License
MIT
Instructions
326 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Files (3)

  • SKILL.md
  • capture-caller.yml · references/
  • capture-spec-template.ts · references/

SKILL.md (first lines)

# PR Visual Diff

Produce before/after screenshots of the views affected by a branch's frontend
changes, push them to a hidden ref (never the PR branch), and embed them in the
PR body. Reviewers
should see what changed visually without checking out the branch.

The approach leans on the project's existing Playwright e2e harness with the
**API mocked**: because the data is stubbed and identical across both runs, any
pixel difference between "before" and "after" is caused by the code change
alone — that's the property that makes the comparison trustworthy. Never
screenshot against a live backend for this purpose.

Because every project wires this differently, the skill **discovers** the
project's setup once and caches it, then reuses the cache on later runs.

## Step 0. Load or build the per-project config

The config cache lives beside this skill at
`<skill-dir>/pr-visual-diff.<slug>.json`, where `<slug>` is the target repo's
directory name. It is gitignored — local to this machine. Ensure the cache file is ignored in the `.gitignore` of the repo where you install the skill directory (add an entry like `pr-visual-diff.*.json` if it isn't already).

- **If the cache exists**, read it and skip to "When NOT to run the capture".
  If it says `{"supported": false}`, tell the user this project has no
  mocked-API harness and create a plain PR (see Preconditions), then stop.
- **If it does not exist**, run the discovery pass below to build it.

### Discovery pass (first run only)

Inspect the target repo and record these values, then write them to the cache
file as JSON:

| Key | How to find it |
|---|---|
| `frontendDir` | the dir holding the app + its `src/` (repo root or a subdir like `frontend/`) |
| `e2eDir`, `specsDir` | the Playwright spec/support tree (look for `playwright.config.*`, a `specs/` dir) |
| `authFixtureImport`, `authFixtureName`, `authedPageProp` | the support file exporting a `test` fixture that seeds auth; note its import path, the exported name, and the authed-page property (e.g. `authenticatedPage`) |
| `mockHelperImport`, `mockHelperName` | the helper that stubs `/api` routes with fixture data; its import path + exported name |
| `port` | the `webServer` port in the Playwright config |
| `deviceProjects` | the config's `projects` (default to a desktop + a mobile project) |
| `baseBranch` | the repo's default branch (`main`/`master`; `git symbolic-ref refs/remotes/origin/HEAD`) |
| `packageManager` | infer from lockfile: `pnpm-lock.yaml`→pnpm, `package-lock.json`→npm, `yarn.lock`→yarn, `bun.lockb`→bun |
| `spinnerSelector` | every loading indicator of the app, as one selector list: spinners and skeletons (search for a spinner, `role="status"`, `aria-busy`, a skeleton component, `animate-pulse`), e.g. `.animate-spin, .animate-pulse`. A skeleton left out lets a half-loaded view pass as a good shot |

### Preconditions gate

The discovery pass is also the gate. **If there is no Playwright e2e harness
that mocks the API** (no mock helper, or no Playwright at all), write
`{ "supported": false, "reason": "<why>" }` to the cache, tell the user that a
trustworthy before/after diff isn't possible here (unmocked data would differ
between runs for reasons other than the code change), and **create a plain PR
instead** — no screenshots. Then stop.

## When NOT to run the capture

If `git diff --name-only $(git merge-base <baseBranch> HEAD)...HEAD` shows no
changes under `<frontendDir>/src/`, there is nothing visual to diff — create the
PR normally and say so. Test-only, docs-only, or backend-only diffs don't need
screenshots.

## Always run the capture in a subagent

Steps 2–6 (writing the spec, capturing, **reading every PNG back to eyeball
it**, pushing them to the hidden ref, embedding) MUST run inside a single dispatched subagent — not
in the main context. Reading screenshots back is this skill's dominant token
cost, and those image bytes are worthless to the main thread; keeping them in a
subagent's throwaway context is the whole savings, with no loss of verification.

Main context does only: step 1 (map the diff, get the user's go-ahead), then
dispatch a subagent with the plan and the config values. The subagent returns a
compact report: the screenshot file names + pinned URLs, the PR-body
markdown, and any views it flagged. The main context creates/edits the PR from
that report — it never reads a PNG.

## Where the capture runs

- **Local** (the default): steps 3–5 below, on this machine.
- **Remote**: when the session instructions say so (the agent-ops box does),
  or when this machine cannot start a Playwright browser. A GitHub workflow of
  the target repo captures both sides and pushes the hidden ref; see "Remote
  capture". Steps 1, 2 and 6 stay the same.

## Workflow

### 1. Map the diff to views, then get the user's go-ahead

List changed files against the merge base (`git merge-base <baseBranch> HEAD`).
For each changed component, trace upward (imports → page/route component → route
path) to find the route(s) where it renders, and note any interaction needed to
make it visible (open a modal, select a tab). Classify each view as **changed**
(existed at the merge base) or **new** (introduced by this branch) — new ones
get an after-only shot.

This capture is heavy (temp worktree, two Playwright passes, images pushed to a
hidden ref, PR body rewritten). ALWAYS confirm with AskUserQuestion before
running any of it. The question must cover **both** (a) whether to run the whole
before/after capture at all, and (b) that it will push the screenshots to a
hidden ref on the remote and embed them in the PR. Include the proposed plan: which routes/states, and which
device projects — default to the config's `deviceProjects`; add more only when
the change is layout-sensitive. If they decline, create the PR normally and stop.

In an unattended session (nobody answers questions, as on the agent-ops box),
do not ask: run the capture with the plan above and name the plan in the PR
body.

### 2. Write the capture spec

Copy `references/capture-spec-template.ts` from this skill into
`<specsDir>/__pr-capture__.spec.ts` and substitute the `__PVD_*__` markers from
the config:

- `__PVD_AUTH_FIXTURE_IMPORT__` → `authFixtureImport` (and, if the fixture isn't
  named `test`, adjust the `import { <authFixtureName> as test }` accordingly)
- `__PVD_MOCK_HELPER_IMPORT__` → `mockHelperImport` (and `mockHelperName` if not
  `mockApi`)
- `__PVD_SPINNER_SELECTOR__` → `spinnerSelector`
- the `{ authenticatedPage: page }` destructure → `{ <authedPageProp>: page }`

Then fill in the `VIEWS` array. This file is scaffolding: never commit it, and

From jesdi/general-skills, MIT.

More from jesdi/general-skills

Signals

Stars
0
Forks
0
Open issues
23
Last commit (this folder)
Oct 15, 2026 (14 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from jesdi

Cite this page

pr-visual-diff skill. Agent Mart. https://agentmart.dev/skills/jesdi-pr-visual-diff (last updated 2026-10-24)