amagi-site-diff 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- amagi_site_diff-0.1.0/LICENSE +21 -0
- amagi_site_diff-0.1.0/PKG-INFO +194 -0
- amagi_site_diff-0.1.0/README.md +171 -0
- amagi_site_diff-0.1.0/pyproject.toml +42 -0
- amagi_site_diff-0.1.0/setup.cfg +4 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/__init__.py +3 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/__main__.py +3 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/capture.py +271 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/cli.py +160 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/imagediff.py +152 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/locate.py +58 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/report.py +182 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/runner.py +262 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/textdiff.py +43 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff/urls.py +131 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff.egg-info/PKG-INFO +194 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff.egg-info/SOURCES.txt +24 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff.egg-info/dependency_links.txt +1 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff.egg-info/entry_points.txt +2 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff.egg-info/requires.txt +5 -0
- amagi_site_diff-0.1.0/src/amagi_site_diff.egg-info/top_level.txt +1 -0
- amagi_site_diff-0.1.0/tests/test_cli_e2e.py +151 -0
- amagi_site_diff-0.1.0/tests/test_imagediff.py +104 -0
- amagi_site_diff-0.1.0/tests/test_runner_report.py +196 -0
- amagi_site_diff-0.1.0/tests/test_textdiff_locate.py +69 -0
- amagi_site_diff-0.1.0/tests/test_urls.py +94 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Amagisolutionsgroup, Inc. (AmagiLabs)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: amagi-site-diff
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
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.
|
|
5
|
+
Author-email: "AmagiLabs (Amagisolutionsgroup, Inc.)" <dev@amagisolutionsgroup.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/amagilabs/amagi-site-diff
|
|
8
|
+
Keywords: visual-regression,screenshot,diff,playwright,website,deploy,qa,cli,claude-code
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Topic :: Software Development :: Testing
|
|
14
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: playwright>=1.40
|
|
19
|
+
Requires-Dist: Pillow>=10.0
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# amagi-site-diff
|
|
25
|
+
|
|
26
|
+
See what changed between two versions of a website before your client does.
|
|
27
|
+
`amagi-site-diff` takes two base URLs (production and staging, or the old build and the new one),
|
|
28
|
+
crawls the same pages on both, screenshots each page in headless Chromium, and writes one
|
|
29
|
+
markdown report: pixel-diff images, changed regions named by page element, text diffs, new console
|
|
30
|
+
errors, broken requests, and pages that went missing.
|
|
31
|
+
|
|
32
|
+
It's for freelancers and agencies shipping redesigns, CMS migrations and theme updates who want a
|
|
33
|
+
page-by-page check before launch. The report is plain markdown, so you can read it yourself or hand
|
|
34
|
+
it to Claude.
|
|
35
|
+
|
|
36
|
+
## Demo
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
pipx install amagi-site-diff
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
(Not yet published to PyPI. Until it is, install from a clone of this repo with
|
|
47
|
+
`pipx install .`.)
|
|
48
|
+
|
|
49
|
+
Requires Python 3.10+. The first run downloads Playwright's Chromium if it isn't
|
|
50
|
+
already installed. To use the Chrome or Edge you already have instead, pass `--channel chrome` or
|
|
51
|
+
`--channel msedge`.
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
amagi-site-diff https://example.com https://staging.example.com
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
A is "before", B is "after". Starting from `/`, it follows links on both sides, staying on each
|
|
60
|
+
site's own origin and path, and compares up to 20 pages. Either side can also be a local folder,
|
|
61
|
+
such as a static build, which is served on 127.0.0.1 for the run.
|
|
62
|
+
|
|
63
|
+
This repo ships two versions of a fictional bike shop site, so you can try it without touching a
|
|
64
|
+
real one:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
cd examples
|
|
68
|
+
amagi-site-diff site-v1 site-v2
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
A: site-v1 (local folder)
|
|
73
|
+
B: site-v2 (local folder)
|
|
74
|
+
Comparing up to 20 pages, following links...
|
|
75
|
+
/ changed 1.61% pixels, 3 region(s); text +3 -3
|
|
76
|
+
/services/ changed 0.76% pixels, 3 region(s); text +1 -1; meta description; 2 new console error(s); 1 new failed request(s)
|
|
77
|
+
/about/ identical
|
|
78
|
+
/contact/ missing on B B: HTTP 404
|
|
79
|
+
/blog/ new on B A: HTTP 404
|
|
80
|
+
/blog/winter-chain-care/ new on B A: HTTP 404
|
|
81
|
+
6 page(s) compared: 2 changed, 1 identical, 1 missing on B, 2 new on B
|
|
82
|
+
Report: site-diff-report/report.md
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### The report
|
|
86
|
+
|
|
87
|
+
`site-diff-report/report.md` opens with a summary table, then one section for each page that
|
|
88
|
+
differs. Each section has a diff image: B faded to grey, changed pixels in red, and numbered
|
|
89
|
+
blue boxes around each changed region.
|
|
90
|
+
|
|
91
|
+

