Zero-config CLI for visual regression testing. Powered by Playwright + pixelmatch.
snapdiff is a visual regression testing CLI. Take a baseline screenshot before you change code, then compare after ? it tells you what changed and by how much, with an interactive HTML report.
Ideal for:
- Checking for unintended layout changes after CSS/component edits
- Automated visual diff on every PR
- CI pipeline integration
# Initialize (interactive wizard, auto-captures first baseline)
npx snapdiff-cli init
# After code changes, compare against baseline
npx snapdiff-cli diff
# Check baseline status
npx snapdiff-cli status
# Accept changes as new baseline
npx snapdiff-cli approve <name>Running init for the first time will:
- Create
snapdiff.config.json - Take the first baseline screenshot automatically
- Add
.snapdiff/diffs/and.snapdiff/reports/to.gitignore
| Feature | Description |
|---|---|
| Zero config | snapdiff init sets up everything ? config file, first capture, .gitignore |
| Pixel-level diff | Uses pixelmatch for accurate comparison |
| HTML report | Side-by-side view of baseline / current / diff, auto-generated |
| Parallel capture | Captures 3 pages concurrently |
| Mask regions | Exclude dynamic areas (ads, animations) from comparison |
| CI ready | Built-in GitHub Action, works with any CI pipeline |
| Multi-page | Capture and diff entire site configurations from a single config file |
| Auto-cleanup | Old reports older than 7 days are removed automatically |
Initialize a snapdiff project (interactive wizard, auto-captures first screenshot).
npx snapdiff-cli init # Interactive
npx snapdiff-cli init --yes # Non-interactive, use defaults
npx snapdiff-cli init --yes --ci # Non-interactive + generate CI configinit auto-detects whether stdin is a terminal. In CI environments (non-TTY), it switches to non-interactive mode automatically.
Capture and save baseline screenshots.
# Capture all pages from the config file
npx snapdiff-cli capture
# Capture a single page
npx snapdiff-cli capture https://example.com --name my-page
# Wait for a CSS selector to appear before capturing
npx snapdiff-cli capture https://example.com --name home --selector "#app-root"
# Custom viewport
npx snapdiff-cli capture https://example.com --name mobile -w 375 -h 812Multi-page mode uses 3 concurrent workers automatically.
Compare current pages against their baselines.
# Diff all pages from the config file
npx snapdiff-cli diff
# Diff a single page
npx snapdiff-cli diff https://example.com --name my-page
# Set a more permissive threshold (allow 0.5% diff)
npx snapdiff-cli diff -t 0.5Generates an HTML report in .snapdiff/reports/ with baseline / current / diff side-by-side. Reports older than 7 days are auto-cleaned.
Accept the current diff as the new baseline (overwrites old baseline).
npx snapdiff-cli approve my-pageDisplay all baseline entries in a table.
npx snapdiff-cli statusCreate snapdiff.config.json in your project root:
{
"snaps": [
{
"name": "homepage",
"url": "https://example.com",
"viewport": { "width": 1440, "height": 900 },
"threshold": 0.1
},
{
"name": "pricing",
"url": "https://example.com/pricing",
"selector": "#app-root",
"viewport": { "width": 1440, "height": 900 },
"threshold": 0.1
}
]
}| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Snapshot name for identification |
url |
string | Yes | Page URL |
selector |
string | No | Wait for CSS selector before capture |
viewport |
object | No | Viewport size, default { width: 1440, height: 900 } |
threshold |
number | No | Diff threshold percentage, default 0.1. Exceeds threshold = failure |
fullPage |
boolean | No | Capture full scrollable page, default false |
headless |
boolean | No | Headless browser mode, default true |
maskRegions |
array | No | Mask regions array [{ x, y, width, height }]. These areas are excluded from diff comparison |
project-root/
+-- snapdiff.config.json # Configuration file
+-- .gitignore # Automatically includes .snapdiff/*
+-- .snapdiff/
+-- baselines/ # Baseline images (tracked in git)
| +-- homepage.png
| +-- homepage.json # Metadata (URL, viewport, timestamp)
+-- diffs/ # Diff comparison images (gitignored)
| +-- homepage-1234567890-diff.png
+-- reports/ # HTML reports (gitignored)
| +-- report-1234567890.html
+-- tmp/ # Temp screenshots (gitignored)
Baseline images are tracked in git so that PR diffs show image changes directly. Diff images and reports are gitignored.
snapdiff ships with a built-in GitHub Action that supports both capture and diff modes.
# .github/workflows/snapdiff.yml
name: Visual Regression Test
on: [pull_request]
jobs:
snapdiff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npx snapdiff-cli diffGenerate this automatically with:
npx snapdiff-cli init --yes --cisnapdiff runs anywhere Node.js is available. Just install and run:
npx snapdiff-cli capture # In a pre-change step
npx snapdiff-cli diff # In a post-change step| Feature | snapdiff | Percy | Chromatic | BackstopJS |
|---|---|---|---|---|
| Local CLI | Free, open-source | Limited (cloud-dependent) | Limited (cloud-dependent) | Free |
| SaaS requirement | None | Required (cloud rendering) | Required (cloud rendering) | None |
| Pricing | Free (open source MIT) | Paid tiers after free quota | Paid tiers after free quota | Free |
| Self-hosted | Yes | No (cloud only) | No (cloud only) | Yes |
| HTML report | Built-in, local | Web dashboard | Web dashboard | Customizable |
| Parallel capture | Yes (3 workers) | Yes | Yes | Yes |
| Mask regions | Yes | Yes | Yes | Limited |
| CI integration | CLI + GitHub Action | GitHub Action + SDK | GitHub App | CLI + Docker |
| Setup time | ~30 seconds | ~5 minutes + account | ~5 minutes + account | ~10 minutes |
| Full page capture | Yes | Yes | Yes | Yes |
| Component | Purpose |
|---|---|
| Playwright | Browser automation & screenshot engine |
| pixelmatch | Pixel-level image comparison |
| pngjs | PNG image processing |
| commander | CLI framework |
git clone https://github.com/zixuan57/snapdiff.git
cd snapdiff
cd packages/cli
npm install
npm run build
node dist/index.js --helpBug reports, feature requests, and pull requests are welcome. See CONTRIBUTING.md.
MIT