# diffglow

Adopt this skill: https://proskills.md/skills/other/m1chaelchen-diffglow-skills-diffglow

Page: https://proskills.md/skills/other/m1chaelchen-diffglow-skills-diffglow
This document is the public skill bundle for that page. It contains SKILL.md and every helper file the catalog carries. No login is required.

## File: skills/diffglow/SKILL.md
size: 10120
sha: c7c01639cf36b086f589aee4bc6d16480e8c4e11
upstream: https://github.com/m1chaelchen/diffglow/blob/main/skills/diffglow/SKILL.md

````text
---
name: diffglow
description: Integrate Diffglow with existing E2E screenshot tooling, or verify a UI change through intent, captures, visual evidence, agent feedback, and reruns. Use for Playwright, Maestro, or other screenshot-producing suites; preserve the existing test runner.
---

# Diffglow

Use the customer's existing E2E tools to capture screenshots and Diffglow to
compare them. Use your own image-reading capabilities to assess visual intent.
The workflow is **intent → existing E2E captures → evidence → agent feedback →
rerun**. Routine changes do not require a separate snapshot approval ceremony.

## Find the integration point

Inspect the project's instructions, package manager, existing test commands,
screenshot checkpoints, CI jobs, and available reference captures. Preserve the
chosen runner and its assertions. Add named screenshot checkpoints only where
the requested coverage is missing; do not replace a working E2E suite.

- For Playwright, read [references/playwright.md](references/playwright.md).
- For Maestro, read [references/maestro.md](references/maestro.md).
- For verification plans and evidence reports, read
  [references/verification.md](references/verification.md).
- For another runner, use its existing screenshot output and the same file or
  folder comparison interface. Do not require browser-only metadata for mobile.

Prefer the project's installed, pinned Diffglow command. If installing it is part
of the request, use the project's package manager and record the resolved version
in its lockfile. Diffglow requires Node.js 22+. Check that version's `--help`
before configuring commands. Keep the skill usable independently of a particular
coding-agent vendor or hosted model provider.

## Integrate with the current CLI

Diffglow accepts PNG/JPEG files, two folders, a root with `baseline/` and `current/`,
or explicit JSON pairs. Names and variants must identify the same checkpoint
across runs. Separate browser/device, viewport, locale, and theme where relevant;
keep timestamps and run IDs out of checkpoint identity.

For an installed command, an evidence-producing invocation is:

```sh
diffglow captures/base captures/candidate --html --json --output-dir artifacts/diffglow/run-001
```

Adapt paths and the invocation to the existing project. Preserve stdout JSON and
the complete report directory, including assets, even if a comparison or E2E job
fails. Use a distinct report directory per run and keep verification plans and
agent reports outside the generated directory: rerunning replaces that directory.
Keep generated captures out of source control unless project policy says otherwise.

For reports that will be shared, add `--relative` to omit local absolute paths.
Use `--max-height 1200 --image-format webp` to reduce bundled report assets;
WebP is lossless, and the height limit preserves aspect ratio without enlarging
images. These settings leave comparison pixels and statistics at full resolution.
Keep the original captures for fine visual assessment: a reduced report image
cannot establish that small text or layout details are correct. Review screenshot
contents and user-supplied comparison IDs before sharing; path presentation does
not remove private content from either.

For known dynamic areas such as a mobile status-bar clock, use a narrow rectangle
in normalized screenshot pixels:

```sh
diffglow captures/base captures/candidate --ignore-region '0,0,160,60' --html --json --output-dir artifacts/diffglow/run-002
```

Repeat `--ignore-region 'x,y,width,height'` for multiple areas, or configure
`"ignoreRegions": [{"x": 0, "y": 0, "width": 160, "height": 60}]` in JSON.
Coordinates start at the top-left after orientation normalization, using actual
image pixels rather than CSS/device-independent coordinates. Positions must be
nonnegative integers and dimensions positive integers, with safe integer sums.
Rectangles clip to image coverage and overlapping pixels count once. CLI regions
replace the configured global `ignoreRegions` array; all configured values must
still be valid.

