@americano98/peye 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/dist/bin.js +3219 -0
- package/dist/bin.js.map +1 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
# peye
|
|
2
|
+
|
|
3
|
+
`peye` is a standalone CLI for visual diffing an implemented UI against a Figma reference or another screenshot. It is designed for agent-driven workflows and local terminal use: feed it a preview URL or image, feed it a reference URL or image, and it will produce deterministic artifacts plus a machine-readable JSON report.
|
|
4
|
+
|
|
5
|
+
The comparison core is intentionally separated from screenshot acquisition so the tool stays scriptable, predictable, and easy to embed into automation pipelines.
|
|
6
|
+
|
|
7
|
+
## What It Does
|
|
8
|
+
|
|
9
|
+
- Compare `preview` from a local screenshot or live URL
|
|
10
|
+
- Compare `reference` from a local screenshot or Figma URL
|
|
11
|
+
- Capture only a target element when the preview URL contains `#fragment`
|
|
12
|
+
- Generate a compact LLM-friendly `report.json`, `overlay.png`, `diff.png`, `heatmap.png`, plus normalized input images
|
|
13
|
+
- Group mismatches by DOM element for URL previews and by visual cluster for local image previews
|
|
14
|
+
- Expose structured failure metadata, normalized image dimensions, and per-finding hotspots for agent triage
|
|
15
|
+
- Return a recommendation:
|
|
16
|
+
- `pass`
|
|
17
|
+
- `pass_with_tolerated_differences`
|
|
18
|
+
- `retry_fix`
|
|
19
|
+
- `needs_human_review`
|
|
20
|
+
|
|
21
|
+
## Requirements
|
|
22
|
+
|
|
23
|
+
- Node.js `>= 22`
|
|
24
|
+
- A Chromium browser available to Playwright for URL capture
|
|
25
|
+
- One of these when `--reference` is a Figma URL:
|
|
26
|
+
- Figma desktop MCP running locally
|
|
27
|
+
- remote Figma MCP authorization in an interactive terminal
|
|
28
|
+
- `FIGMA_TOKEN` as a fallback for CI or REST-only workflows
|
|
29
|
+
|
|
30
|
+
When Figma MCP returns a screenshot that is smaller than the selected node's metadata size, `peye` automatically upscales the reference image back to the node dimensions before diffing. If you need a strict export raster from Figma, force REST with `PEYE_FIGMA_SOURCE=rest`.
|
|
31
|
+
|
|
32
|
+
If Playwright Chromium is missing, install it with:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx playwright install chromium
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
From the repository:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pnpm install
|
|
44
|
+
pnpm build
|
|
45
|
+
node dist/bin.js --help
|
|
46
|
+
node dist/bin.js --version
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
After publishing, install the CLI globally with:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm install -g @americano98/peye
|
|
53
|
+
peye --help
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`npm install` only installs the CLI. Agent integration files are kept in [`agents/`](./agents) and are not part of the published npm package.
|
|
57
|
+
|
|
58
|
+
## Agent Integration
|
|
59
|
+
|
|
60
|
+
If your agent runtime supports reusable skill or instruction files, copy or vendor [`agents/SKILL.md`](./agents/SKILL.md) into that runtime's skill registry.
|
|
61
|
+
|
|
62
|
+
Recommended practice:
|
|
63
|
+
|
|
64
|
+
- Install `peye` separately so the `peye` executable is available in `PATH`.
|
|
65
|
+
- Treat [`agents/SKILL.md`](./agents/SKILL.md) as an optional integration asset, not part of the CLI install step.
|
|
66
|
+
- Keep the skill file versioned alongside the CLI, so updates to command flags and report shape stay in sync.
|
|
67
|
+
- Adapt the file to your agent runtime if it expects a different frontmatter format or install location.
|
|
68
|
+
|
|
69
|
+
[`agents/openai.yaml`](./agents/openai.yaml) is included as a small example of agent-facing metadata and prompt wiring.
|
|
70
|
+
|
|
71
|
+
## CLI
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
peye compare \
|
|
75
|
+
--preview <url|path> \
|
|
76
|
+
--reference <figma-url|path> \
|
|
77
|
+
--output <dir> \
|
|
78
|
+
[--viewport 1920|1920x900] \
|
|
79
|
+
[--mode all|pixel|layout|color] \
|
|
80
|
+
[--selector <css>] \
|
|
81
|
+
[--full-page] \
|
|
82
|
+
[--quiet] \
|
|
83
|
+
[--report-stdout] \
|
|
84
|
+
[--threshold-pass 0.5] \
|
|
85
|
+
[--threshold-tolerated 1.5] \
|
|
86
|
+
[--threshold-retry 5]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Important Rules
|
|
90
|
+
|
|
91
|
+
- `--viewport` is required when `--preview` is a URL.
|
|
92
|
+
- `--viewport 1920` is valid and means `width=1920`, `height=900` by default.
|
|
93
|
+
- Use explicit `WIDTHxHEIGHT` only when exact viewport height matters for the comparison.
|
|
94
|
+
- If `--preview` is a local image and `--viewport` is omitted, viewport is inferred from the image dimensions.
|
|
95
|
+
- If `--preview` contains a hash, for example `https://example.com/#road-map`, `peye` automatically treats it as selector `#road-map` unless `--selector` is passed explicitly.
|
|
96
|
+
- `--full-page` is allowed only for URL preview capture without a selector.
|
|
97
|
+
- If `--reference` is a Figma URL, it must include `node-id`.
|
|
98
|
+
- `--quiet` suppresses the human-readable terminal summary.
|
|
99
|
+
- `--report-stdout` writes the compact JSON report to stdout and suppresses the human-readable summary.
|
|
100
|
+
|
|
101
|
+
## Examples
|
|
102
|
+
|
|
103
|
+
Compare two local screenshots:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
peye compare \
|
|
107
|
+
--preview ./artifacts/preview.png \
|
|
108
|
+
--reference ./artifacts/reference.png \
|
|
109
|
+
--output ./peye-output
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Capture a live preview page at a fixed viewport:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
peye compare \
|
|
116
|
+
--preview http://localhost:3000 \
|
|
117
|
+
--reference ./figma-export/home.png \
|
|
118
|
+
--viewport 1920 \
|
|
119
|
+
--output ./peye-output
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Capture only a single element via URL hash:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
peye compare \
|
|
126
|
+
--preview https://example.com/#road-map \
|
|
127
|
+
--reference ./figma-export/road-map.png \
|
|
128
|
+
--viewport 1920 \
|
|
129
|
+
--output ./peye-output
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Compare against a Figma node:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
peye compare \
|
|
136
|
+
--preview http://localhost:3000/#hero \
|
|
137
|
+
--reference "https://www.figma.com/design/FILE_KEY/Mockup?node-id=1-2" \
|
|
138
|
+
--viewport 1920 \
|
|
139
|
+
--output ./peye-output
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
By default this prefers Figma MCP. If MCP returns a downscaled screenshot, `peye` upsizes it to the node's Figma metadata dimensions before comparison so the reference stays aligned with the selected frame size.
|
|
143
|
+
|
|
144
|
+
Force REST fallback explicitly, for example in CI:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
PEYE_FIGMA_SOURCE=rest \
|
|
148
|
+
FIGMA_TOKEN=your_token_here \
|
|
149
|
+
peye compare \
|
|
150
|
+
--preview http://localhost:3000/#hero \
|
|
151
|
+
--reference "https://www.figma.com/design/FILE_KEY/Mockup?node-id=1-2" \
|
|
152
|
+
--viewport 1920 \
|
|
153
|
+
--output ./peye-output
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Write the machine-readable report to stdout for automation:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
peye compare \
|
|
160
|
+
--preview ./artifacts/preview.png \
|
|
161
|
+
--reference ./artifacts/reference.png \
|
|
162
|
+
--output ./peye-output \
|
|
163
|
+
--report-stdout
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Keep the CLI silent while still writing artifacts to disk:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
peye compare \
|
|
170
|
+
--preview ./artifacts/preview.png \
|
|
171
|
+
--reference ./artifacts/reference.png \
|
|
172
|
+
--output ./peye-output \
|
|
173
|
+
--quiet
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Output
|
|
177
|
+
|
|
178
|
+
`peye` writes these files into `--output`:
|
|
179
|
+
|
|
180
|
+
- `preview.png`: normalized preview image used for analysis
|
|
181
|
+
- `reference.png`: normalized reference image used for analysis
|
|
182
|
+
- `overlay.png`: blended reference + preview image
|
|
183
|
+
- `diff.png`: raw pixel diff image
|
|
184
|
+
- `heatmap.png`: mismatch heatmap with highlighted findings
|
|
185
|
+
- `report.json`: compact machine-readable result optimized for agent workflows
|
|
186
|
+
|
|
187
|
+
`report.json` is versioned and compact by default:
|
|
188
|
+
|
|
189
|
+
- `analysisMode` is `dom-elements` for URL captures and `visual-clusters` for local image inputs
|
|
190
|
+
- `images` preserves normalized preview, reference, and padded canvas dimensions for fast debugging
|
|
191
|
+
- `findings` is capped to the top actionable mismatches
|
|
192
|
+
- `findings[].signals` adds stable heuristic hints such as probable text clipping, capture crop, and viewport mismatch
|
|
193
|
+
- `findings[].hotspots` exposes the top mismatch subregions without forcing the caller to inspect images first
|
|
194
|
+
- `rollups.rawRegionCount` preserves the internal mismatch count without emitting every low-level region
|
|
195
|
+
- `error` is `null` on successful comparisons and contains a stable `code`, `message`, and `exitCode` for failure reports
|
|
196
|
+
|
|
197
|
+
## Automation
|
|
198
|
+
|
|
199
|
+
For agent workflows, prefer one of these modes:
|
|
200
|
+
|
|
201
|
+
- Default mode: writes `report.json` to `--output` and prints a short human summary to stdout
|
|
202
|
+
- `--quiet`: writes files to `--output` and keeps stdout empty on success
|
|
203
|
+
- `--report-stdout`: writes files to `--output` and also emits the full report JSON as a single stdout payload
|
|
204
|
+
|
|
205
|
+
`--report-stdout` is the most stable mode when another tool is parsing the command result directly.
|
|
206
|
+
|
|
207
|
+
Suggested orchestration policy:
|
|
208
|
+
|
|
209
|
+
- exit code `0`: accept or continue to the next step
|
|
210
|
+
- exit code `2`: fix the top finding and rerun
|
|
211
|
+
- exit code `3`: stop the auto-fix loop and inspect the report plus artifacts
|
|
212
|
+
- exit code `1`: treat as an operational or input error, read `error.code`, fix inputs or environment, and retry
|
|
213
|
+
|
|
214
|
+
Example `report.json` shape:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"analysisMode": "dom-elements",
|
|
219
|
+
"summary": {
|
|
220
|
+
"recommendation": "retry_fix",
|
|
221
|
+
"severity": "medium",
|
|
222
|
+
"reason": "Mismatch is 3.21%; localized issues were detected and should be fixed before retrying."
|
|
223
|
+
},
|
|
224
|
+
"inputs": {
|
|
225
|
+
"preview": {
|
|
226
|
+
"input": "http://localhost:3000/#hero",
|
|
227
|
+
"kind": "url",
|
|
228
|
+
"resolved": "http://localhost:3000/#hero",
|
|
229
|
+
"selector": "#hero"
|
|
230
|
+
},
|
|
231
|
+
"reference": {
|
|
232
|
+
"input": "https://www.figma.com/design/FILE_KEY/Mockup?node-id=1-2",
|
|
233
|
+
"kind": "figma-url",
|
|
234
|
+
"resolved": "https://www.figma.com/design/FILE_KEY/Mockup?node-id=1-2",
|
|
235
|
+
"selector": null,
|
|
236
|
+
"transport": "figma-mcp-desktop"
|
|
237
|
+
},
|
|
238
|
+
"viewport": {
|
|
239
|
+
"width": 1920,
|
|
240
|
+
"height": 900
|
|
241
|
+
},
|
|
242
|
+
"mode": "all",
|
|
243
|
+
"fullPage": false
|
|
244
|
+
},
|
|
245
|
+
"images": {
|
|
246
|
+
"preview": { "width": 1920, "height": 900 },
|
|
247
|
+
"reference": { "width": 1920, "height": 900 },
|
|
248
|
+
"canvas": { "width": 1920, "height": 900 }
|
|
249
|
+
},
|
|
250
|
+
"metrics": {
|
|
251
|
+
"mismatchPixels": 1234,
|
|
252
|
+
"mismatchPercent": 3.21,
|
|
253
|
+
"meanColorDelta": 7.42,
|
|
254
|
+
"maxColorDelta": 24.5,
|
|
255
|
+
"structuralMismatchPercent": 8.13,
|
|
256
|
+
"findingsCount": 2,
|
|
257
|
+
"affectedElementCount": 2,
|
|
258
|
+
"dimensionMismatch": {
|
|
259
|
+
"widthDelta": 0,
|
|
260
|
+
"heightDelta": 0,
|
|
261
|
+
"aspectRatioDelta": 0,
|
|
262
|
+
"hasMismatch": false
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
"rollups": {
|
|
266
|
+
"bySeverity": [{ "severity": "medium", "count": 2 }],
|
|
267
|
+
"byKind": [
|
|
268
|
+
{ "kind": "mixed", "count": 1 },
|
|
269
|
+
{ "kind": "color", "count": 1 }
|
|
270
|
+
],
|
|
271
|
+
"byTag": [
|
|
272
|
+
{ "tag": "button", "count": 1 },
|
|
273
|
+
{ "tag": "h1", "count": 1 }
|
|
274
|
+
],
|
|
275
|
+
"rawRegionCount": 18,
|
|
276
|
+
"findingsCount": 2,
|
|
277
|
+
"affectedElementCount": 2,
|
|
278
|
+
"omittedFindings": 0
|
|
279
|
+
},
|
|
280
|
+
"findings": [
|
|
281
|
+
{
|
|
282
|
+
"id": "finding-001",
|
|
283
|
+
"source": "dom-element",
|
|
284
|
+
"severity": "medium",
|
|
285
|
+
"kind": "mixed",
|
|
286
|
+
"summary": "Element <button> differs in both layout and styling.",
|
|
287
|
+
"bbox": {
|
|
288
|
+
"x": 20,
|
|
289
|
+
"y": 80,
|
|
290
|
+
"width": 120,
|
|
291
|
+
"height": 36
|
|
292
|
+
},
|
|
293
|
+
"regionCount": 11,
|
|
294
|
+
"mismatchPixels": 519,
|
|
295
|
+
"mismatchPercentOfCanvas": 1.54,
|
|
296
|
+
"issueTypes": ["position", "spacing", "style"],
|
|
297
|
+
"signals": [
|
|
298
|
+
{
|
|
299
|
+
"code": "probable_text_clipping",
|
|
300
|
+
"confidence": "medium",
|
|
301
|
+
"message": "Text content likely overflows the element bounds and is being clipped on the horizontal axis."
|
|
302
|
+
}
|
|
303
|
+
],
|
|
304
|
+
"hotspots": [{ "x": 20, "y": 80, "width": 52, "height": 36 }],
|
|
305
|
+
"element": {
|
|
306
|
+
"tag": "button",
|
|
307
|
+
"selector": "section#hero > button#cta",
|
|
308
|
+
"role": null,
|
|
309
|
+
"textSnippet": "Buy",
|
|
310
|
+
"bbox": {
|
|
311
|
+
"x": 20,
|
|
312
|
+
"y": 80,
|
|
313
|
+
"width": 120,
|
|
314
|
+
"height": 36
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
],
|
|
319
|
+
"artifacts": {
|
|
320
|
+
"reference": "/abs/path/reference.png",
|
|
321
|
+
"preview": "/abs/path/preview.png",
|
|
322
|
+
"overlay": "/abs/path/overlay.png",
|
|
323
|
+
"diff": "/abs/path/diff.png",
|
|
324
|
+
"heatmap": "/abs/path/heatmap.png",
|
|
325
|
+
"report": "/abs/path/report.json"
|
|
326
|
+
},
|
|
327
|
+
"error": null
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Failure reports keep the same top-level shape and set `error` to a structured object, for example:
|
|
332
|
+
|
|
333
|
+
```json
|
|
334
|
+
{
|
|
335
|
+
"summary": {
|
|
336
|
+
"recommendation": "needs_human_review",
|
|
337
|
+
"severity": "medium",
|
|
338
|
+
"reason": "Preview URL requires --viewport so the browser screenshot is deterministic."
|
|
339
|
+
},
|
|
340
|
+
"error": {
|
|
341
|
+
"code": "preview_viewport_required",
|
|
342
|
+
"message": "Preview URL requires --viewport so the browser screenshot is deterministic.",
|
|
343
|
+
"exitCode": 1
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Exit Codes
|
|
349
|
+
|
|
350
|
+
- `0`: `pass` or `pass_with_tolerated_differences`
|
|
351
|
+
- `2`: `retry_fix`
|
|
352
|
+
- `3`: `needs_human_review`
|
|
353
|
+
- `1`: operational error
|
|
354
|
+
|
|
355
|
+
## Troubleshooting
|
|
356
|
+
|
|
357
|
+
- `Preview URL requires --viewport`: pass `--viewport 1920` or `--viewport 1920x900` when `--preview` is a URL.
|
|
358
|
+
- Playwright cannot launch Chromium: install it with `npx playwright install chromium`.
|
|
359
|
+
- Figma URL falls back to REST unexpectedly: check `inputs.reference.transport` in `report.json` and ensure `PEYE_FIGMA_SOURCE` is not forcing `rest`.
|
|
360
|
+
- Remote Figma MCP requires authorization: run `peye compare` in an interactive terminal so it can complete the OAuth callback flow.
|
|
361
|
+
- `FIGMA_TOKEN is required`: either export `FIGMA_TOKEN`, or make sure a Figma MCP source is reachable for Figma URLs.
|
|
362
|
+
- Figma MCP reference still looks softer than a manual export: MCP screenshots may be downscaled by Figma first; `peye` upscales them back to the node size for comparison, but if you need the original export raster use `PEYE_FIGMA_SOURCE=rest` with `FIGMA_TOKEN`.
|
|
363
|
+
- Selector capture fails: verify the selector exists at capture time and do not combine selector capture with `--full-page`.
|
|
364
|
+
- Large dimension mismatch triggers `needs_human_review`: check that preview and reference target the same frame, selector, and viewport.
|
|
365
|
+
|
|
366
|
+
## Limitations
|
|
367
|
+
|
|
368
|
+
- No config file support yet; inputs are provided through CLI flags only.
|
|
369
|
+
- No mask support yet; every visible pixel participates in the comparison.
|
|
370
|
+
- No automatic geometric alignment step yet; mismatches are evaluated on the captured canvas as-is.
|
|
371
|
+
- Browser capture currently uses Playwright Chromium.
|
|
372
|
+
- DOM-based findings are heuristic and depend on the element boxes collected during capture.
|
|
373
|
+
- Exit code `1` can still happen before the CLI is able to produce comparison artifacts; use `error.code` when `report.json` is present and stderr otherwise.
|
|
374
|
+
|
|
375
|
+
## Uninstall
|
|
376
|
+
|
|
377
|
+
If `peye` was installed globally, remove it with your package manager:
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
npm uninstall -g peye
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
pnpm remove -g peye
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
If it was installed in a project, use:
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
npm uninstall peye
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
or:
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
pnpm remove peye
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## Development
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
pnpm install
|
|
403
|
+
pnpm format:check
|
|
404
|
+
pnpm lint
|
|
405
|
+
pnpm typecheck
|
|
406
|
+
pnpm test
|
|
407
|
+
pnpm build
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Run the full quality gate with:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
pnpm check
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
Clean generated local artifacts with:
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
pnpm clean
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
For local development without building every time:
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
pnpm dev compare --preview ./preview.png --reference ./reference.png --output ./tmp/peye
|
|
426
|
+
```
|