Visual regression testing from your terminal
Vizzly is a visual testing and regression platform for teams that ship UI. It captures screenshots from your real tests, compares them to approved baselines, and gives you useful review data: meaningful diffs, comments, approvals, build status, and preview links.
This package is the CLI and local SDK surface. Use it to run local visual TDD, upload screenshots from CI, generate static reports, and fetch machine-readable build or diff data for scripts, automation, and coding agents.
You need Node.js 22+.
pnpm install -g @vizzly-testing/cli
vizzly initFor agent-friendly repos, install the Vizzly skill and add a short project
AGENTS.md note:
vizzly init --agent-guidanceThis installs the portable Agent Skills bundle in .agents/skills/vizzly and
adds a small managed block to AGENTS.md. Run the same command again after a
CLI upgrade to refresh both without replacing the rest of AGENTS.md or an
existing Vizzly config.
Use vizzly init --agent-skill to install or refresh only the local skill, or
vizzly init --skip-agent-skill when you want config without the agent prompt.
Start the TDD server, run your tests, and open the dashboard at the URL the
command prints. Add --open when you want Vizzly to open the dashboard for
you. If the default port is busy, Vizzly picks the next available port; use the
printed --port value with vizzly tdd status or vizzly tdd stop.
vizzly tdd start --open
pnpm test -- --watchThe dashboard shows screenshots, baselines, and diffs as they arrive. Accept or reject changes right from the UI.
For a one-off local check, wrap the test command with tdd run:
vizzly tdd run "pnpm test" --no-open
vizzly context build current --source local --jsonThat run writes review data under .vizzly/ and prints a context command you
can use for follow-up inspection. If screenshots were captured, Vizzly also
generates .vizzly/report/index.html; omit --no-open when you want that
report opened automatically.
Use cloud builds when you want shared baselines, team review, and CI status:
vizzly login
vizzly project link your-org/your-project
vizzly run "pnpm test" --waitvizzly login authenticates your user account. vizzly project link creates a
project-scoped upload credential for this checkout, which vizzly run uses for
cloud uploads.
--wait blocks until Vizzly finishes processing the build. It exits with code
1 when visual differences need review.
In CI, use a project token:
export VIZZLY_TOKEN=your-project-token
vizzly run "pnpm test" --waitUse vizzly context for human summaries and local .vizzly evidence. For cloud
reviews, agents should discover and call the public API through its schema:
vizzly api schema --json
vizzly api schema sdk.listBuilds --jsonThe context build --agent and context comparison --agent formats are
deprecated and scheduled for removal in v0.38.0. Use the schema-driven API for
cloud evidence; use vizzly context ... --json for local evidence.
# Human-readable cloud build context
vizzly context build abc123 --source cloud
# Discover cloud evidence operations for an agent workflow
vizzly api schema sdk.getBuildContext --json
vizzly api schema getComparisonContext --json
# Local workspace context from .vizzly/
vizzly context build current --source local
vizzly context build current --source local --json
vizzly context screenshot build-detail-screenshots --source local --json
vizzly context review-queue --source local --jsonUse vizzly api schema to inspect cloud operation inputs, output fields, and
pagination before making requests. The old compact --agent handoff remains
available during deprecation, but new cloud workflows should use the schema.
Use --json for machine-readable local context.
Local context is read-only and file-backed. It reads your existing .vizzly
workspace state from TDD runs, including screenshots, diffs, and saved hotspot
or region metadata.
The context commands are read-only. The schema-discovered review API also
supports explicit decisions when a task asks for them.
Add screenshots to your existing tests:
import { vizzlyScreenshot } from '@vizzly-testing/cli/client';
test('homepage looks correct', async ({ page }) => {
await page.goto('/');
let screenshot = await page.screenshot();
await vizzlyScreenshot('homepage', screenshot, {
fullPage: true,
requestTimeout: 5000,
properties: {
theme: 'dark',
locale: 'en-US',
},
});
});properties is your key/value metadata bag for baseline grouping, filtering,
and debugging. Vizzly passes every property through as user metadata; property
names are never interpreted as options. The supported top-level options are
threshold, minClusterSize, fullPage, requestTimeout, and buildId.
Vizzly reads width and height from the captured image, so viewport dimensions do
not need to be included in properties.
The client SDK is lightweight. It posts screenshots to the local Vizzly server or the cloud build wrapper. It works with any test runner.
SDKs are available for JavaScript, Ruby, Swift, and more.
Already saving screenshots to disk? Pass the file path instead:
await page.screenshot({ path: './screenshots/homepage.png' });
await vizzlyScreenshot('homepage', './screenshots/homepage.png');Or upload an existing folder of screenshots:
vizzly upload ./screenshots --threshold 2 --min-cluster-size 4 --batch-size 10 --upload-timeout 60000--batch-size controls how many screenshots are uploaded per request.
--upload-timeout controls the upload client's timeout, including how long
--wait polls for build processing.
When vizzly run sends screenshots to Vizzly, the CLI first asks the API to
resolve each screenshot by SHA. If Vizzly already has the image bytes, the CLI
creates the screenshot record without re-uploading the image. CI workflows can
force every screenshot through with --upload-all. Parallel jobs should use the
same stable ID, then finalize that ID after every shard completes:
vizzly run "pnpm test" --upload-all --parallel-id "$GITHUB_RUN_ID"
vizzly finalize "$GITHUB_RUN_ID"For smoke jobs where cloud credentials are intentionally unavailable, add
--allow-no-token to vizzly run and Vizzly will keep the local screenshot
server path working without creating a cloud build.
Generate a config file:
vizzly initTo teach project agents the Vizzly evidence workflow, add the repo-local skill and AGENTS.md guidance:
vizzly init --agent-guidanceOr create vizzly.config.js manually:
export default {
comparison: {
// CIEDE2000 Delta E. 0 is exact. 2 is a good default.
threshold: 2.0,
},
};| Command | What it does |
|---|---|
vizzly tdd start |
Start the local TDD server and dashboard. |
vizzly tdd status |
Check the local TDD server for this project. |
vizzly tdd list |
List running local TDD servers. |
vizzly tdd stop |
Stop the local TDD server for this project. |
vizzly tdd run "cmd" |
Run tests once and write local review data under .vizzly/. |
vizzly run "cmd" |
Run tests with cloud build and review integration. |
vizzly context ... |
Fetch visual context for builds, comparisons, screenshots, and review queues. |
vizzly upload <dir> |
Upload an existing folder of screenshots. |
vizzly preview <dir> |
Upload static build output for in-context review. |
vizzly approve <comparison-id> |
Approve a visual comparison. |
vizzly reject <comparison-id> |
Reject a visual comparison with a reason. |
vizzly comment <build-id> |
Add a build comment. |
vizzly config [key] |
Inspect resolved configuration values. |
vizzly login |
Authenticate through the browser. |
vizzly doctor |
Validate your local setup. |
Full documentation lives at docs.vizzly.dev. Start there for framework guides, CI setup, SDK examples, and the configuration reference.
Found a bug or have an idea? Open an issue or send a PR.
MIT
