| name | screenshot-handling |
| description | Ensures all screenshots are saved to a dedicated screenshots/ folder instead of project root. Use when capturing screenshots via agent-browser, Playwright, Puppeteer, or any other screenshot capture method to maintain project organization. |
Screenshot Handling
⚠️ CRITICAL REQUIREMENT ⚠️
SAVING SCREENSHOTS TO PROJECT ROOT IS FORBIDDEN.
ALL screenshots MUST be saved to the screenshots/ folder. There are NO exceptions.
Validation Checklist
Before capturing ANY screenshot, verify:
- ✅
screenshots/ folder exists (create with mkdir -p screenshots/)
- ✅ Screenshot command includes
screenshots/ in the path
- ✅ Path format:
screenshots/filename.png (NOT filename.png)
Correct vs Incorrect Examples
✅ CORRECT - Screenshots in screenshots/ folder:
screenshots/mainmenu-verification.png
screenshots/timer-test.png
screenshots/game-over-state.png
screenshots/ui-validation.png
❌ INCORRECT - Screenshots in project root (FORBIDDEN):
mainmenu-verification.png (project root)
timer-test.png (project root)
game-over-state.png (project root)
verification.png (project root)
If you discover screenshots in the project root, move them immediately to screenshots/ folder.
Screenshot path: Use project root or absolute path for the screenshot directory so CWD does not cause wrong locations. When saving to screenshots/, ensure CWD is project root.
Pre-completion (web tasks): For frontend/web tasks, do not skip browser verification; if agent-browser is loaded, at least one browser action (open, navigate, submit, or capture) must be performed before marking complete, unless documented as impossible (e.g. backend down) with fallback. For scaffold-only tasks, at least open the app URL and capture one screenshot to confirm the shell renders.
Overview
Screenshots should always be saved to a dedicated screenshots/ folder instead of the project root directory. This keeps the project root clean and organized, making it easier to manage and locate screenshot files.
Problem: Screenshots saved to project root create clutter and make it difficult to manage project files.
Solution: Always save screenshots to screenshots/ folder, creating it if it doesn't exist.
Required Behavior
ALWAYS save screenshots to the screenshots/ folder:
- ✅
screenshots/mainmenu-verification.png
- ✅
screenshots/timer-test.png
- ✅
screenshots/game-over-state.png
- ❌
mainmenu-verification.png (project root)
- ❌
timer-test.png (project root)
Folder Creation
Always ensure the screenshots/ folder exists before saving screenshots.
Bash/Shell
mkdir -p screenshots/
agent-browser screenshot screenshots/mainmenu-verification.png
Node.js/TypeScript
import fs from 'fs';
fs.mkdirSync('screenshots', { recursive: true });
await page.screenshot({ path: 'screenshots/mainmenu-verification.png' });
Python
import os
os.makedirs('screenshots', exist_ok=True)
page.screenshot(path='screenshots/mainmenu-verification.png')
Methods Covered
agent-browser Screenshot Commands
CRITICAL: ALWAYS create the screenshots/ folder FIRST, then specify the screenshots/ folder path:
mkdir -p screenshots/
agent-browser screenshot screenshots/mainmenu-verification.png
agent-browser screenshot screenshots/timer-test.png
agent-browser screenshot screenshots/game-over-state.png
agent-browser screenshot --full screenshots/full-page.png
❌ FORBIDDEN - Never save to project root:
agent-browser screenshot mainmenu-verification.png
agent-browser screenshot verification.png
✅ CORRECT - Always include screenshots/ in path:
mkdir -p screenshots/
agent-browser screenshot screenshots/mainmenu-verification.png
Reference: See agent-browser skill for complete screenshot command syntax.
Playwright Screenshot Methods
Always use screenshots/ folder path:
import { chromium } from 'playwright';
import fs from 'fs';
fs.mkdirSync('screenshots', { recursive: true });
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('http://localhost:5173');
await page.screenshot({ path: 'screenshots/mainmenu-verification.png' });
await page.screenshot({
path: 'screenshots/full-page.png',
fullPage: true
});
await browser.close();
Puppeteer Screenshot Methods
Always use screenshots/ folder path:
import puppeteer from 'puppeteer';
import fs from 'fs';
fs.mkdirSync('screenshots', { recursive: true });
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://localhost:5173');
await page.screenshot({ path: 'screenshots/mainmenu-verification.png' });
await page.screenshot({
path: 'screenshots/full-page.png',
fullPage: true
});
await browser.close();
Other Screenshot Capture Tools
For any other screenshot capture method:
- Create
screenshots/ folder if it doesn't exist
- Always specify
screenshots/filename.png as the output path
- Never save to project root
Naming Conventions
Use descriptive filenames with context:
- ✅
screenshots/mainmenu-verification.png - Clear purpose
- ✅
screenshots/timer-test-10seconds.png - Includes test context
- ✅
screenshots/game-over-state.png - Describes state
- ✅
screenshots/ui-validation-mainmenu.png - Includes validation context
- ✅
screenshots/2026-01-25-mainmenu.png - Includes date if needed
- ❌
screenshots/screenshot.png - Too generic
- ❌
screenshots/test.png - Not descriptive
Recommended patterns:
screenshots/{feature}-{state}.png - e.g., mainmenu-default.png
screenshots/{feature}-{test-context}.png - e.g., timer-test-5seconds.png
screenshots/{validation-type}-{scene}.png - e.g., ui-validation-mainmenu.png
Migration
When discovering screenshots in project root, move them to screenshots/ folder:
Manual Migration
mkdir -p screenshots/
mv *.png screenshots/ 2>/dev/null || true
mv mainmenu-verification.png screenshots/
mv timer-test.png screenshots/
Automated Migration Script
#!/bin/bash
mkdir -p screenshots/
find . -maxdepth 1 -name "*.png" -type f ! -path "./node_modules/*" ! -path "./.git/*" -exec mv {} screenshots/ \;
echo "Screenshots migrated to screenshots/ folder"
Verification
After migration, verify screenshots are in the correct location:
ls -la screenshots/
find . -maxdepth 1 -name "*.png" -type f ! -path "./node_modules/*" ! -path "./.git/*"
Troubleshooting
Screenshots Ended Up in Wrong Location
If you discover screenshots in the project root instead of screenshots/ folder:
-
Verify the issue:
find . -maxdepth 1 -name "*.png" -type f
-
Create screenshots folder if missing:
mkdir -p screenshots/
-
Move misplaced screenshots:
mv *.png screenshots/ 2>/dev/null || true
mv mainmenu-verification.png screenshots/
mv timer-test.png screenshots/
-
Verify migration:
ls -la screenshots/
find . -maxdepth 1 -name "*.png" -type f
-
Prevent future issues:
- Always run
mkdir -p screenshots/ before capturing screenshots
- Always include
screenshots/ in the screenshot path
- Review this skill's instructions before capturing screenshots
Common Mistakes
Mistake 1: Forgetting to create folder
agent-browser screenshot screenshots/test.png
mkdir -p screenshots/
agent-browser screenshot screenshots/test.png
Mistake 2: Missing screenshots/ in path
agent-browser screenshot test.png
agent-browser screenshot screenshots/test.png
Mistake 3: Using relative path without screenshots/
page.screenshot({ path: 'verification.png' })
page.screenshot({ path: 'screenshots/verification.png' })
Screenshot Freshness Verification
Verify Screenshots Are Current
Always verify screenshots are current before using them for verification:
agent-browser reload
agent-browser wait 2000
agent-browser screenshot screenshots/verification.png
Timestamp Verification Techniques
Pattern 1: Check File Timestamp
ls -l screenshots/verification.png
file_age=$(($(date +%s) - $(stat -f %m screenshots/verification.png)))
if [ $file_age -lt 10 ]; then
echo "Screenshot is fresh"
else
echo "Screenshot may be stale"
fi
Pattern 2: Timestamp in Filename
timestamp=$(date +%Y%m%d_%H%M%S)
agent-browser screenshot "screenshots/verification-${timestamp}.png"
Pattern 3: Browser State Verification
agent-browser eval "
const state = {
url: window.location.href,
timestamp: Date.now(),
testSeamReady: window.__TEST__?.ready || false
};
JSON.stringify(state)
"
agent-browser screenshot screenshots/verification.png
Detecting Stale Screenshots
Check for stale screenshots:
check_screenshot_freshness() {
local screenshot=$1
local max_age=30
if [ ! -f "$screenshot" ]; then
echo "Screenshot not found"
return 1
fi
local file_age=$(($(date +%s) - $(stat -f %m "$screenshot")))
if [ $file_age -gt $max_age ]; then
echo "Screenshot is stale (${file_age}s old)"
return 1
fi
echo "Screenshot is fresh"
return 0
}
Force Browser Refresh Before Capture
Always refresh browser before capturing verification screenshots:
agent-browser reload
agent-browser wait 2000
agent-browser eval "
const lastReload = window.__HMR_LAST_RELOAD__ || 0;
const now = Date.now();
const timeSinceReload = now - lastReload;
timeSinceReload < 5000 ? 'Recently reloaded' : 'Stale state'
"
agent-browser screenshot screenshots/verification.png
Timing Considerations
When to Wait for Scene Transitions/Updates
Wait for scene transitions before capturing:
agent-browser eval "window.__TEST__.commands.goToScene('GameScene')"
agent-browser wait 500
agent-browser eval "
new Promise((resolve) => {
const check = () => {
if (window.__TEST__?.ready) {
resolve(true);
} else {
setTimeout(check, 100);
}
};
check();
})
"
agent-browser screenshot screenshots/gamescene-ready.png
Verify HMR Has Applied Changes Before Screenshots
Always verify HMR has applied changes before capturing:
agent-browser eval "
const lastReload = window.__HMR_LAST_RELOAD__ || 0;
const now = Date.now();
const timeSinceReload = now - lastReload;
timeSinceReload < 5000 ? 'HMR applied' : 'HMR not applied'
"
if [ "$hmr_status" != "HMR applied" ]; then
agent-browser reload
agent-browser wait 2000
fi
agent-browser screenshot screenshots/after-change.png
Explicit Wait Patterns for Dynamic Content
Wait for dynamic content before capturing:
agent-browser eval "
new Promise((resolve) => {
const check = () => {
if (document.querySelector('.content-loaded')) {
resolve(true);
} else {
setTimeout(check, 100);
}
};
check();
})
"
agent-browser wait 1000
agent-browser screenshot screenshots/content-loaded.png
Pattern for Phaser Games:
agent-browser eval "window.__TEST__?.ready || false"
agent-browser eval "
const state = window.__TEST__?.gameState?.();
state && state.initialized ? true : false
"
agent-browser wait 500
agent-browser screenshot screenshots/game-ready.png
Batch Screenshot Operations
Patterns for Capturing Multiple Screenshots Efficiently
Pattern 1: Sequential Screenshots with Minimal Waits
mkdir -p screenshots/
agent-browser open "http://localhost:5173?scene=MainMenu"
agent-browser wait 1000
agent-browser screenshot screenshots/mainmenu.png
agent-browser eval "window.__TEST__.commands.goToScene('GameScene')"
agent-browser wait 500
agent-browser screenshot screenshots/gamescene.png
agent-browser eval "window.__TEST__.commands.triggerGameOver()"
agent-browser wait 500
agent-browser screenshot screenshots/gameover.png
Pattern 2: Batch Screenshots with State Verification
capture_screenshot_with_state() {
local scene=$1
local filename=$2
agent-browser eval "window.__TEST__.commands.goToScene('$scene')"
agent-browser wait 500
agent-browser eval "window.__TEST__?.sceneKey === '$scene'"
agent-browser screenshot "screenshots/$filename"
}
capture_screenshot_with_state "MainMenu" "mainmenu.png"
capture_screenshot_with_state "GameScene" "gamescene.png"
capture_screenshot_with_state "GameOverScene" "gameover.png"
When to Use Comparison Screenshots (Before/After)
Use before/after screenshots for verification:
agent-browser screenshot screenshots/before-change.png
agent-browser reload
agent-browser wait 2000
agent-browser screenshot screenshots/after-change.png
When to Use Before/After:
- Verifying code changes
- Testing visual regressions
- Documenting changes
- Debugging layout issues
Caching Strategies to Avoid Redundant Captures
Pattern 1: Check Screenshot Age Before Capture
should_capture_screenshot() {
local screenshot=$1
local max_age=60
if [ ! -f "$screenshot" ]; then
return 0
fi
local file_age=$(($(date +%s) - $(stat -f %m "$screenshot")))
if [ $file_age -gt $max_age ]; then
return 0
fi
return 1
}
if should_capture_screenshot "screenshots/mainmenu.png"; then
agent-browser screenshot screenshots/mainmenu.png
else
echo "Using cached screenshot"
fi
Pattern 2: Hash-Based Caching
get_state_hash() {
agent-browser eval "
const state = {
scene: window.__TEST__?.sceneKey,
score: window.__TEST__?.gameState?.()?.score
};
JSON.stringify(state)
" | md5sum | cut -d' ' -f1
}
current_hash=$(get_state_hash)
if [ "$current_hash" != "$last_hash" ]; then
agent-browser screenshot screenshots/state-${current_hash}.png
last_hash=$current_hash
fi
Pattern 3: Timestamp-Based Caching
capture_with_cache() {
local scene=$1
local cache_file="screenshots/.cache-${scene}.txt"
local screenshot="screenshots/${scene}.png"
if [ -f "$cache_file" ]; then
local cached_time=$(cat "$cache_file")
local current_time=$(date +%s)
local age=$((current_time - cached_time))
if [ $age -lt 30 ]; then
echo "Using cached screenshot for $scene"
return 0
fi
fi
agent-browser eval "window.__TEST__.commands.goToScene('$scene')"
agent-browser wait 500
agent-browser screenshot "$screenshot"
echo $(date +%s) > "$cache_file"
}
Best Practices
- Always create folder first: Use
mkdir -p screenshots/ or equivalent before capturing
- Use descriptive names: Include feature, state, or test context in filename
- Consistent location: Always use
screenshots/ folder, never project root
- Clean up root: Move any screenshots found in root to
screenshots/ folder immediately
- Add to .gitignore: Consider adding
screenshots/*.png to .gitignore if screenshots are temporary
- Validate before completion: Verify all screenshots are in
screenshots/ folder before marking task complete
- Verify freshness: Always refresh browser before capturing verification screenshots
- Wait for transitions: Wait for scene transitions and HMR before capturing
- Use batch operations: Capture multiple screenshots efficiently with minimal waits
- Cache when appropriate: Use caching to avoid redundant captures
Examples
Example 1: UI Validation Screenshot
mkdir -p screenshots/
agent-browser open http://localhost:5173
agent-browser wait 2000
agent-browser screenshot screenshots/ui-validation-mainmenu.png
Example 2: Timer Test Screenshot
mkdir -p screenshots/
agent-browser open http://localhost:5173
agent-browser eval "window.__TEST__.commands.goToScene('GameScene')"
agent-browser eval "window.__TEST__.commands.setTimer(5)"
agent-browser wait 1000
agent-browser screenshot screenshots/timer-test-5seconds.png
Example 3: Playwright Test Screenshot
import { test } from '@playwright/test';
import fs from 'fs';
test('capture main menu screenshot', async ({ page }) => {
fs.mkdirSync('screenshots', { recursive: true });
await page.goto('http://localhost:5173');
await page.waitForTimeout(2000);
await page.screenshot({ path: 'screenshots/mainmenu-test.png' });
});
Resources
agent-browser skill - Browser automation and screenshot commands
- Project root should remain clean and organized
- Screenshots in root should be moved to
screenshots/ folder when discovered