|
|
92
|
+
|
|
93
|
+
The boxes are listed with the element under them on each side, followed by the text diff:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
1. `160,214 225x42` (9,039 px): B `main > a.button` "Book a repair"; A `main > a.button` "See services and prices"
|
|
97
|
+
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..."
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```diff
|
|
101
|
+
-Drop your bike off before 10 am and pick it up the same afternoon. Flat tyres, brakes, gears and full tune-ups.
|
|
102
|
+
-See services and prices
|
|
103
|
+
+Drop your bike off before 11 am and pick it up the same afternoon. Flat tyres, brakes, gears and full tune-ups.
|
|
104
|
+
+Book a repair
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
It also catches the problems that don't show up in a screenshot:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
- Meta description: "Repair prices." -> "Repair prices, labour included."
|
|
111
|
+
|
|
112
|
+
Console errors on B only:
|
|
113
|
+
- `Uncaught: bookingWidget is not defined`
|
|
114
|
+
|
|
115
|
+
Failed requests on B only:
|
|
116
|
+
- `404 /img/workshop.jpg`
|
|
117
|
+
|
|
118
|
+
## Missing on B: `/contact/`
|
|
119
|
+
A serves this page and B does not. A's title: "Contact | Fernhill Bike Works".
|
|
120
|
+
B still links to it from: `/`, `/services/`, `/about/`, `/blog/`, `/blog/winter-chain-care/`. Those links are broken on B.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
(Trimmed. The full report has every changed page, region and image link.)
|
|
124
|
+
|
|
125
|
+
Next to it:
|
|
126
|
+
|
|
127
|
+
- `report.json`: the same results in machine-readable form.
|
|
128
|
+
- `pages/<page>/a.png`, `b.png`, `diff.png`: full-page screenshots and the diff image, written only
|
|
129
|
+
for pages that differ.
|
|
130
|
+
|
|
131
|
+
The images use relative links, so Claude Code can open them alongside the text. Point it at the
|
|
132
|
+
report ("read site-diff-report/report.md and tell me what will break for users"). The repo's
|
|
133
|
+
[SKILL.md](SKILL.md) teaches Claude how to run the tool and summarize the report.
|
|
134
|
+
|
|
135
|
+
### Options
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
amagi-site-diff A B --path /pricing --path /contact --no-crawl # only these pages
|
|
139
|
+
amagi-site-diff A B --max-pages 100 # crawl further (default 20)
|
|
140
|
+
amagi-site-diff A B --hide "#cookie-banner" --hide ".chat-widget" # hide noise on both sides
|
|
141
|
+
amagi-site-diff A B --viewport 390x844 # phone width (default 1280x800)
|
|
142
|
+
amagi-site-diff A B --viewport-only # first screenful instead of the full page
|
|
143
|
+
amagi-site-diff A B --threshold 40 # ignore smaller colour shifts (default 24 of 255)
|
|
144
|
+
amagi-site-diff A B --wait 1500 # extra settle time for slow widgets, in ms
|
|
145
|
+
amagi-site-diff A B --keep-query # treat ?page=2 as its own page
|
|
146
|
+
amagi-site-diff A B --out diff-report # report folder (default site-diff-report)
|
|
147
|
+
amagi-site-diff A B --exit-code # exit 1 when anything differs, for CI
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
In Git Bash on Windows, write `--path pricing` without the leading slash. Git Bash rewrites
|
|
151
|
+
`/pricing` into a Windows file path before the tool sees it, and the tool stops with an error.
|
|
152
|
+
|
|
153
|
+
Exit codes: `0` done, `1` differences found (only with `--exit-code`), `2` bad arguments, the
|
|
154
|
+
browser failed to start, no page loaded on either side, or one site never responded at all
|
|
155
|
+
(a typo in the URL or a server that is down).
|
|
156
|
+
|
|
157
|
+
## Limits
|
|
158
|
+
|
|
159
|
+
- **No logins.** Pages behind auth are compared as a logged-out visitor sees them.
|
|
160
|
+
- **Live content is noise.** Ads, rotating banners, A/B tests and live data change on every load.
|
|
161
|
+
Hide them with `--hide`. Animations and transitions are frozen before each screenshot.
|
|
162
|
+
- **Links only.** The crawler follows `<a href>` links. Pages reached through forms, JavaScript
|
|
163
|
+
navigation or only a sitemap need `--path`.
|
|
164
|
+
- **Chromium only.** It doesn't render in Firefox or Safari.
|
|
165
|
+
- **Compare what you're allowed to.** It loads every page it finds on both sites. Run it against
|
|
166
|
+
your own sites, or ones your client has asked you to check.
|
|
167
|
+
|
|
168
|
+
## Why not BackstopJS, Playwright screenshots or Percy?
|
|
169
|
+
|
|
170
|
+
[BackstopJS](https://github.com/garris/BackstopJS) and Playwright's
|
|
171
|
+
[`toHaveScreenshot()`](https://playwright.dev/docs/test-snapshots) are built for ongoing visual
|
|
172
|
+
regression testing. You list scenarios or write a test for each page, store baseline images, and
|
|
173
|
+
compare future runs against them. Hosted services such as [Percy](https://percy.io) and
|
|
174
|
+
[Chromatic](https://www.chromatic.com) add review dashboards on top of the same model.
|
|
175
|
+
|
|
176
|
+
`amagi-site-diff` answers a one-off question: "what's different between these two sites right
|
|
177
|
+
now?" You give it two URLs. It finds the pages by crawling both, and writes a markdown file a person
|
|
178
|
+
or an AI assistant can read, with text diffs and element names next to the images.
|
|
179
|
+
|
|
180
|
+
## If this saved you time
|
|
181
|
+
|
|
182
|
+
A star helps other freelancers and agencies find this. It costs nothing and means a lot.
|
|
183
|
+
|
|
184
|
+
## More from AmagiLabs
|
|
185
|
+
|
|
186
|
+
- [amagi-legal-review-skills](https://github.com/amagilabs/amagi-legal-review-skills): Claude Code skills for
|
|
187
|
+
first-pass NDA/MSA/lease review.
|
|
188
|
+
- [amagi-watch](https://github.com/amagilabs/amagi-watch): turn a video URL into a transcript and
|
|
189
|
+
key-frame index Claude can read.
|
|
190
|
+
- [github.com/amagilabs](https://github.com/amagilabs): the rest of the AmagiLabs lab.
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT, see [LICENSE](LICENSE). Copyright (c) 2026 AmagiLabs (Amagisolutionsgroup, Inc.).
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# amagi-site-diff
|
|
2
|
+
|
|
3
|
+
See what changed between two versions of a website before your client does.
|
|
4
|
+
`amagi-site-diff` takes two base URLs (production and staging, or the old build and the new one),
|
|
5
|
+
crawls the same pages on both, screenshots each page in headless Chromium, and writes one
|
|
6
|
+
markdown report: pixel-diff images, changed regions named by page element, text diffs, new console
|
|
7
|
+
errors, broken requests, and pages that went missing.
|
|
8
|
+
|
|
9
|
+
It's for freelancers and agencies shipping redesigns, CMS migrations and theme updates who want a
|
|
10
|
+
page-by-page check before launch. The report is plain markdown, so you can read it yourself or hand
|
|
11
|
+
it to Claude.
|
|
12
|
+
|
|
13
|
+
## Demo
|
|
14
|
+
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
pipx install amagi-site-diff
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
(Not yet published to PyPI. Until it is, install from a clone of this repo with
|
|
24
|
+
`pipx install .`.)
|
|
25
|
+
|
|
26
|
+
Requires Python 3.10+. The first run downloads Playwright's Chromium if it isn't
|
|
27
|
+
already installed. To use the Chrome or Edge you already have instead, pass `--channel chrome` or
|
|
28
|
+
`--channel msedge`.
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
amagi-site-diff https://example.com https://staging.example.com
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
A is "before", B is "after". Starting from `/`, it follows links on both sides, staying on each
|
|
37
|
+
site's own origin and path, and compares up to 20 pages. Either side can also be a local folder,
|
|
38
|
+
such as a static build, which is served on 127.0.0.1 for the run.
|
|
39
|
+
|
|
40
|
+
This repo ships two versions of a fictional bike shop site, so you can try it without touching a
|
|
41
|
+
real one:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
cd examples
|
|
45
|
+
amagi-site-diff site-v1 site-v2
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
A: site-v1 (local folder)
|
|
50
|
+
B: site-v2 (local folder)
|
|
51
|
+
Comparing up to 20 pages, following links...
|
|
52
|
+
/ changed 1.61% pixels, 3 region(s); text +3 -3
|
|
53
|
+
/services/ changed 0.76% pixels, 3 region(s); text +1 -1; meta description; 2 new console error(s); 1 new failed request(s)
|
|
54
|
+
/about/ identical
|
|
55
|
+
/contact/ missing on B B: HTTP 404
|
|
56
|
+
/blog/ new on B A: HTTP 404
|
|
57
|
+
/blog/winter-chain-care/ new on B A: HTTP 404
|
|
58
|
+
6 page(s) compared: 2 changed, 1 identical, 1 missing on B, 2 new on B
|
|
59
|
+
Report: site-diff-report/report.md
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### The report
|
|
63
|
+
|
|
64
|
+
`site-diff-report/report.md` opens with a summary table, then one section for each page that
|
|
65
|
+
differs. Each section has a diff image: B faded to grey, changed pixels in red, and numbered
|
|
66
|
+
blue boxes around each changed region.
|
|
67
|
+
|
|
68
|
+

|
|
69
|
+
|
|
70
|
+
The boxes are listed with the element under them on each side, followed by the text diff:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
1. `160,214 225x42` (9,039 px): B `main > a.button` "Book a repair"; A `main > a.button` "See services and prices"
|
|
74
|
+
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..."
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```diff
|
|
78
|
+
-Drop your bike off before 10 am and pick it up the same afternoon. Flat tyres, brakes, gears and full tune-ups.
|
|
79
|
+
-See services and prices
|
|
80
|
+
+Drop your bike off before 11 am and pick it up the same afternoon. Flat tyres, brakes, gears and full tune-ups.
|
|
81
|
+
+Book a repair
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
It also catches the problems that don't show up in a screenshot:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
- Meta description: "Repair prices." -> "Repair prices, labour included."
|
|
88
|
+
|
|
89
|
+
Console errors on B only:
|
|
90
|
+
- `Uncaught: bookingWidget is not defined`
|
|
91
|
+
|
|
92
|
+
Failed requests on B only:
|
|
93
|
+
- `404 /img/workshop.jpg`
|
|
94
|
+
|
|
95
|
+
## Missing on B: `/contact/`
|
|
96
|
+
A serves this page and B does not. A's title: "Contact | Fernhill Bike Works".
|
|
97
|
+
B still links to it from: `/`, `/services/`, `/about/`, `/blog/`, `/blog/winter-chain-care/`. Those links are broken on B.
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
(Trimmed. The full report has every changed page, region and image link.)
|
|
101
|
+
|
|
102
|
+
Next to it:
|
|
103
|
+
|
|
104
|
+
- `report.json`: the same results in machine-readable form.
|
|
105
|
+
- `pages/<page>/a.png`, `b.png`, `diff.png`: full-page screenshots and the diff image, written only
|
|
106
|
+
for pages that differ.
|
|
107
|
+
|
|
108
|
+
The images use relative links, so Claude Code can open them alongside the text. Point it at the
|
|
109
|
+
report ("read site-diff-report/report.md and tell me what will break for users"). The repo's
|
|
110
|
+
[SKILL.md](SKILL.md) teaches Claude how to run the tool and summarize the report.
|
|
111
|
+
|
|
112
|
+
### Options
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
amagi-site-diff A B --path /pricing --path /contact --no-crawl # only these pages
|
|
116
|
+
amagi-site-diff A B --max-pages 100 # crawl further (default 20)
|
|
117
|
+
amagi-site-diff A B --hide "#cookie-banner" --hide ".chat-widget" # hide noise on both sides
|
|
118
|
+
amagi-site-diff A B --viewport 390x844 # phone width (default 1280x800)
|
|
119
|
+
amagi-site-diff A B --viewport-only # first screenful instead of the full page
|
|
120
|
+
amagi-site-diff A B --threshold 40 # ignore smaller colour shifts (default 24 of 255)
|
|
121
|
+
amagi-site-diff A B --wait 1500 # extra settle time for slow widgets, in ms
|
|
122
|
+
amagi-site-diff A B --keep-query # treat ?page=2 as its own page
|
|
123
|
+
amagi-site-diff A B --out diff-report # report folder (default site-diff-report)
|
|
124
|
+
amagi-site-diff A B --exit-code # exit 1 when anything differs, for CI
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
In Git Bash on Windows, write `--path pricing` without the leading slash. Git Bash rewrites
|
|
128
|
+
`/pricing` into a Windows file path before the tool sees it, and the tool stops with an error.
|
|
129
|
+
|
|
130
|
+
Exit codes: `0` done, `1` differences found (only with `--exit-code`), `2` bad arguments, the
|
|
131
|
+
browser failed to start, no page loaded on either side, or one site never responded at all
|
|
132
|
+
(a typo in the URL or a server that is down).
|
|
133
|
+
|
|
134
|
+
## Limits
|
|
135
|
+
|
|
136
|
+
- **No logins.** Pages behind auth are compared as a logged-out visitor sees them.
|
|
137
|
+
- **Live content is noise.** Ads, rotating banners, A/B tests and live data change on every load.
|
|
138
|
+
Hide them with `--hide`. Animations and transitions are frozen before each screenshot.
|
|
139
|
+
- **Links only.** The crawler follows `<a href>` links. Pages reached through forms, JavaScript
|
|
140
|
+
navigation or only a sitemap need `--path`.
|
|
141
|
+
- **Chromium only.** It doesn't render in Firefox or Safari.
|
|
142
|
+
- **Compare what you're allowed to.** It loads every page it finds on both sites. Run it against
|
|
143
|
+
your own sites, or ones your client has asked you to check.
|
|
144
|
+
|
|
145
|
+
## Why not BackstopJS, Playwright screenshots or Percy?
|
|
146
|
+
|
|
147
|
+
[BackstopJS](https://github.com/garris/BackstopJS) and Playwright's
|
|
148
|
+
[`toHaveScreenshot()`](https://playwright.dev/docs/test-snapshots) are built for ongoing visual
|
|
149
|
+
regression testing. You list scenarios or write a test for each page, store baseline images, and
|
|
150
|
+
compare future runs against them. Hosted services such as [Percy](https://percy.io) and
|
|
151
|
+
[Chromatic](https://www.chromatic.com) add review dashboards on top of the same model.
|
|
152
|
+
|
|
153
|
+
`amagi-site-diff` answers a one-off question: "what's different between these two sites right
|
|
154
|
+
now?" You give it two URLs. It finds the pages by crawling both, and writes a markdown file a person
|
|
155
|
+
or an AI assistant can read, with text diffs and element names next to the images.
|
|
156
|
+
|
|
157
|
+
## If this saved you time
|
|
158
|
+
|
|
159
|
+
A star helps other freelancers and agencies find this. It costs nothing and means a lot.
|
|
160
|
+
|
|
161
|
+
## More from AmagiLabs
|
|
162
|
+
|
|
163
|
+
- [amagi-legal-review-skills](https://github.com/amagilabs/amagi-legal-review-skills): Claude Code skills for
|
|
164
|
+
first-pass NDA/MSA/lease review.
|
|
165
|
+
- [amagi-watch](https://github.com/amagilabs/amagi-watch): turn a video URL into a transcript and
|
|
166
|
+
key-frame index Claude can read.
|
|
167
|
+
- [github.com/amagilabs](https://github.com/amagilabs): the rest of the AmagiLabs lab.
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
MIT, see [LICENSE](LICENSE). Copyright (c) 2026 AmagiLabs (Amagisolutionsgroup, Inc.).
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "amagi-site-diff"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "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."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "AmagiLabs (Amagisolutionsgroup, Inc.)", email = "dev@amagisolutionsgroup.com" }]
|
|
13
|
+
keywords = ["visual-regression", "screenshot", "diff", "playwright", "website", "deploy", "qa", "cli", "claude-code"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Topic :: Software Development :: Testing",
|
|
20
|
+
"Topic :: Internet :: WWW/HTTP :: Site Management",
|
|
21
|
+
]
|
|
22
|
+
dependencies = [
|
|
23
|
+
"playwright>=1.40",
|
|
24
|
+
"Pillow>=10.0",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
dev = [
|
|
29
|
+
"pytest>=7.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
amagi-site-diff = "amagi_site_diff.cli:main"
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://github.com/amagilabs/amagi-site-diff"
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.packages.find]
|
|
39
|
+
where = ["src"]
|
|
40
|
+
|
|
41
|
+
[tool.pytest.ini_options]
|
|
42
|
+
testpaths = ["tests"]
|