For different screenshot geometries, configure `ignoreRegionsById` glob rules or
add `ignoreRegions` to individual manifest pairs. Effective masks combine the
selected global array, every matching ID rule, and the pair's manifest regions.
CLI global replacements do not remove ID rules or pair regions. ID rules match
the comparison identity: the relative filename, a configured pairing key, or the
explicit manifest ID. For example:

```json
{
  "ignoreRegionsById": {
    "catalog/*.png": [{ "x": 720, "y": 340, "width": 180, "height": 48 }],
    "checkout-ready/ios/**": [{ "x": 0, "y": 0, "width": 160, "height": 60 }]
  }
}
```

Load these rules with `--config path/to/diffglow.config.json`, or use the single
input folder's automatically loaded `diffglow.config.json`. Diffglow does not
detect clocks automatically or resolve element selectors from screenshot pixels.
The existing capture tool can measure an element's rectangle and supply its
coordinates as a manifest mask.

Record the regions with the evidence and inspect that they do not hide relevant
UI. Masks change comparison only, **not screenshot redaction**: original values
remain visible in report previews. Ignored pixels retain current-image appearance,
are not highlighted, and are excluded from changed/unchanged/compared counts and
bounds. Each result records its effective `comparison.ignoreRegions` and
`stats.ignoredPixels`; batch `comparison.ignoreRegions` contains the global array,
and `summary.ignoredPixels` totals ignored pixels. HTML displays the exclusions.
If no pixels remain, the percentage is `0` and `--fail-on-diff` exits `0`, but the
visual check is inconclusive. Added/removed file statuses still describe coverage and require
interpretation even when all of their pixels are ignored.

Exit `0` means the comparison completed, even if images differ. With
`--fail-on-diff`, exit `1` means non-ignored raw differences were found; it does not
establish that they are regressions. Exit `2` means processing failed. Record E2E results
separately so a completed comparison cannot hide a failed test run. Preserve any
existing strict visual gate; do not turn it green by swallowing failures.

The CLI currently produces pixel evidence, not an AI verdict. It has no supported
JavaScript import API, semantic `verify` command, approval command, or automatic
baseline history. Plans and agent reports below are skill-authored artifacts,
separate from CLI `results.json`. If asked for an enforced semantic CI check,
identify that additional implementation explicitly; prose from this skill is
not an executable gate or independent verification service.

## Verify the change

1. Derive expected effects and protected behavior from the original request,
   acceptance criteria, and existing tests. Save that plan before inspecting the
   candidate images. If implementation already exists, record that fact and use
   the original requirements rather than treating the patch as proof of intent.
   Do not broaden expectations, masks, or tolerances to explain away a failure.
2. Obtain reference and candidate captures from the existing E2E workflow under
   matching render conditions. Record source revisions, runner outcomes, capture
   hashes, expected checkpoint coverage, and comparison settings. Confirm the
   images show the declared checkpoint/state; filenames alone do not establish
   that the correct screen was captured. Never label
   synthetic fixtures or two copies of the same capture as real before/after
   application evidence. If the reference or runner is unavailable, make useful
   integration changes and report the missing execution as inconclusive.
3. Check completeness before interpreting folder additions/removals. A missing
   screenshot may mean a skipped/failed test or absent shard. Require explicit
   scope/completion information for deletions; do not remove references based on
   absence alone. Aggregate compatible shards and identify retry attempts without
   selecting whichever image happens to pass.
4. Read the original before/after images and highlighted diff. Examine changed
   areas at sufficient resolution and keep whole-screen context. Pixel counts
   establish change, not correctness. Verify text, geometry, state, and visibility
   with supplied runner assertions or element metadata where available. Report
   screenshot-only judgments as model-assessed; an accessibility assertion alone
   does not prove the absence of visual clipping or overlap.
5. Return per-check **passed**, **failed**, or **inconclusive**, with evidence and
   verification method. A measured failure cannot be waived by model opinion.
   Missing coverage, unreadable evidence, or an ambiguous requirement stays
   inconclusive. Never invent model confidence percentages or claim the whole
   application is correct because captured checkpoints passed.
6. Fix demonstrated defects within the authorized task, then rerun the relevant
   existing E2E tests and comparison. Preserve earlier evidence, bound retries,
   and stop when checks pass or further progress needs missing infrastructure,
   product clarification, or authorization beyond the task. Report unresolved
   issues instead of weakening the checks.

