Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 62 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,73 @@
# Vizzly CLI

> Visual review for agents and teams
> Visual regression testing from your terminal

[![package version](https://img.shields.io/npm/v/@vizzly-testing/cli.svg)](https://www.npmjs.com/package/@vizzly-testing/cli)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Vizzly keeps the visual truth behind your UI: approved baselines, meaningful diffs, review state, comments, and preview links in one place. That makes it useful for humans reviewing product changes and for LLM agents that need to understand what the UI is supposed to look like before they edit it.
<p align="center">
<img src="./docs/assets/vizzly-mascot-inspector.png" alt="Vizzly bear inspecting a screenshot" width="220" />
</p>

Unlike tools that re-render components in isolation, Vizzly captures screenshots directly from your functional tests: the real thing. Whether you're validating AI-generated code or testing manual changes, you get reviewed visual evidence before anything hits production.
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.

## Why Vizzly?

**Local TDD workflow.** See changes as you type, not after CI. The `vizzly tdd` command runs a local dashboard that compares screenshots instantly and exposes the current workspace as local context.

**Meaningful diff metadata.** Vizzly stores rich diff evidence: changed regions, cluster metadata, fingerprints, hotspots, confirmed regions, and image URLs. Agents can inspect what changed instead of guessing from a pass/fail label.

**Any screenshot source.** Playwright, Cypress, Puppeteer, Selenium, native mobile apps, or even design mockups. If you can capture it, Vizzly can compare it.

**Approved baselines as truth.** Cloud context carries human review state. Local context carries the downloaded or generated baseline metadata. That is the bridge between TDD locally and collaborative review in Vizzly.
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.

## Quick Start

Requires Node.js 22+.
You need Node.js 22+.

```bash
pnpm install -g @vizzly-testing/cli

vizzly init
```

### Local Development (TDD Mode)
### Start Local TDD

Start the TDD server, run your tests in watch mode, and see visual diffs instantly at `http://localhost:47392`.
Start the TDD server, run your tests, and open the dashboard at
`http://localhost:47392`.

```bash
vizzly tdd start
pnpm test -- --watch
```

The dashboard shows diffs in real-time. Accept or reject changes right from the UI.
The dashboard shows screenshots, baselines, and diffs as they arrive. Accept or
reject changes right from the UI.

### Cloud Integration (CI/CD)
### Run With Cloud Review

For team collaboration and CI pipelines:
Use cloud builds when you want shared baselines, team review, and CI status:

```bash
vizzly login
vizzly run "pnpm test" --wait
```

The `--wait` flag polls for results and exits with code 1 if visual differences are detected.
`--wait` blocks until Vizzly finishes processing the build. It exits with code
`1` when visual differences need review.

For CI environments, set your project token:
In CI, use a project token:

```bash
export VIZZLY_TOKEN=your-project-token
vizzly run "pnpm test" --wait
```

### Visual Context For Agents
### Inspect Builds And Diffs

Use `vizzly context` when you want Vizzly to act like a visual context store, not just a test runner.
Use `vizzly context` when you need build, comparison, screenshot, or review
queue data from the terminal.

This is especially useful for LLM agents, automation, and quick debugging loops. Instead of
making a bunch of narrow API calls, you can ask for one build, comparison, screenshot, or review
queue bundle and get the evidence in one place.
This is useful for scripts, coding agents, and debugging loops. Instead of
making a pile of narrow API calls, ask for one focused bundle and get the
evidence in one place.

```bash
# Cloud context for a build or comparison
Expand All @@ -75,15 +78,19 @@ vizzly context comparison def456 --json
vizzly context build current --source local
vizzly context build current --source local --agent
vizzly context screenshot build-detail-screenshots --source local --json
vizzly context review-queue --source local --json
```

`--json` is the durable automation path. `--agent` gives a compact handoff for prompt assembly and local dogfooding. Add `--full` when an agent really needs the complete build context payload, or `--include screenshots,diffs,comments` when the compact JSON needs selected detail.
`--json` is the durable automation path. `--agent` gives a compact handoff for
prompt assembly. Add `--full` when you need the whole payload, or
`--include screenshots,diffs,comments` when compact JSON needs selected detail.

Local context is read-only and file-backed. It reads your existing `.vizzly` workspace state from
TDD runs, including screenshots, diffs, and any saved hotspot or region metadata.
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.

Cloud context is also read-only right now. That is intentional. It keeps the trust model simple:
Vizzly helps you see and inspect visual changes, while people still decide what gets approved.
Cloud context is also read-only right now. That is intentional. Vizzly helps you
see and inspect visual changes, while people still decide what gets approved.

## Capture Screenshots

Expand All @@ -103,7 +110,14 @@ test('homepage looks correct', async ({ page }) => {
});
```

The client SDK is lightweight—it just POSTs to the local server. Works with any test runner. SDKs available for [JavaScript](https://docs.vizzly.dev/integration/sdk/javascript), [Ruby](https://docs.vizzly.dev/integration/sdk/ruby), [Swift](https://docs.vizzly.dev/integration/sdk/swift), and [more](https://docs.vizzly.dev/integration/sdk/overview).
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](https://docs.vizzly.dev/integration/sdk/javascript),
[Ruby](https://docs.vizzly.dev/integration/sdk/ruby),
[Swift](https://docs.vizzly.dev/integration/sdk/swift), and
[more](https://docs.vizzly.dev/integration/sdk/overview).

Already saving screenshots to disk? Pass the file path instead:

Expand Down Expand Up @@ -131,31 +145,34 @@ Or create `vizzly.config.js` manually:
```javascript
export default {
comparison: {
threshold: 2.0 // CIEDE2000 Delta E (0=exact, 2=recommended)
}
// CIEDE2000 Delta E. 0 is exact. 2 is a good default.
threshold: 2.0,
},
};
```

## Commands

| Command | Description |
|---------|-------------|
| `vizzly tdd start` | Start local TDD server with dashboard |
| `vizzly tdd run "cmd"` | Run tests once, generate static report |
| `vizzly run "cmd"` | Run tests with cloud integration |
| `vizzly context ...` | Fetch visual context bundles for builds, comparisons, and screenshots |
| `vizzly upload <dir>` | Upload existing screenshots |
| `vizzly login` | Authenticate via browser |
| `vizzly doctor` | Validate local setup |
| Command | What it does |
| --- | --- |
| `vizzly tdd start` | Start the local TDD server and dashboard. |
| `vizzly tdd run "cmd"` | Run tests once and generate a static visual report. |
| `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 login` | Authenticate through the browser. |
| `vizzly doctor` | Validate your local setup. |

## Documentation

Full documentation at **[docs.vizzly.dev](https://docs.vizzly.dev)**—including framework guides,
CI/CD setup, configuration reference, and more.
Full documentation lives at **[docs.vizzly.dev](https://docs.vizzly.dev)**.
Start there for framework guides, CI setup, SDK examples, and the configuration
reference.

## Contributing

Found a bug? Have an idea? [Open an issue](https://github.com/vizzly-testing/cli/issues) or submit a PR.
Found a bug or have an idea?
[Open an issue](https://github.com/vizzly-testing/cli/issues) or send a PR.

## License

Expand Down
Binary file added docs/assets/vizzly-mascot-inspector.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vizzly-testing/cli",
"version": "0.32.0",
"description": "Visual review for agents and teams",
"description": "Visual regression testing from your terminal",
"keywords": [
"llm-context",
"visual-context",
Expand Down Expand Up @@ -54,6 +54,7 @@
"files": [
"bin",
"dist",
"docs/assets",
"README.md",
"LICENSE"
],
Expand Down
8 changes: 4 additions & 4 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const formatHelp = (cmd, helper) => {
// Cute grizzly bear mascot with square eyes (like the Vizzly logo!)
lines.push(c.brand.amber(' ʕ□ᴥ□ʔ'));
lines.push(` ${c.brand.amber(c.bold('vizzly'))} ${c.dim(`v${version}`)}`);
lines.push(` ${c.gray('Visual review for agents and teams')}`);
lines.push(` ${c.gray('Visual regression testing from your terminal')}`);
} else {
// Compact header for subcommands
lines.push(` ${c.brand.amber(c.bold('vizzly'))} ${c.white(cmd.name())}`);
Expand Down Expand Up @@ -332,7 +332,7 @@ function normalizeJsonArgv(argv, commandNames) {

program
.name('vizzly')
.description('Vizzly CLI for visual review')
.description('Vizzly CLI for visual regression testing')
.version(getPackageVersion())
.option('-c, --config <path>', 'Config file path')
.option('--token <token>', 'Vizzly API token')
Expand Down Expand Up @@ -768,11 +768,11 @@ Examples:

let contextCmd = program
.command('context')
.description('Fetch build context for agents and reviewers');
.description('Fetch build and diff context');

contextCmd
.command('build')
.description('Fetch build context for agents and reviewers')
.description('Fetch build context')
.argument('<build-id>', 'Build ID to fetch context for')
.option('--source <source>', 'Context source: auto, cloud, or local', 'auto')
.option('--agent', 'Output compact context for LLM agents')
Expand Down