Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Capture Playwright screenshots and embed them in GitHub PR descriptions
.claude/skills/github-pr-screenshots/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -26% | 0% |
| case-02 | ✗→✓ | ▲ Improved | -15% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 69% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 21% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 2% | 0% |
When a PR includes visual changes (docs sites, UI components, generated pages), reviewers need to see what the PR delivers without checking out the branch. Screenshots belong in the PR description body, not as committed files and not as text descriptions.
Use this skill whenever:
If Playwright tests already exist and produce screenshots, reuse those. Otherwise, write a minimal capture script:
javascript// scripts/capture-pr-screenshots.mjs import { chromium } from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: 1280, height: 720 } }); const screenshots = [ { url: 'http://localhost:4321/path/to/page', name: 'feature-landing' }, { url: 'http://localhost:4321/path/to/detail', name: 'feature-detail' }, ]; for (const { url, name } of screenshots) { await page.goto(url, { waitUntil: 'networkidle' }); await page.screenshot({ path: `screenshots/${name}.png`, fullPage: false }); } await browser.close();
GitHub PR descriptions render images via URLs. The gh CLI cannot upload binary images directly. Use a temporary orphan branch to host the images:
powershell# Save current branch $currentBranch = git branch --show-current # Create orphan branch with only screenshot files git checkout --orphan screenshots-temp git reset git add screenshots/*.png git commit -m "screenshots for PR review" git push origin screenshots-temp --force # Build raw URLs $base = "https://raw.githubusercontent.com/{owner}/{repo}/screenshots-temp/screenshots" # Each image: $base/{name}.png # Return to working branch git checkout -f $currentBranch
Use gh pr edit with the raw URLs embedded as markdown images:
powershell$base = "https://raw.githubusercontent.com/{owner}/{repo}/screenshots-temp/screenshots" gh pr edit {PR_NUMBER} --repo {owner}/{repo} --body @" ## {PR Title} ### What this PR delivers - {bullet points of changes} --- ### Screenshots #### {Page/Feature Name}  #### {Another Page}  --- ### To verify locally
{commands to run locally}
"@After the PR is merged, delete the temporary branch:
bashgit push origin --delete screenshots-temp
Screenshots are build artifacts — never commit them to feature branches:
gitignore# PR screenshots (hosted on temp branch, not committed to features) screenshots/ docs/tests/screenshots/
cd docs && npm run devscreenshots-temp branch![...]() image referencesIf tests at docs/tests/*.spec.mjs already save to docs/tests/screenshots/:
powershellcd docs && npx playwright test tests/api-reference.spec.mjs # Screenshots now at docs/tests/screenshots/*.png # Push those to screenshots-temp and embed in PR
gh CLI to "upload" images — gh issue comment and gh pr edit don't support binary uploads| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 26,151 | 11,022 | -58% | 1 | 1 | 0% | 3,974 | 2,949 | -26% | 0 | 0 | — |
case-02 | fail→pass | 18,426 | 9,244 | -50% | 1 | 1 | 0% | 2,995 | 2,552 | -15% | 0 | 0 | — |
case-03 | fail→fail | 20,548 | 9,808 | -52% | 1 | 1 | 0% | 3,310 | 2,792 | -16% | 0 | 0 | — |
case-04 | fail→fail | 10,150 | 3,668 | -64% | 1 | 1 | 0% | 1,553 | 1,574 | +1% | 0 | 0 | — |
case-05 | pass→pass | 15,526 | 16,147 | +4% | 1 | 1 | 0% | 2,721 | 3,560 | +31% | 0 | 0 | — |
case-06 | fail→pass | 8,429 | 8,548 | +1% | 1 | 1 | 0% | 1,421 | 2,408 | +69% | 0 | 0 | — |
case-07 | pass→pass | 11,161 | 6,998 | -37% | 1 | 1 | 0% | 1,589 | 2,136 | +34% | 0 | 0 | — |
case-08 | fail→pass | 12,042 | 8,978 | -25% | 1 | 1 | 0% | 1,870 | 2,269 | +21% | 0 | 0 | — |
case-09 | fail→pass | 12,828 | 13,765 | +7% | 1 | 1 | 0% | 2,012 | 2,061 | +2% | 0 | 0 | — |
case-10 | pass→pass | 3,054 | 2,354 | -23% | 1 | 1 | 0% | 380 | 1,365 | +259% | 0 | 0 | — |
case-11 | fail→pass | 8,169 | 4,952 | -39% | 1 | 1 | 0% | 1,296 | 1,848 | +43% | 0 | 0 | — |
case-12 | pass→pass | 12,702 | 6,814 | -46% | 1 | 1 | 0% | 1,790 | 2,044 | +14% | 0 | 0 | — |
case-13 | pass→pass | 12,136 | 5,496 | -55% | 1 | 1 | 0% | 1,910 | 2,039 | +7% | 0 | 0 | — |
case-14 | fail→pass | 17,244 | 7,930 | -54% | 1 | 1 | 0% | 2,120 | 2,314 | +9% | 0 | 0 | — |
case-15 | fail→pass | 18,026 | 8,292 | -54% | 1 | 1 | 0% | 2,561 | 2,303 | -10% | 0 | 0 | — |
case-16 | fail→pass | 13,484 | 7,237 | -46% | 1 | 1 | 0% | 2,010 | 2,156 | +7% | 0 | 0 | — |
case-17 | fail→pass | 29,817 | 11,808 | -60% | 1 | 1 | 0% | 3,084 | 3,026 | -2% | 0 | 0 | — |
case-18 | fail→pass | 13,102 | 7,092 | -46% | 1 | 1 | 0% | 2,139 | 2,160 | +1% | 0 | 0 | — |
case-19 | pass→pass | 11,131 | 6,778 | -39% | 1 | 1 | 0% | 1,575 | 2,060 | +31% | 0 | 0 | — |
case-20 | fail→pass | 17,056 | 15,269 | -10% | 1 | 1 | 0% | 2,437 | 3,285 | +35% | 0 | 0 | — |
case-21 | pass→pass | 16,309 | 12,554 | -23% | 1 | 1 | 0% | 2,477 | 3,067 | +24% | 0 | 0 | — |
case-22 | fail→pass | 10,438 | 5,545 | -47% | 1 | 1 | 0% | 1,748 | 1,962 | +12% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +59 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.