## Handoff and references

Summarize intended effects verified, unexpected changes, failed/incomplete tests,
coverage limits, and links to the evidence. Keep raw diff status distinct from
the agent's semantic verdict. An integration-only request can be complete while
real application verification remains unexecuted; say which was achieved.

Use the project's established reference/history process if one exists. Do not
overwrite references merely to make a comparison pass. If automatic advancement
is requested, bind it to the exact verified capture hashes and the project's
normal trusted merge/check process, preserving previous revisions. Changes to
the images, reference, expectations, or settings invalidate affected conclusions.
Do not introduce manual per-snapshot approvals as the default workflow.
````

## File: skills/diffglow/references/maestro.md
size: 6192
sha: 5d5a43d36a341ed9ed0ed5c0a0615cefcec0ac9f
upstream: https://github.com/m1chaelchen/diffglow/blob/main/skills/diffglow/references/maestro.md

````text
# Add Diffglow to an existing Maestro suite

Keep Maestro responsible for mobile interactions, assertions, app installation,
device selection, and screenshots. Diffglow consumes exported images; it does not
run Maestro Flows or require Maestro Cloud. Reuse the project's installed Maestro
version, Flows, device setup, and test command.

## Capture a named checkpoint

Reuse existing explicit captures. Otherwise append a screenshot after the existing
Flow steps have established and asserted the intended screen state:

```yaml
# Existing navigation, state setup, and assertions run above this step.
- takeScreenshot:
    path: checkout/ready
```

[`takeScreenshot`](https://docs.maestro.dev/reference/commands-available/takescreenshot.md)
writes PNG and adds the extension, so the checkpoint name above ends in
`checkout/ready.png`. Choose a distinct stable name for each state. Avoid failure
screenshots as substitutes for intentional checkpoints; they may show a different
state. Keep screenshots unmasked unless the project already has a documented
capture policy that excludes specific dynamic content.

## Keep builds, variants, and runs identifiable

Use the project's existing process to install the base build and candidate build
on equivalent devices and run the same Flows. Do not change a developer's checkout,
stash their work, or infer the installed app version from the checkout alone.
Record the actual source commit, build identity, platform, device model, OS,
screen size/pixel ratio, theme, locale, test data, and Maestro version for each run.

These example commands only add output destinations to an existing invocation;
preserve the project's real Flow paths, device flags, environment, and report setup:

```bash
maestro test --test-output-dir=artifacts/visual/run-001/base/maestro .maestro/checkout.yaml
```

```bash
maestro test --test-output-dir=artifacts/visual/run-001/candidate/maestro .maestro/checkout.yaml
```

The [artifact documentation](https://docs.maestro.dev/maestro-flows/workspace-management/test-reports-and-artifacts.md)
currently describes timestamped session and per-Flow bundles. Explicit captures
reside in each bundle's `takeScreenshot/` folder. `--test-output-dir` selects a root;
it does not imply that `checkout/ready.png` sits directly under that root. Consult
the installed version's actual output. Where present, use the Flow `manifest.json`
to locate artifacts and `commands.json` to attribute captures to executed steps.
Do not hardcode a session timestamp or mistake Maestro's manifest for Diffglow's
pairing manifest.

Keep the E2E exit status and available test reports. Record expected versus captured
checkpoints, failed/skipped Flows, attempts, and required/completed shards in a
separate run inventory. Collect all required devices and shards before assessing
coverage. A failed or absent Flow cannot establish that a screen was deleted.
Pair iOS with the corresponding iOS variant and Android with Android; never
compare across different devices, languages, or themes and call the result a pass.

## Pair the actual screenshot paths

Build an explicit Diffglow manifest from recorded artifacts. The stable identity
is the checkpoint plus environment variant, not the timestamped artifact path.
For example, save `artifacts/visual/run-001/pairs.json`, replacing these example
session/Flow names with the actual paths from each run:

```json
{
  "pairs": [
    {
      "id": "checkout-ready/ios/iphone-16/light/en-US",
      "before": "base/maestro/base-session/checkout_flow/takeScreenshot/checkout/ready.png",
      "after": "candidate/maestro/candidate-session/checkout_flow/takeScreenshot/checkout/ready.png"
    }
  ]
}
```

Paths resolve relative to `pairs.json`, and IDs must be unique. After installing
and pinning Diffglow in the project, compare with the existing CLI:

```bash
npx --no-install diffglow --manifest artifacts/visual/run-001/pairs.json --json --html --output-dir artifacts/visual/run-001/diffglow-report > artifacts/visual/run-001/comparison.stdout.json
```

If existing automation exports complete screenshot-only base and candidate
directories with matching relative checkpoint names, those two directories can
be passed directly instead. Do not compare the whole Maestro artifact tree: it
can include automatic failure images, timestamps, and repeated Flow attempts.

Save each rerun under a new run ID. Keep originals, run inventories, and the
entire Diffglow report including assets. The report destination must be dedicated
to Diffglow because rerunning the CLI replaces that directory; put your metadata
and redirected stdout outside it.

## Interpret evidence and rerun

Read `results.json` and inspect before/current/highlighted images against the
original task's expectations and existing Maestro assertions. Identify clipping,
overlap, missing controls, and unintended changes only when the evidence supports
them. Separate measured pixel facts from model interpretation. An image comparison
does not establish that a native control is interactive or accessible; rely on
existing tests and report uncovered checks.

Return passed, failed, or inconclusive per expectation with evidence paths.
Fix unexpected changes, then rerun the affected existing Flows and compare the new
captures. Preserve earlier failures. Do not promote screenshots or ask users to
manually approve them as the way to make verification succeed.

Diffglow currently supplies comparison artifacts, not an AI verdict, baseline
approval/history command, capture runner, or supported JavaScript API:

- `0` without `--fail-on-diff` means comparison outputs were generated; differences
  may still exist, and the requested change may still be absent.
- `1` with `--fail-on-diff` signals raw differences, not a semantic regression.
- `2`, E2E failures, missing required captures, mismatched variants, and incomplete
  shard/device runs prevent a verified result. Retain their evidence.

Do not interpret folder mode's `added`/`removed` labels as intentional screen
changes without task and coverage evidence. Missing captures are uncovered scope;
a small changed percentage or an agent's confidence statement cannot repair it.
````

## File: skills/diffglow/references/playwright.md
size: 5873
sha: 985d3e2c9d7f3f3dc48ca4b9e6d24889d1424bbf
upstream: https://github.com/m1chaelchen/diffglow/blob/main/skills/diffglow/references/playwright.md

````text
# Add Diffglow to an existing Playwright suite

Keep Playwright responsible for navigation, assertions, application startup, and
screenshots. Diffglow consumes the image files. Reuse the project's installed
Playwright version, fixtures, projects, and invocation; do not replace its test
configuration or introduce another runner.

## Capture a named checkpoint

Reuse existing explicit screenshot captures when available. Otherwise add a
capture after the existing assertions that establish the intended screen state.
Inside an existing test receiving `({ page }, testInfo)`, for example:

```ts
// Existing navigation, data setup, and assertions run above this line.
const screenshotPath = testInfo.outputPath('diffglow', 'checkout-ready.png');
await page.screenshot({ path: screenshotPath, type: 'png' });
```

[`page.screenshot`](https://playwright.dev/docs/screenshots) supplies the PNG;
[`testInfo.outputPath`](https://playwright.dev/docs/api/class-testinfo#test-info-output-path)
isolates concurrent tests' output. Give each checkpoint a distinct name. Record
the actual path, project, test identity, and attempt in the capture inventory;
do not infer stable checkpoint identity from Playwright's generated directory name.

Preserve the suite's existing capture policy, including viewport versus full-page
screenshots. If animations or changing data cause noise, fix capture consistency
in the existing test setup and document any exclusions. Do not hide the changed
component or relax assertions to obtain a clean comparison.

## Keep base and candidate runs separate

Obtain the base build and candidate build through the project's existing build or
CI workflow. Do not switch branches, stash changes, or alter a developer's running
application to produce a reference. If a trustworthy base is unavailable, report
the comparison as inconclusive.

These are example destinations added to an existing command, run against the
corresponding build; retain the project's actual options and project names:

```bash
npx playwright test tests/checkout.spec.ts --project chromium --output artifacts/visual/run-001/base/playwright
```

```bash
npx playwright test tests/checkout.spec.ts --project chromium --output artifacts/visual/run-001/candidate/playwright
```

Playwright documents [`--output`](https://playwright.dev/docs/test-cli) for test
artifacts. Choose a new run directory for each rerun so earlier evidence survives.
For sharded suites, use distinct destinations per shard, then collect every
required shard before assessing coverage. Keep retries and repeated executions
identifiable; do not select the cleanest attempt and discard failures.

Alongside captures, record each build's commit and dirty-state/build identity,
Playwright and browser versions, OS/container, project/device, viewport, pixel
ratio, theme, locale, test-data identity, screenshot options, and capture time.
Include expected checkpoints, captured checkpoints, E2E exit status, skipped or
failed tests, retries, and required/completed shards. This inventory is workflow
metadata; it is not a Diffglow configuration schema. Pair only matching variants.

## Compare explicit checkpoints

Use a Diffglow manifest when generated test directories differ or contain retries.
For example, save `artifacts/visual/run-001/pairs.json` after replacing these
illustrative directory names with the recorded capture paths:

```json
{
  "pairs": [
    {
      "id": "checkout-ready/chromium/1280x720/light/en-US",
      "before": "base/playwright/checkout-guest-chromium/diffglow/checkout-ready.png",
      "after": "candidate/playwright/checkout-guest-chromium/diffglow/checkout-ready.png"
    }
  ]
}
```

Both paths resolve relative to `pairs.json`. IDs must be unique. After installing
and pinning Diffglow in the project, run:

```bash
npx --no-install diffglow --manifest artifacts/visual/run-001/pairs.json --json --html --output-dir artifacts/visual/run-001/diffglow-report > artifacts/visual/run-001/comparison.stdout.json
```

If the project already exports two complete screenshot-only folders with stable
relative names, pass those folders instead of creating a manifest. Never compare
the entire Playwright artifact tree: it can contain failure screenshots and
multiple attempts that are not intended checkpoints.

Keep the report directory separate from inputs and your own metadata. Diffglow
replaces its report directory on rerun. Preserve the entire report, including
assets, and both original capture inventories even if tests or comparisons fail.

## Feed evidence back to the coding agent

Inspect `results.json`, each before/current/diff image, existing E2E assertions,
and the expectations written before inspecting candidate output. Distinguish
observed pixel changes from an interpretation that the requested change is correct.
Report each expectation as passed, failed, or inconclusive with evidence paths.
Fix unexpected changes and rerun the affected existing tests into a new directory;
do not overwrite references or add manual snapshot approval as the acceptance step.

Diffglow currently has no AI verdict, baseline approval/history command, capture
runner, or supported JavaScript API. Its exit code is comparison evidence:

- `0` without `--fail-on-diff` means output generation succeeded; changes may exist.
- `1` with `--fail-on-diff` means raw differences were detected, not that they are
  regressions. Use this flag only when the integration needs that mechanical gate.
- `2`, failed E2E checks, missing required captures, mismatched environments, or
  incomplete shards prevent a verified result. Preserve errors in the final report.

A missing capture is uncovered scope until explained. Folder mode's `added` and
`removed` labels do not establish intentional UI additions or deletions. An
identical image also cannot prove that a required visual change occurred.
````

## File: skills/diffglow/references/verification.md
size: 5965
sha: dfb9c642774303d9055b67ebe9e1c694ca84449e
upstream: https://github.com/m1chaelchen/diffglow/blob/main/skills/diffglow/references/verification.md

````text
# Verification plans and evidence

These are artifacts authored by the agent using this skill. They are not inputs
understood by the current Diffglow CLI, its `--manifest` format, or a built-in AI
verification engine. Store them beside the generated comparison directory, never
inside a directory that Diffglow replaces.

## Establish intent

Record a small plan from the original task and project requirements. Prefer
concrete checks to "looks good" and separate an allowed effect from protected
behavior in the same region. Allowing a button's color to change does not allow
its label to disappear or its position to move. A code diff can help locate
relevant checkpoints but is not an independent statement of desired behavior.

For example, a plan for "make the checkout button green without changing layout":

```json
{
  "artifactType": "diffglow-agent-plan",
  "schemaVersion": 1,
  "requirement": "Make the checkout button green without changing layout",
  "expectations": [
    {
      "id": "checkout-color",
      "checkpoint": "checkout/ready",
      "expected": "Checkout button uses the project's specified green token"
    },
    {
      "id": "checkout-layout",
      "checkpoint": "checkout/ready",
      "expected": "Button label, geometry, and surrounding layout are preserved"
    }
  ],
  "requiredVariants": ["web-chromium-desktop-en-light"],
  "protectedCheckpoints": ["login/ready"]
}
```

Adapt the plan to the task. Do not invent a color token or other acceptance
criterion when the requirement does not specify one. Capture missing detail as a
limit on the corresponding check; progress on independent checks can continue.
For a broad redesign, use the supplied design/requirements and persistent layout
constraints rather than requiring every old pixel or element position to remain.

## Keep evidence attributable

Record enough to distinguish what was actually tested:

- Reference and candidate source revisions, dirty-source status where relevant,
  capture run IDs, screenshot hashes, and checkpoint names.
- Browser/platform/device profile, viewport, scale, theme, locale, and relevant
  test-data configuration. Separate incompatible variants rather than resizing
  images to make them agree.
- Existing E2E command/result, required shards, retry attempt, and which expected
  captures completed, failed, or were skipped. Missing screenshots are not proof
  of intentional removal. Mark unrepresented platforms as uncovered.
- Diffglow version, settings, raw exit code, and the saved JSON/report assets.
- The verification plan fingerprint and evidence supporting each conclusion.

Use an existing project metadata format when available. A file-based adapter can
record these alongside captures; Diffglow does not collect this metadata itself.
If noise is suspected, a bounded repeat of the same code/environment can help
identify unstable captures. Preserve the disagreement instead of retrying until
a favorable image appears or automatically increasing the threshold.

Record effective per-pair masks as comparison settings, including matching
`ignoreRegionsById` rules and manifest regions. Masked content remains visible in
images and cannot support a pixel-comparison conclusion about that area. Portable
paths (`--relative`) and smaller report assets (`--max-height`, lossless WebP) help
sharing, but do not redact captures. Retain full-resolution originals and inspect
them when reduced previews cannot resolve a required detail; unchanged statistics
do not give a thumbnail the evidentiary detail of the original image.

## Report evidence and uncertainty separately

An illustrative report structure:

```json
{
  "artifactType": "diffglow-agent-verification",
  "schemaVersion": 1,
  "verdict": "inconclusive",
  "comparison": {
    "exitCode": 0,
    "status": "different",
    "report": "run-001/comparison/results.json"
  },
  "checks": [
    {
      "id": "checkout-color",
      "status": "passed",
      "method": "runner-assertion",
      "evidence": ["run-001/runner-results.json#checkout-color"],
      "observation": "Existing runner assertion confirms the specified token"
    },
    {
      "id": "checkout-layout",
      "status": "inconclusive",
      "method": "visual-assessment",
      "evidence": ["run-001/comparison/index.html"],
      "observation": "The whole-page preview is too small to assess label clipping"
    }
  ],
  "coverage": {
    "required": ["web-chromium-desktop-en-light"],
    "completed": ["web-chromium-desktop-en-light"],
    "missing": []
  },
  "limitations": ["No native mobile captures were requested or checked"]
}
```

Populate reports only with evidence that exists and was inspected. Reference the
recorded run metadata and plan, as well as individual files/crops/assertions.
The example's runner assertion is not provided by Diffglow; if it did not run,
use the actual verification method and status instead.

Use `passed` only when every required check passes with adequate evidence and
coverage is complete. Any required failure makes the verdict `failed`; otherwise
an unresolved check, missing capture, or processing problem makes it
`inconclusive`. Record a nonzero E2E exit as an execution check: a documented
required assertion failure is `failed`, while an unexplained nonzero exit or
infrastructure failure is `inconclusive` until its cause is established. Neither
can yield an overall pass, and neither should be silently relabeled as a visual
regression. Preserve the original runner exit code and errors.

Distinguish pixel measurements, runner assertions, and model
assessments. A visual assessment can pass a scoped visual question, but cannot be
presented as a measured fact or proof that unobserved behavior works.

This report communicates the agent's conclusions. A CI system cannot enforce
these semantics simply by running today's comparison CLI. Preserve existing
gates and identify any separate verifier/policy implementation the customer wants.
````

## File: skills/diffglow/agents/openai.yaml
size: 267
sha: 4a76a9950db1d1825ee7cbae18bfe6f8ab99b383
upstream: https://github.com/m1chaelchen/diffglow/blob/main/skills/diffglow/agents/openai.yaml

```text
interface:
  display_name: "Diffglow"
  short_description: "Integrate and verify visual changes with existing E2E"
  default_prompt: "Use $diffglow to integrate visual comparison with my existing E2E tools and verify the intended UI change with evidence and reruns."
```

## File: README.md
upstream: https://github.com/m1chaelchen/diffglow/blob/main/README.md

````text
# Diffglow

Compare two screenshots and highlight changes directly over the second image.
Unchanged areas keep their original colors; changed pixels receive a 65% overlay,
magenta by default. You can choose the highlight color. Images stay on your machine.

![Before, after, and highlighted screenshot comparison](./docs/demo.png)

## Quick start

Requires Node.js 22 or newer. Diffglow supports Linux, macOS, and Windows, with CI
coverage for Node.js 22 and 24.

```bash
npx --yes diffglow before.png after.png --output highlighted.png
```

Or install the command:

```bash
npm install --global diffglow
diffglow before.png after.png --output highlighted.png
```

PNG and JPEG inputs can be mixed. Quote paths containing spaces:

```bash
diffglow "before screenshot.png" "after screenshot.jpg" -o "my diff.png"
```

The command prints the changed-pixel count, changed percentage, and absolute
output path. The default output is `diff.png` in the current directory. This
single-pair output is always PNG; missing parent directories are created. An
existing result can be replaced, but neither input can be overwritten, including
through a symbolic link or hard link.

## Integrate with an AI coding agent

The optional [Diffglow skill](./skills/diffglow/SKILL.md) helps your coding agent
integrate visual comparison with existing Playwright, Maestro, or other E2E tests:
**intent → existing E2E captures → evidence → agent feedback → rerun**.

Install Diffglow in your project, then install its bundled skill with the
[Skills CLI](https://github.com/vercel-labs/skills):

```bash
npm install --save-dev --save-exact diffglow
npx skills add ./node_modules/diffglow/skills/diffglow --skill diffglow
```

Choose your coding agent when prompted. Ask it to "Use the diffglow skill to add
visual verification to my existing E2E tests" or to verify a specific UI change.
The skill includes Playwright and Maestro integration guidance, comparison
commands, and a format for reporting verified effects, defects, and uncertainty.

Your E2E tools still capture screenshots. The skill uses your agent's existing
image-reading capabilities; Diffglow requires no additional AI service or API key.
Pixel statistics, runner assertions, and the agent's visual assessments remain
distinct. Routine changes do not require manual snapshot approvals.

The skill guides the agent; it does not add an AI verification engine, automatic
baseline updates, or a semantic CI gate to the CLI. A completed comparison is not
proof that a UI change is correct. Existing test failures and incomplete coverage
remain visible in the verification report.

## Options

| Option | Behavior |
| --- | --- |
| `-o, --output <path>` | Output `.png` path; defaults to `diff.png`. |
| `--threshold <0..1>` | Per-pixel color tolerance; defaults to `0.1`. Lower is more sensitive. |
| `--highlight-color <hex>` | Overlay color as `#RGB` or `#RRGGBB`; defaults to magenta (`#ff00ff`). |
| `--ignore-region <x,y,width,height>` | Exclude a rectangle from comparison; repeat for multiple areas. |
| `--fail-on-diff` | Exit `1` when changes exist, after saving the highlighted PNG. |
| `--json` | Write detailed comparison statistics as JSON to stdout; still save the PNG. |
| `--manifest <file>` | Compare explicitly named pairs from a JSON manifest. |
| `--config <file>` | Load JSON folder names, matching rules, threshold, highlight color, and ignored regions. |
| `--output-dir <dir>` | Batch/HTML report directory; defaults to `diffglow-report`. |
| `--html` | Generate an offline HTML review page and screenshot assets. |
| `--relative` | Present portable paths in text, JSON, and HTML instead of local absolute paths. |
| `--max-height <pixels>` | Limit report asset height without enlarging images; a positive integer. Requires `--html` for a single pair. |
| `--image-format <png\|webp>` | Report asset format; defaults to PNG. WebP is lossless. Requires `--html` for a single pair. |
| `-h, --help` | Show usage. |
| `-v, --version` | Show the installed version. |

For a more sensitive comparison:

```bash
diffglow before.png after.png --threshold 0 --output sensitive.png
```

The threshold controls color differences at individual pixels, rather than an
allowed percentage of changes. Detected anti-aliasing differences are ignored,
including at threshold `0`, to reduce text-edge noise. Diffglow compares visual
pixels rather than file bytes. JPEG compression can introduce visual differences.

Choose a highlight color for a single pair, folders, or manifest comparisons:

```bash
diffglow before.png after.png --highlight-color '#00ff00' -o green-diff.png
diffglow screenshots/ --highlight-color '#0af' --html
```

Quote the hex value so your shell preserves `#`. Colors accept three or six hex
digits, case-insensitively, and are normalized to lowercase `#rrggbb` in JSON.
Opacity stays at 65%. The color affects highlighted pixels, including added and
removed areas, and the HTML report legend; it does not affect which pixels count
as changes or the comparison statistics.

### Ignore clocks and other dynamic areas

Exclude a known changing area, such as a mobile status-bar clock:

```bash
diffglow before.png after.png --ignore-region '0,0,160,60' -o highlighted.png
```

Repeat the flag for multiple rectangles:

```bash
diffglow screenshots/ --ignore-region '0,0,160,60' --ignore-region '900,20,100,40' --html
```

Coordinates are integer **screenshot pixels**, after EXIF orientation is applied,
with `x,y` measured from the top-left. Use the image's actual pixel dimensions,
which may differ from CSS or device-independent coordinates. `x` and `y` must be
nonnegative; width and height must be positive. Coordinates, dimensions, and their
sums must be safe integers. Rectangles are clipped to the image coverage, and
overlapping ignored pixels count once.

Ignored pixels are excluded from changed, unchanged, and compared counts, so they
do not contribute to the changed percentage or `--fail-on-diff`. They keep the
current screenshot's original appearance without a highlight; ignored areas beyond
the current screenshot stay transparent. JSON and HTML reports record the regions
and ignored-pixel count. If nothing remains to compare, the percentage is `0` and
`--fail-on-diff` exits `0`; this makes no visual assertion about the ignored image.

Global regions apply to every comparison in a run. For prices, dates, or balances
that appear in different places, configure `ignoreRegionsById` rules or add
`ignoreRegions` to individual manifest pairs, as shown below. Keep masks narrow
enough to retain the visual coverage you need.

Masks affect comparison only: **they do not redact screenshot contents**. Baseline
and current previews still show the original prices, dates, balances, and other
content in those areas. Diffglow receives raster images, so it cannot resolve DOM
elements or selectors. Your screenshot capture tool can measure an element's
rectangle and supply those pixel coordinates in the manifest.

## Compare folders or multiple files

Pass two directories to compare matching relative filenames recursively:

```bash
diffglow baseline/ current/ --output-dir visual-results --fail-on-diff
```

Or pass one folder containing `baseline/` and `current/`:

```text
screenshots/
  baseline/
    home.png
    account/settings.png
  current/
    home.png
    account/settings.png
```

```bash
diffglow screenshots/ --html --output-dir visual-results
```

PNG, `.jpg`, and `.jpeg` filenames are discovered, including uppercase extensions.
Matching is case-sensitive and uses the entire relative filename by default.
Screenshots found only in `current/` are **added**; those found only in `baseline/`
are **removed**. Their image area outside ignored regions is highlighted.
Unrelated file types and symlinks encountered during directory traversal are
ignored. Explicit file inputs
and manifests retain the existing input-alias safeguards.

For arbitrary files, create a manifest. Paths resolve relative to t
````
