visualdiff
README.md
# visualdiff
visualdiff wraps the SnapDiff visual-testing API: verify that a UI
change matches what you meant to do, diff two pages (or a page
against a stored baseline), capture a screenshot of any URL, and
render raw HTML/CSS straight to an image. One binary serves a
command-line interface and a stdio MCP server.
An API key is required. Set `SNAPDIFF_API_KEY` to a key from the
SnapDiff dashboard; calls fail before any request is made when it
is missing. The API base URL can be overridden with
`SNAPDIFF_API_URL`; when it is not set, calls go to
`https://api.snapdiff.ai/v1`.
## Install
```bash
npx @reneturcios/visualdiff screenshot https://example.com
```
Or run the container image:
```bash
docker run -i -e SNAPDIFF_API_KEY=sk_live_... ghcr.io/cloudcorprecords/visualdiff
```
The container defaults to the MCP server (see below). Pass CLI
arguments to use it as a CLI instead.
## CLI
```bash
export SNAPDIFF_API_KEY=sk_live_...
visualdiff verify myproj pricing https://staging.example.com/pricing "added a yearly billing toggle"
visualdiff compare https://staging.example.com --before https://www.example.com
visualdiff compare http://localhost:3000 --project myproj --page-name homepage
visualdiff screenshot https://example.com --width 800 --full-page
visualdiff html-to-image "<h1>Hello</h1>" --css "h1 { color: navy; }" --width 1200 --height 630
visualdiff --version
```
Commands print the upstream JSON payload. Exit codes: `0` on
success, `1` when a call fails (including a missing API key or an
upstream API error), `2` for usage errors.
## MCP server
One bin serves both faces. The `mcp` subcommand starts a stdio MCP
server:
```bash
npx -y @reneturcios/visualdiff mcp
```
MCP client configuration:
```json
{
"mcpServers": {
"visualdiff": {
"command": "npx",
"args": ["-y", "@reneturcios/visualdiff", "mcp"],
"env": { "SNAPDIFF_API_KEY": "sk_live_..." }
}
}
}
```
### Tools
| Tool | Input | What it returns |
| --- | --- | --- |
| `snapdiff_verify_ui_change` | `project`, `page_name`, `after`, `intent` (all required); optional `intent_regions`, `branch`, `threshold`, `match_tolerance_percent`, `ignore_selectors`, `full_page` | A verdict (`pass`, `expected_change_detected`, `unexpected_regression`, `no_change_detected`, or `needs_human_review`), a `next_action`, and a `review_url`. Requires a project with a stored page baseline. |
| `snapdiff_compare_pages` | `after` (required); plus `before`, or `project` + `page_name` for baseline mode; optional `branch`, `threshold`, `ignore_selectors`, `full_page` | A diff percentage plus a highlighted diff image. |
| `snapdiff_capture_screenshot` | `url` (required); optional `full_page`, `dark_mode`, `selector`, `width` | A screenshot of the page. |
| `snapdiff_html_to_image` | `html` (required); optional `css`, `width`, `height` | The rendered image (OG cards, social images, email headers). |
Each tool is sent as a POST to a per-tool endpoint under the base
URL with the API key as a Bearer token. Optional arguments that
are not supplied are omitted from the request body entirely.
## Development
```bash
npm install
npm run build # tsc -> dist/
npm test # node test runner over test/*.test.ts, no network (fake fetch fixtures)
npm run dev # run the CLI from source via tsx
```
## License
MIT — see `LICENSE`.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues