Metadata-Version: 2.4
Name: amagi-site-diff
Version: 0.1.0
Summary: Two base URLs in, one markdown report out: crawl both sites, screenshot every matching page with Playwright, and write pixel-diff images plus text diffs an AI agent can read.
Author-email: "AmagiLabs (Amagisolutionsgroup, Inc.)" <dev@amagisolutionsgroup.com>
License: MIT
Project-URL: Homepage, https://github.com/amagilabs/amagi-site-diff
Keywords: visual-regression,screenshot,diff,playwright,website,deploy,qa,cli,claude-code
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Environment :: Console
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: playwright>=1.40
Requires-Dist: Pillow>=10.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Dynamic: license-file

# amagi-site-diff

See what changed between two versions of a website before your client does.
`amagi-site-diff` takes two base URLs (production and staging, or the old build and the new one),
crawls the same pages on both, screenshots each page in headless Chromium, and writes one
markdown report: pixel-diff images, changed regions named by page element, text diffs, new console
errors, broken requests, and pages that went missing.

It's for freelancers and agencies shipping redesigns, CMS migrations and theme updates who want a
page-by-page check before launch. The report is plain markdown, so you can read it yourself or hand
it to Claude.

## Demo

![demo](assets/demo.gif)

## Install

```
pipx install amagi-site-diff
```

(Not yet published to PyPI. Until it is, install from a clone of this repo with
`pipx install .`.)

Requires Python 3.10+. The first run downloads Playwright's Chromium if it isn't
already installed. To use the Chrome or Edge you already have instead, pass `--channel chrome` or
`--channel msedge`.

## Usage

```
amagi-site-diff https://example.com https://staging.example.com
```

A is "before", B is "after". Starting from `/`, it follows links on both sides, staying on each
site's own origin and path, and compares up to 20 pages. Either side can also be a local folder,
such as a static build, which is served on 127.0.0.1 for the run.

This repo ships two versions of a fictional bike shop site, so you can try it without touching a
real one:

```
cd examples
amagi-site-diff site-v1 site-v2
```

```
A: site-v1 (local folder)
B: site-v2 (local folder)
Comparing up to 20 pages, following links...
  /                        changed       1.61% pixels, 3 region(s); text +3 -3
  /services/               changed       0.76% pixels, 3 region(s); text +1 -1; meta description; 2 new console error(s); 1 new failed request(s)
  /about/                  identical
  /contact/                missing on B  B: HTTP 404
  /blog/                   new on B      A: HTTP 404
  /blog/winter-chain-care/ new on B      A: HTTP 404
6 page(s) compared: 2 changed, 1 identical, 1 missing on B, 2 new on B
Report: site-diff-report/report.md
```

### The report

`site-diff-report/report.md` opens with a summary table, then one section for each page that
differs. Each section has a diff image: B faded to grey, changed pixels in red, and numbered
blue boxes around each changed region.

![diff image for the home page](assets/diff-home.png)

The boxes are listed with the element under them on each side, followed by the text diff:

```
1. `160,214 225x42` (9,039 px): B `main > a.button` "Book a repair"; A `main > a.button` "See services and prices"
2. `384,172 689x18` (5,885 px): B `main > p.lead:nth-of-type(1)` "Drop your bike off before 11 am and pick it up the same a..."; A `main > p.lead:nth-of-type(1)` "Drop your bike off before 10 am and pick it up the same a..."
```

```diff
-Drop your bike off before 10 am and pick it up the same afternoon. Flat tyres, brakes, gears and full tune-ups.
-See services and prices
+Drop your bike off before 11 am and pick it up the same afternoon. Flat tyres, brakes, gears and full tune-ups.
+Book a repair
```

It also catches the problems that don't show up in a screenshot:

```
- Meta description: "Repair prices." -> "Repair prices, labour included."

Console errors on B only:
- `Uncaught: bookingWidget is not defined`

Failed requests on B only:
- `404 /img/workshop.jpg`

## Missing on B: `/contact/`
A serves this page and B does not. A's title: "Contact | Fernhill Bike Works".
B still links to it from: `/`, `/services/`, `/about/`, `/blog/`, `/blog/winter-chain-care/`. Those links are broken on B.
```

(Trimmed. The full report has every changed page, region and image link.)

Next to it:

- `report.json`: the same results in machine-readable form.
- `pages/<page>/a.png`, `b.png`, `diff.png`: full-page screenshots and the diff image, written only
  for pages that differ.

The images use relative links, so Claude Code can open them alongside the text. Point it at the
report ("read site-diff-report/report.md and tell me what will break for users"). The repo's
[SKILL.md](SKILL.md) teaches Claude how to run the tool and summarize the report.

### Options

```
amagi-site-diff A B --path /pricing --path /contact --no-crawl   # only these pages
amagi-site-diff A B --max-pages 100          # crawl further (default 20)
amagi-site-diff A B --hide "#cookie-banner" --hide ".chat-widget"   # hide noise on both sides
amagi-site-diff A B --viewport 390x844       # phone width (default 1280x800)
amagi-site-diff A B --viewport-only          # first screenful instead of the full page
amagi-site-diff A B --threshold 40           # ignore smaller colour shifts (default 24 of 255)
amagi-site-diff A B --wait 1500              # extra settle time for slow widgets, in ms
amagi-site-diff A B --keep-query             # treat ?page=2 as its own page
amagi-site-diff A B --out diff-report        # report folder (default site-diff-report)
amagi-site-diff A B --exit-code              # exit 1 when anything differs, for CI
```

In Git Bash on Windows, write `--path pricing` without the leading slash. Git Bash rewrites
`/pricing` into a Windows file path before the tool sees it, and the tool stops with an error.

Exit codes: `0` done, `1` differences found (only with `--exit-code`), `2` bad arguments, the
browser failed to start, no page loaded on either side, or one site never responded at all
(a typo in the URL or a server that is down).

## Limits

- **No logins.** Pages behind auth are compared as a logged-out visitor sees them.
- **Live content is noise.** Ads, rotating banners, A/B tests and live data change on every load.
  Hide them with `--hide`. Animations and transitions are frozen before each screenshot.
- **Links only.** The crawler follows `<a href>` links. Pages reached through forms, JavaScript
  navigation or only a sitemap need `--path`.
- **Chromium only.** It doesn't render in Firefox or Safari.
- **Compare what you're allowed to.** It loads every page it finds on both sites. Run it against
  your own sites, or ones your client has asked you to check.

## Why not BackstopJS, Playwright screenshots or Percy?

[BackstopJS](https://github.com/garris/BackstopJS) and Playwright's
[`toHaveScreenshot()`](https://playwright.dev/docs/test-snapshots) are built for ongoing visual
regression testing. You list scenarios or write a test for each page, store baseline images, and
compare future runs against them. Hosted services such as [Percy](https://percy.io) and
[Chromatic](https://www.chromatic.com) add review dashboards on top of the same model.

`amagi-site-diff` answers a one-off question: "what's different between these two sites right
now?" You give it two URLs. It finds the pages by crawling both, and writes a markdown file a person
or an AI assistant can read, with text diffs and element names next to the images.

## If this saved you time

A star helps other freelancers and agencies find this. It costs nothing and means a lot.

## More from AmagiLabs

- [amagi-legal-review-skills](https://github.com/amagilabs/amagi-legal-review-skills): Claude Code skills for
  first-pass NDA/MSA/lease review.
- [amagi-watch](https://github.com/amagilabs/amagi-watch): turn a video URL into a transcript and
  key-frame index Claude can read.
- [github.com/amagilabs](https://github.com/amagilabs): the rest of the AmagiLabs lab.

## License

MIT, see [LICENSE](LICENSE). Copyright (c) 2026 AmagiLabs (Amagisolutionsgroup, Inc.).
