@agent-scope/cli 1.17.0 → 1.17.2
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/README.md +1176 -0
- package/dist/cli.js +71 -87
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +62 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -79
- package/dist/index.js.map +1 -1
- package/package.json +9 -8
package/README.md
ADDED
|
@@ -0,0 +1,1176 @@
|
|
|
1
|
+
# @agent-scope/cli
|
|
2
|
+
|
|
3
|
+
CLI for Scope — capture, replay, and analyze React components from the command line.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Quick Start](#quick-start)
|
|
9
|
+
- [Commands Reference](#commands-reference)
|
|
10
|
+
- [scope init](#scope-init)
|
|
11
|
+
- [scope capture](#scope-capture)
|
|
12
|
+
- [scope tree](#scope-tree)
|
|
13
|
+
- [scope report](#scope-report)
|
|
14
|
+
- [scope manifest](#scope-manifest)
|
|
15
|
+
- [scope render](#scope-render)
|
|
16
|
+
- [scope tokens](#scope-tokens)
|
|
17
|
+
- [scope instrument](#scope-instrument)
|
|
18
|
+
- [scope report baseline / diff / pr-comment](#scope-report-baseline--diff--pr-comment)
|
|
19
|
+
- [scope ci](#scope-ci)
|
|
20
|
+
- [scope site](#scope-site)
|
|
21
|
+
- [Configuration](#configuration)
|
|
22
|
+
- [Architecture](#architecture)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install -g @agent-scope/cli
|
|
30
|
+
# or use it locally in a project
|
|
31
|
+
npm install --save-dev @agent-scope/cli
|
|
32
|
+
npx scope --help
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Requirements:** Node.js 18+, Playwright browsers (installed automatically on first run).
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# 1. Scaffold configuration in your React project
|
|
43
|
+
scope init
|
|
44
|
+
|
|
45
|
+
# 2. Scan your components and build the manifest
|
|
46
|
+
scope manifest generate
|
|
47
|
+
|
|
48
|
+
# 3. Render all components to screenshots
|
|
49
|
+
scope render all
|
|
50
|
+
|
|
51
|
+
# 4. Build a static component gallery site
|
|
52
|
+
scope site build
|
|
53
|
+
|
|
54
|
+
# 5. Preview it
|
|
55
|
+
scope site serve
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Commands Reference
|
|
61
|
+
|
|
62
|
+
### `scope init`
|
|
63
|
+
|
|
64
|
+
Scaffold a Scope project — creates `reactscope.config.json`, an empty `reactscope.tokens.json`, and the `.reactscope/` output directory.
|
|
65
|
+
|
|
66
|
+
| Flag | Type | Default | Description |
|
|
67
|
+
|------|------|---------|-------------|
|
|
68
|
+
| `-y, --yes` | boolean | `false` | Accept all detected defaults without prompting |
|
|
69
|
+
| `--force` | boolean | `false` | Overwrite existing `reactscope.config.json` |
|
|
70
|
+
|
|
71
|
+
**Auto-detection:** Scope detects your framework (Next.js, Vite, Create React App, etc.), TypeScript support, and likely component file patterns before prompting.
|
|
72
|
+
|
|
73
|
+
**Example:**
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
scope init
|
|
77
|
+
scope init --yes # non-interactive, accept all defaults
|
|
78
|
+
scope init --force # overwrite existing config
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Interactive output:**
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
🚀 scope init — project configuration
|
|
85
|
+
Press Enter to accept the detected value shown in brackets.
|
|
86
|
+
|
|
87
|
+
Detected framework: Next.js
|
|
88
|
+
|
|
89
|
+
Component include patterns (comma-separated) [src/**/*.tsx]:
|
|
90
|
+
Component exclude patterns (comma-separated) [**/*.test.tsx,**/*.stories.tsx]:
|
|
91
|
+
Token file location [reactscope.tokens.json]:
|
|
92
|
+
Output directory [.reactscope/]:
|
|
93
|
+
|
|
94
|
+
✅ Scope project initialised!
|
|
95
|
+
|
|
96
|
+
Created files:
|
|
97
|
+
/home/user/project/reactscope.config.json
|
|
98
|
+
/home/user/project/reactscope.tokens.json
|
|
99
|
+
/home/user/project/.reactscope/
|
|
100
|
+
|
|
101
|
+
Next steps: run `scope manifest` to scan your components.
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Files written:**
|
|
105
|
+
|
|
106
|
+
| Path | Description |
|
|
107
|
+
|------|-------------|
|
|
108
|
+
| `reactscope.config.json` | Project configuration |
|
|
109
|
+
| `reactscope.tokens.json` | Design tokens stub |
|
|
110
|
+
| `.reactscope/` | Output directory |
|
|
111
|
+
| `.gitignore` | `.reactscope/` entry added |
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### `scope capture`
|
|
116
|
+
|
|
117
|
+
Capture a React component tree from a live URL and output raw JSON.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
scope capture <url>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
| Flag | Type | Default | Description |
|
|
124
|
+
|------|------|---------|-------------|
|
|
125
|
+
| `-o, --output <path>` | string | stdout | Write JSON to file instead of stdout |
|
|
126
|
+
| `--pretty` | boolean | `false` | Pretty-print JSON output |
|
|
127
|
+
| `--timeout <ms>` | number | `10000` | Max wait time for React to mount |
|
|
128
|
+
| `--wait <ms>` | number | `0` | Additional wait after page load before capture |
|
|
129
|
+
|
|
130
|
+
**Example:**
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
scope capture http://localhost:5173
|
|
134
|
+
scope capture http://localhost:5173 --pretty -o capture.json
|
|
135
|
+
scope capture http://localhost:5173 --timeout 30000
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Output:** `PageReport` JSON containing the full component tree, hooks, console entries, errors, and suspense boundaries.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### `scope tree`
|
|
143
|
+
|
|
144
|
+
Display the React component tree from a live URL as an ASCII tree in the terminal.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
scope tree <url>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
| Flag | Type | Default | Description |
|
|
151
|
+
|------|------|---------|-------------|
|
|
152
|
+
| `--depth <n>` | number | unlimited | Max depth to display |
|
|
153
|
+
| `--show-props` | boolean | `false` | Include prop names next to components |
|
|
154
|
+
| `--show-hooks` | boolean | `false` | Show hook counts per component |
|
|
155
|
+
| `--timeout <ms>` | number | `10000` | Max wait time for React to mount |
|
|
156
|
+
| `--wait <ms>` | number | `0` | Additional wait after page load |
|
|
157
|
+
|
|
158
|
+
**Example:**
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
scope tree http://localhost:5173
|
|
162
|
+
scope tree http://localhost:5173 --depth 3 --show-props
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Output:**
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
Button
|
|
169
|
+
├── div
|
|
170
|
+
│ ├── span
|
|
171
|
+
│ └── svg
|
|
172
|
+
└── FocusRing
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### `scope report`
|
|
178
|
+
|
|
179
|
+
Capture and display a human-readable summary of a React app.
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
scope report <url>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
| Flag | Type | Default | Description |
|
|
186
|
+
|------|------|---------|-------------|
|
|
187
|
+
| `--json` | boolean | `false` | Output as structured JSON instead of human-readable text |
|
|
188
|
+
| `--timeout <ms>` | number | `10000` | Max wait time for React to mount |
|
|
189
|
+
| `--wait <ms>` | number | `0` | Additional wait after page load |
|
|
190
|
+
|
|
191
|
+
**Example:**
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
scope report http://localhost:5173
|
|
195
|
+
scope report http://localhost:5173 --json
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**TTY output:**
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
Scope Report for http://localhost:5173
|
|
202
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
203
|
+
Components: 24 total (18 function, 4 memo, 2 forwardRef)
|
|
204
|
+
Max depth: 6
|
|
205
|
+
Hooks: 42 total (12 useState, 8 useEffect, ...)
|
|
206
|
+
Error boundaries: 2
|
|
207
|
+
Suspense boundaries: 1 (1 resolved)
|
|
208
|
+
Console entries: 3 (1 warn, 2 error)
|
|
209
|
+
Capture time: 45ms
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
### `scope manifest`
|
|
215
|
+
|
|
216
|
+
Manage the component manifest — a catalogue of all React components in your project with their metadata.
|
|
217
|
+
|
|
218
|
+
The manifest is stored at `.reactscope/manifest.json` by default.
|
|
219
|
+
|
|
220
|
+
#### `scope manifest generate`
|
|
221
|
+
|
|
222
|
+
Scan source files and generate the component manifest.
|
|
223
|
+
|
|
224
|
+
| Flag | Type | Default | Description |
|
|
225
|
+
|------|------|---------|-------------|
|
|
226
|
+
| `--root <path>` | string | cwd | Project root directory |
|
|
227
|
+
| `--output <path>` | string | `.reactscope/manifest.json` | Output path |
|
|
228
|
+
| `--include <globs>` | string | from config | Comma-separated glob patterns to include |
|
|
229
|
+
| `--exclude <globs>` | string | from config | Comma-separated glob patterns to exclude |
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
scope manifest generate
|
|
233
|
+
scope manifest generate --root /path/to/project --output manifest.json
|
|
234
|
+
scope manifest generate --include "src/**/*.tsx" --exclude "**/*.stories.tsx"
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Files written:** `.reactscope/manifest.json`
|
|
238
|
+
|
|
239
|
+
#### `scope manifest list`
|
|
240
|
+
|
|
241
|
+
List all components in the manifest.
|
|
242
|
+
|
|
243
|
+
| Flag | Type | Default | Description |
|
|
244
|
+
|------|------|---------|-------------|
|
|
245
|
+
| `--format <fmt>` | `json\|table` | auto (TTY→table, pipe→json) | Output format |
|
|
246
|
+
| `--filter <glob>` | string | — | Filter by component name glob |
|
|
247
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
scope manifest list
|
|
251
|
+
scope manifest list --filter "Button*"
|
|
252
|
+
scope manifest list --format json | jq '.[] | select(.complexityClass == "complex")'
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Table output (TTY):**
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
NAME FILE COMPLEXITY HOOKS CONTEXTS
|
|
259
|
+
Button src/Button.tsx simple 2 0
|
|
260
|
+
SearchPage src/SearchPage.tsx complex 5 2
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**JSON output (pipe):**
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
[
|
|
267
|
+
{
|
|
268
|
+
"name": "Button",
|
|
269
|
+
"file": "src/Button.tsx",
|
|
270
|
+
"complexityClass": "simple",
|
|
271
|
+
"hookCount": 2,
|
|
272
|
+
"contextCount": 0
|
|
273
|
+
}
|
|
274
|
+
]
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### `scope manifest get <name>`
|
|
278
|
+
|
|
279
|
+
Get full details of a single component by name.
|
|
280
|
+
|
|
281
|
+
| Flag | Type | Default | Description |
|
|
282
|
+
|------|------|---------|-------------|
|
|
283
|
+
| `--format <fmt>` | `json\|table` | auto | Output format |
|
|
284
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
scope manifest get Button
|
|
288
|
+
scope manifest get Button --format json
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**TTY output:**
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
Component: Button
|
|
295
|
+
File: src/Button.tsx
|
|
296
|
+
Export: named
|
|
297
|
+
Display Name: Button
|
|
298
|
+
Complexity: simple
|
|
299
|
+
Memoized: true
|
|
300
|
+
Forwarded Ref: false
|
|
301
|
+
HOC Wrappers: none
|
|
302
|
+
Hooks: useState, useCallback
|
|
303
|
+
Contexts: none
|
|
304
|
+
Composes: Icon
|
|
305
|
+
Composed By: ButtonGroup
|
|
306
|
+
Side Effects: none
|
|
307
|
+
|
|
308
|
+
Props (3):
|
|
309
|
+
variant: "primary" | "secondary" — optional [default: "primary"]
|
|
310
|
+
size: "sm" | "md" | "lg" — optional [default: "md"]
|
|
311
|
+
disabled: boolean — optional [default: false]
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
#### `scope manifest query`
|
|
315
|
+
|
|
316
|
+
Query components by attributes.
|
|
317
|
+
|
|
318
|
+
| Flag | Type | Default | Description |
|
|
319
|
+
|------|------|---------|-------------|
|
|
320
|
+
| `--context <name>` | string | — | Find components consuming a context |
|
|
321
|
+
| `--hook <name>` | string | — | Find components using a specific hook |
|
|
322
|
+
| `--complexity <class>` | `simple\|complex` | — | Filter by complexity class |
|
|
323
|
+
| `--side-effects` | boolean | `false` | Find components with any side effects |
|
|
324
|
+
| `--has-fetch` | boolean | `false` | Find components with fetch calls |
|
|
325
|
+
| `--format <fmt>` | `json\|table` | auto | Output format |
|
|
326
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
scope manifest query --hook useState --complexity complex
|
|
330
|
+
scope manifest query --context AuthContext
|
|
331
|
+
scope manifest query --has-fetch --format json
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
### `scope render`
|
|
337
|
+
|
|
338
|
+
Render components to PNG screenshots or JSON using esbuild bundling and Playwright.
|
|
339
|
+
|
|
340
|
+
#### `scope render <component>` (or `scope render component <component>`)
|
|
341
|
+
|
|
342
|
+
Render a single component.
|
|
343
|
+
|
|
344
|
+
| Flag | Type | Default | Description |
|
|
345
|
+
|------|------|---------|-------------|
|
|
346
|
+
| `--props <json>` | string | `{}` | Inline props JSON |
|
|
347
|
+
| `--viewport <WxH>` | string | `375x812` | Viewport size |
|
|
348
|
+
| `--theme <name>` | string | — | Theme name from the token system |
|
|
349
|
+
| `-o, --output <path>` | string | `.reactscope/renders/<component>.png` | Write PNG to file |
|
|
350
|
+
| `--format <fmt>` | `png\|json` | auto (TTY→png, pipe→json) | Output format |
|
|
351
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
scope render Button
|
|
355
|
+
scope render Button --props '{"variant":"primary","size":"lg"}'
|
|
356
|
+
scope render Button --viewport 1280x800 --format json
|
|
357
|
+
scope render Button -o screenshots/button.png
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**JSON output:**
|
|
361
|
+
|
|
362
|
+
```json
|
|
363
|
+
{
|
|
364
|
+
"component": "Button",
|
|
365
|
+
"props": { "variant": "primary" },
|
|
366
|
+
"width": 120,
|
|
367
|
+
"height": 48,
|
|
368
|
+
"renderTimeMs": 145,
|
|
369
|
+
"screenshot": "iVBORw0KGgoAAAANSUhEUgAA...",
|
|
370
|
+
"computedStyles": {}
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
**Files written (TTY mode):**
|
|
375
|
+
- `.reactscope/renders/<component>.png`
|
|
376
|
+
- `.reactscope/renders/<component>.json`
|
|
377
|
+
|
|
378
|
+
#### `scope render matrix <component>`
|
|
379
|
+
|
|
380
|
+
Render a component across a matrix of prop combinations (Cartesian product).
|
|
381
|
+
|
|
382
|
+
| Flag | Type | Default | Description |
|
|
383
|
+
|------|------|---------|-------------|
|
|
384
|
+
| `--axes <spec>` | string | — | Axis definitions, e.g. `'variant:primary,secondary size:sm,md,lg'` |
|
|
385
|
+
| `--contexts <ids>` | string | — | Composition context IDs, comma-separated |
|
|
386
|
+
| `--stress <ids>` | string | — | Stress preset IDs, comma-separated |
|
|
387
|
+
| `--sprite <path>` | string | `.reactscope/renders/<component>-matrix.png` | Write sprite sheet |
|
|
388
|
+
| `--format <fmt>` | `json\|png\|html\|csv` | auto | Output format |
|
|
389
|
+
| `--concurrency <n>` | number | `8` | Max parallel renders |
|
|
390
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
scope render matrix Button --axes 'variant:primary,secondary size:sm,md,lg'
|
|
394
|
+
scope render matrix Button --axes 'variant:primary,secondary' --format html > matrix.html
|
|
395
|
+
scope render matrix Button --axes 'variant:primary,secondary size:sm,md' --format csv
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**CSV output:**
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
component,variant,size,renderTimeMs,width,height
|
|
402
|
+
Button,primary,sm,145,100,36
|
|
403
|
+
Button,primary,md,148,120,48
|
|
404
|
+
Button,secondary,sm,142,100,36
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
#### `scope render all`
|
|
408
|
+
|
|
409
|
+
Render all components in the manifest.
|
|
410
|
+
|
|
411
|
+
| Flag | Type | Default | Description |
|
|
412
|
+
|------|------|---------|-------------|
|
|
413
|
+
| `--concurrency <n>` | number | `4` | Max parallel renders |
|
|
414
|
+
| `--output-dir <dir>` | string | `.reactscope/renders` | Output directory |
|
|
415
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
416
|
+
| `--format <fmt>` | `json\|png` | `png` | Output format |
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
scope render all
|
|
420
|
+
scope render all --concurrency 8 --output-dir ./screenshots
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
**Progress output (stderr):**
|
|
424
|
+
|
|
425
|
+
```
|
|
426
|
+
Rendering 128 components (concurrency: 4)…
|
|
427
|
+
Rendering 128/128 Button [===================> ] 95%
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Files written per component:**
|
|
431
|
+
|
|
432
|
+
| Path | Description |
|
|
433
|
+
|------|-------------|
|
|
434
|
+
| `.reactscope/renders/<component>.png` | Screenshot |
|
|
435
|
+
| `.reactscope/renders/<component>.json` | Structured render data |
|
|
436
|
+
| `.reactscope/renders/<component>.error.json` | Error details (if failed) |
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
### `scope tokens`
|
|
441
|
+
|
|
442
|
+
Manage and validate design tokens from `reactscope.tokens.json`.
|
|
443
|
+
|
|
444
|
+
**Token file resolution order:**
|
|
445
|
+
1. `--file` flag
|
|
446
|
+
2. `tokens.file` in `reactscope.config.json`
|
|
447
|
+
3. `reactscope.tokens.json` (default)
|
|
448
|
+
|
|
449
|
+
#### `scope tokens get <path>`
|
|
450
|
+
|
|
451
|
+
Resolve a token path to its computed value.
|
|
452
|
+
|
|
453
|
+
| Flag | Type | Default | Description |
|
|
454
|
+
|------|------|---------|-------------|
|
|
455
|
+
| `--file <path>` | string | — | Override token file path |
|
|
456
|
+
| `--format <fmt>` | `json\|text` | auto | Output format |
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
scope tokens get color.semantic.success
|
|
460
|
+
# Output: #22C55E
|
|
461
|
+
|
|
462
|
+
scope tokens get color.semantic.success --format json
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**JSON output:**
|
|
466
|
+
|
|
467
|
+
```json
|
|
468
|
+
{
|
|
469
|
+
"path": "color.semantic.success",
|
|
470
|
+
"value": "{color.green.500}",
|
|
471
|
+
"resolvedValue": "#22C55E",
|
|
472
|
+
"type": "color"
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
#### `scope tokens list [category]`
|
|
477
|
+
|
|
478
|
+
List tokens, optionally filtered by category or type.
|
|
479
|
+
|
|
480
|
+
| Flag | Type | Default | Description |
|
|
481
|
+
|------|------|---------|-------------|
|
|
482
|
+
| `--type <type>` | string | — | Filter by token type (`color`, `dimension`, `fontFamily`, etc.) |
|
|
483
|
+
| `--file <path>` | string | — | Override token file path |
|
|
484
|
+
| `--format <fmt>` | `json\|table` | auto | Output format |
|
|
485
|
+
|
|
486
|
+
```bash
|
|
487
|
+
scope tokens list
|
|
488
|
+
scope tokens list color
|
|
489
|
+
scope tokens list --type color --format json
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
**Table output:**
|
|
493
|
+
|
|
494
|
+
```
|
|
495
|
+
PATH VALUE RESOLVED TYPE
|
|
496
|
+
color.primary {color.blue.500} #3B82F6 color
|
|
497
|
+
color.semantic.success {color.green.500} #22C55E color
|
|
498
|
+
spacing.xs 0.25rem 0.25rem dimension
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### `scope tokens search <value>`
|
|
502
|
+
|
|
503
|
+
Find which tokens match a computed value. Supports fuzzy color matching.
|
|
504
|
+
|
|
505
|
+
| Flag | Type | Default | Description |
|
|
506
|
+
|------|------|---------|-------------|
|
|
507
|
+
| `--type <type>` | string | — | Restrict search to a token type |
|
|
508
|
+
| `--fuzzy` | boolean | `false` | Return nearest match even if no exact match |
|
|
509
|
+
| `--file <path>` | string | — | Override token file path |
|
|
510
|
+
| `--format <fmt>` | `json\|table` | auto | Output format |
|
|
511
|
+
|
|
512
|
+
```bash
|
|
513
|
+
scope tokens search "#22C55E"
|
|
514
|
+
scope tokens search "#22C55E" --fuzzy
|
|
515
|
+
scope tokens search "0.25rem" --type dimension
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
#### `scope tokens resolve <path>`
|
|
519
|
+
|
|
520
|
+
Show the full resolution chain for a token (useful for debugging alias chains).
|
|
521
|
+
|
|
522
|
+
| Flag | Type | Default | Description |
|
|
523
|
+
|------|------|---------|-------------|
|
|
524
|
+
| `--file <path>` | string | — | Override token file path |
|
|
525
|
+
| `--format <fmt>` | `json\|text` | auto | Output format |
|
|
526
|
+
|
|
527
|
+
```bash
|
|
528
|
+
scope tokens resolve color.semantic.success
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
**Text output:**
|
|
532
|
+
|
|
533
|
+
```
|
|
534
|
+
color.semantic.success → {color.green.500}
|
|
535
|
+
{color.green.500} → #22C55E
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
#### `scope tokens validate`
|
|
539
|
+
|
|
540
|
+
Validate the token file for errors (circular references, missing references, type mismatches).
|
|
541
|
+
|
|
542
|
+
| Flag | Type | Default | Description |
|
|
543
|
+
|------|------|---------|-------------|
|
|
544
|
+
| `--file <path>` | string | — | Override token file path |
|
|
545
|
+
| `--format <fmt>` | `json\|text` | auto | Output format |
|
|
546
|
+
|
|
547
|
+
```bash
|
|
548
|
+
scope tokens validate
|
|
549
|
+
scope tokens validate --file custom-tokens.json
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
**Success output:**
|
|
553
|
+
|
|
554
|
+
```
|
|
555
|
+
✓ Token file is valid: reactscope.tokens.json
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
**Error output:**
|
|
559
|
+
|
|
560
|
+
```
|
|
561
|
+
✗ Token file has 2 error(s): reactscope.tokens.json
|
|
562
|
+
|
|
563
|
+
CIRCULAR_REFERENCE [color.a]: Token references itself via chain
|
|
564
|
+
MISSING_REFERENCE [color.b]: Referenced token "color.missing" not found
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
#### `scope tokens compliance`
|
|
568
|
+
|
|
569
|
+
Check token compliance scores — how many computed CSS values in rendered components map back to design tokens.
|
|
570
|
+
|
|
571
|
+
| Flag | Type | Default | Description |
|
|
572
|
+
|------|------|---------|-------------|
|
|
573
|
+
| `--file <path>` | string | — | Override token file path |
|
|
574
|
+
| `--format <fmt>` | `json\|table` | auto | Output format |
|
|
575
|
+
| `--threshold <n>` | number | `0.90` | Fail if compliance is below this value (0–1) |
|
|
576
|
+
|
|
577
|
+
#### `scope tokens impact`
|
|
578
|
+
|
|
579
|
+
Analyze the impact of token changes — which components will be affected if a token value changes.
|
|
580
|
+
|
|
581
|
+
| Flag | Type | Default | Description |
|
|
582
|
+
|------|------|---------|-------------|
|
|
583
|
+
| `--token <path>` | string | — | Token path to analyze impact for |
|
|
584
|
+
| `--file <path>` | string | — | Override token file path |
|
|
585
|
+
| `--format <fmt>` | `json\|table` | auto | Output format |
|
|
586
|
+
|
|
587
|
+
#### `scope tokens preview`
|
|
588
|
+
|
|
589
|
+
Preview the visual effect of token changes before committing them.
|
|
590
|
+
|
|
591
|
+
| Flag | Type | Default | Description |
|
|
592
|
+
|------|------|---------|-------------|
|
|
593
|
+
| `--set <path=value>` | string | — | Token override, e.g. `color.primary=#FF0000` |
|
|
594
|
+
| `--file <path>` | string | — | Override token file path |
|
|
595
|
+
| `--format <fmt>` | `json\|html` | auto | Output format |
|
|
596
|
+
|
|
597
|
+
#### `scope tokens export`
|
|
598
|
+
|
|
599
|
+
Export tokens in various formats for consumption by other tools.
|
|
600
|
+
|
|
601
|
+
| Flag | Type | Default | Description |
|
|
602
|
+
|------|------|---------|-------------|
|
|
603
|
+
| `--format <fmt>` | `css\|tailwind\|json\|scss` | `css` | Export format |
|
|
604
|
+
| `--file <path>` | string | — | Override token file path |
|
|
605
|
+
| `-o, --output <path>` | string | stdout | Write to file |
|
|
606
|
+
|
|
607
|
+
```bash
|
|
608
|
+
scope tokens export --format css -o tokens.css
|
|
609
|
+
scope tokens export --format tailwind -o tailwind-tokens.js
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
### `scope instrument`
|
|
615
|
+
|
|
616
|
+
Structured runtime instrumentation for analyzing React component behavior during interactions.
|
|
617
|
+
|
|
618
|
+
#### `scope instrument renders <component>`
|
|
619
|
+
|
|
620
|
+
Trace re-render causality chains during an interaction sequence.
|
|
621
|
+
|
|
622
|
+
| Flag | Type | Default | Description |
|
|
623
|
+
|------|------|---------|-------------|
|
|
624
|
+
| `--interaction <json>` | string | `[]` | Interaction sequence JSON |
|
|
625
|
+
| `--json` | boolean | `false` | Force JSON output |
|
|
626
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
627
|
+
|
|
628
|
+
**Interaction steps** are JSON arrays with `action`, `target`, and optional fields:
|
|
629
|
+
|
|
630
|
+
```bash
|
|
631
|
+
scope instrument renders SearchPage \
|
|
632
|
+
--interaction '[{"action":"click","target":"button"},{"action":"type","target":"input","text":"hello"}]'
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
**Supported actions:** `click`, `type`, `wait`, `hover`, `blur`, `focus`, `scroll`
|
|
636
|
+
|
|
637
|
+
**JSON output:**
|
|
638
|
+
|
|
639
|
+
```json
|
|
640
|
+
{
|
|
641
|
+
"component": "SearchPage",
|
|
642
|
+
"interaction": [{"action": "click", "target": "button"}],
|
|
643
|
+
"summary": {
|
|
644
|
+
"totalRenders": 12,
|
|
645
|
+
"uniqueComponents": 5,
|
|
646
|
+
"wastedRenders": 2,
|
|
647
|
+
"interactionDurationMs": 450
|
|
648
|
+
},
|
|
649
|
+
"renders": [
|
|
650
|
+
{
|
|
651
|
+
"component": "SearchPage",
|
|
652
|
+
"renderIndex": 0,
|
|
653
|
+
"trigger": "state_change",
|
|
654
|
+
"propsChanged": false,
|
|
655
|
+
"stateChanged": true,
|
|
656
|
+
"contextChanged": false,
|
|
657
|
+
"memoized": false,
|
|
658
|
+
"wasted": false,
|
|
659
|
+
"chain": [{"component": "SearchPage", "trigger": "state_change"}],
|
|
660
|
+
"cascade": {
|
|
661
|
+
"totalRendersTriggered": 8,
|
|
662
|
+
"uniqueComponents": 3,
|
|
663
|
+
"unchangedPropRenders": 2
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
],
|
|
667
|
+
"flags": [
|
|
668
|
+
{
|
|
669
|
+
"id": "RENDER_CASCADE",
|
|
670
|
+
"severity": "warning",
|
|
671
|
+
"component": "SearchPage",
|
|
672
|
+
"detail": "State change in SearchPage triggered 8 downstream re-renders"
|
|
673
|
+
}
|
|
674
|
+
]
|
|
675
|
+
}
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
**Heuristic flags:** `WASTED_RENDER`, `RENDER_CASCADE`
|
|
679
|
+
|
|
680
|
+
#### `scope instrument hooks <component>`
|
|
681
|
+
|
|
682
|
+
Profile per-hook-instance data for a component.
|
|
683
|
+
|
|
684
|
+
| Flag | Type | Default | Description |
|
|
685
|
+
|------|------|---------|-------------|
|
|
686
|
+
| `--props <json>` | string | `{}` | Inline props JSON |
|
|
687
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
688
|
+
| `--format <fmt>` | `json\|text` | `json` | Output format |
|
|
689
|
+
| `--show-flags` | boolean | `false` | Show heuristic flags only |
|
|
690
|
+
|
|
691
|
+
```bash
|
|
692
|
+
scope instrument hooks Button
|
|
693
|
+
scope instrument hooks Button --props '{"variant":"primary"}' --show-flags
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
**JSON output:**
|
|
697
|
+
|
|
698
|
+
```json
|
|
699
|
+
{
|
|
700
|
+
"component": "Button",
|
|
701
|
+
"components": [
|
|
702
|
+
{
|
|
703
|
+
"name": "Button",
|
|
704
|
+
"source": {"file": "src/Button.tsx", "line": 42},
|
|
705
|
+
"hooks": [
|
|
706
|
+
{
|
|
707
|
+
"index": 0,
|
|
708
|
+
"type": "useState",
|
|
709
|
+
"currentValue": true,
|
|
710
|
+
"updateCount": 0
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
"index": 1,
|
|
714
|
+
"type": "useCallback",
|
|
715
|
+
"dependencyValues": ["variant"],
|
|
716
|
+
"recomputeCount": 0,
|
|
717
|
+
"cacheHitRate": 0
|
|
718
|
+
}
|
|
719
|
+
],
|
|
720
|
+
"flags": ["MEMO_INEFFECTIVE"]
|
|
721
|
+
}
|
|
722
|
+
],
|
|
723
|
+
"flags": ["MEMO_INEFFECTIVE"]
|
|
724
|
+
}
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
**Heuristic flags:** `WASTED_RENDER`, `MEMO_INEFFECTIVE`, `EFFECT_EVERY_RENDER`, `MISSING_CLEANUP`, `STALE_CLOSURE`, `STATE_UPDATE_LOOP`
|
|
728
|
+
|
|
729
|
+
#### `scope instrument profile <component>`
|
|
730
|
+
|
|
731
|
+
Capture a full interaction-scoped performance profile (JS timing, layout, paint, layout shifts).
|
|
732
|
+
|
|
733
|
+
| Flag | Type | Default | Description |
|
|
734
|
+
|------|------|---------|-------------|
|
|
735
|
+
| `--interaction <json>` | string | `[]` | Interaction steps |
|
|
736
|
+
| `--props <json>` | string | `{}` | Inline props JSON |
|
|
737
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
738
|
+
| `--format <fmt>` | `json\|text` | `json` | Output format |
|
|
739
|
+
| `--show-flags` | boolean | `false` | Show heuristic flags only |
|
|
740
|
+
|
|
741
|
+
```bash
|
|
742
|
+
scope instrument profile Button
|
|
743
|
+
scope instrument profile SearchPage \
|
|
744
|
+
--interaction '[{"action":"type","target":"input","text":"hello"}]'
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
**JSON output:**
|
|
748
|
+
|
|
749
|
+
```json
|
|
750
|
+
{
|
|
751
|
+
"component": "Button",
|
|
752
|
+
"totalRenders": 5,
|
|
753
|
+
"uniqueComponents": 3,
|
|
754
|
+
"wastedRenders": 1,
|
|
755
|
+
"timing": {
|
|
756
|
+
"js": 45,
|
|
757
|
+
"layout": 12,
|
|
758
|
+
"paint": 8
|
|
759
|
+
},
|
|
760
|
+
"layoutShifts": {
|
|
761
|
+
"count": 0,
|
|
762
|
+
"cumulativeScore": 0
|
|
763
|
+
},
|
|
764
|
+
"flags": [],
|
|
765
|
+
"interaction": []
|
|
766
|
+
}
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
**Heuristic flags:** `WASTED_RENDER`, `MEMO_INEFFECTIVE`, `EFFECT_EVERY_RENDER`, `MISSING_CLEANUP`, `HIGH_RENDER_COUNT`, `LAYOUT_SHIFT_DETECTED`, `SLOW_INTERACTION`
|
|
770
|
+
|
|
771
|
+
#### `scope instrument tree <component>`
|
|
772
|
+
|
|
773
|
+
Output a structured instrumentation tree of a rendered component, annotated with render counts, timing, and context usage.
|
|
774
|
+
|
|
775
|
+
| Flag | Type | Default | Description |
|
|
776
|
+
|------|------|---------|-------------|
|
|
777
|
+
| `--sort-by <field>` | `renderCount\|depth` | `depth` | Sort nodes by field |
|
|
778
|
+
| `--limit <n>` | number | — | Limit to first N nodes (depth-first) |
|
|
779
|
+
| `--uses-context <name>` | string | — | Filter to components using a specific context |
|
|
780
|
+
| `--provider-depth` | boolean | `false` | Annotate with context-provider nesting depth |
|
|
781
|
+
| `--wasted-renders` | boolean | `false` | Filter to components with wasted renders |
|
|
782
|
+
| `--format <fmt>` | `json\|tree` | auto (TTY→tree, pipe→json) | Output format |
|
|
783
|
+
| `--manifest <path>` | string | `.reactscope/manifest.json` | Path to manifest |
|
|
784
|
+
|
|
785
|
+
```bash
|
|
786
|
+
scope instrument tree SearchPage
|
|
787
|
+
scope instrument tree SearchPage --sort-by renderCount --limit 20
|
|
788
|
+
scope instrument tree SearchPage --wasted-renders
|
|
789
|
+
scope instrument tree SearchPage --format json | jq '.children[]'
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
**TTY (tree) output:**
|
|
793
|
+
|
|
794
|
+
```
|
|
795
|
+
SearchPage
|
|
796
|
+
├── div
|
|
797
|
+
│ ├── SearchInput [renders:1 45.32ms]
|
|
798
|
+
│ │ ├── input [renders:1]
|
|
799
|
+
│ │ └── ClearButton [memo] [renders:1]
|
|
800
|
+
│ └── ResultsList [ctx:ListContext] [renders:2 12.01ms]
|
|
801
|
+
│ └── ResultItem [consumer] [renders:3]
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
**JSON output:**
|
|
805
|
+
|
|
806
|
+
```json
|
|
807
|
+
{
|
|
808
|
+
"component": "SearchPage",
|
|
809
|
+
"type": "function",
|
|
810
|
+
"renderCount": 1,
|
|
811
|
+
"lastRenderDuration": 45.32,
|
|
812
|
+
"memoized": false,
|
|
813
|
+
"memoSkipped": 0,
|
|
814
|
+
"props": {"query": ""},
|
|
815
|
+
"propsChanged": false,
|
|
816
|
+
"state": {"searchTerm": ""},
|
|
817
|
+
"stateChanged": false,
|
|
818
|
+
"contexts": [],
|
|
819
|
+
"contextChanged": false,
|
|
820
|
+
"depth": 0,
|
|
821
|
+
"children": []
|
|
822
|
+
}
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
---
|
|
826
|
+
|
|
827
|
+
### `scope report baseline / diff / pr-comment`
|
|
828
|
+
|
|
829
|
+
Sub-commands for capturing and comparing baseline snapshots (visual regression workflow).
|
|
830
|
+
|
|
831
|
+
#### `scope report baseline`
|
|
832
|
+
|
|
833
|
+
Capture a complete baseline snapshot (manifest + renders + compliance data).
|
|
834
|
+
|
|
835
|
+
| Flag | Type | Default | Description |
|
|
836
|
+
|------|------|---------|-------------|
|
|
837
|
+
| `-o, --output <dir>` | string | `.reactscope/baseline` | Output directory |
|
|
838
|
+
| `--components <glob>` | string | — | Only baseline matching components |
|
|
839
|
+
| `--manifest <path>` | string | — | Use an existing manifest instead of regenerating |
|
|
840
|
+
| `--viewport <WxH>` | string | `375x812` | Viewport size |
|
|
841
|
+
|
|
842
|
+
```bash
|
|
843
|
+
scope report baseline
|
|
844
|
+
scope report baseline -o ./baselines/main
|
|
845
|
+
scope report baseline --components "Button,TextField"
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
**Files written:**
|
|
849
|
+
|
|
850
|
+
```
|
|
851
|
+
.reactscope/baseline/
|
|
852
|
+
├── manifest.json # Full component manifest
|
|
853
|
+
├── compliance.json # Token compliance batch report
|
|
854
|
+
└── renders/
|
|
855
|
+
├── Button.json # Structured render output
|
|
856
|
+
├── Button.png # Screenshot
|
|
857
|
+
├── Button.error.json # Error details (if failed)
|
|
858
|
+
└── ...
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
#### `scope report diff`
|
|
862
|
+
|
|
863
|
+
Compare current renders against a baseline snapshot and report regressions.
|
|
864
|
+
|
|
865
|
+
| Flag | Type | Default | Description |
|
|
866
|
+
|------|------|---------|-------------|
|
|
867
|
+
| `-b, --baseline <dir>` | string | `.reactscope/baseline` | Baseline directory |
|
|
868
|
+
| `--threshold <px>` | number | `10` | Pixel dimension threshold for regression |
|
|
869
|
+
| `--format <fmt>` | `json\|text\|html` | auto | Output format |
|
|
870
|
+
|
|
871
|
+
```bash
|
|
872
|
+
scope report diff
|
|
873
|
+
scope report diff --baseline ./baselines/main --threshold 5
|
|
874
|
+
scope report diff --format html > regression-report.html
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
**Text output:**
|
|
878
|
+
|
|
879
|
+
```
|
|
880
|
+
Visual Regression Report
|
|
881
|
+
========================
|
|
882
|
+
|
|
883
|
+
Regressions detected: 3
|
|
884
|
+
|
|
885
|
+
Button
|
|
886
|
+
Expected: 120×48px
|
|
887
|
+
Actual: 125×50px
|
|
888
|
+
Δ: +5px width, +2px height
|
|
889
|
+
|
|
890
|
+
SearchPage
|
|
891
|
+
Expected: 800×600px
|
|
892
|
+
Actual: 805×595px
|
|
893
|
+
Δ: +5px width, -5px height
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
#### `scope report pr-comment`
|
|
897
|
+
|
|
898
|
+
Generate a Markdown-formatted GitHub PR comment with regression findings.
|
|
899
|
+
|
|
900
|
+
```bash
|
|
901
|
+
scope report pr-comment
|
|
902
|
+
scope report pr-comment --baseline ./baselines/main | gh pr comment --body-file -
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
**Output:** Markdown suitable for posting as a GitHub PR comment.
|
|
906
|
+
|
|
907
|
+
---
|
|
908
|
+
|
|
909
|
+
### `scope ci`
|
|
910
|
+
|
|
911
|
+
Run a complete non-interactive CI pipeline: manifest generation → rendering → compliance checks → visual regression comparison.
|
|
912
|
+
|
|
913
|
+
| Flag | Type | Default | Description |
|
|
914
|
+
|------|------|---------|-------------|
|
|
915
|
+
| `-b, --baseline <dir>` | string | — | Baseline directory for regression comparison |
|
|
916
|
+
| `--checks <list>` | string | all | Comma-separated checks: `compliance,a11y,console-errors,visual-regression` |
|
|
917
|
+
| `--threshold <n>` | number | `0.90` | Compliance pass threshold (0–1) |
|
|
918
|
+
| `--viewport <WxH>` | string | `375x812` | Viewport size |
|
|
919
|
+
| `--json` | boolean | `false` | Emit structured JSON to stdout |
|
|
920
|
+
| `-o, --output <path>` | string | — | Write CI result JSON to file |
|
|
921
|
+
|
|
922
|
+
```bash
|
|
923
|
+
scope ci
|
|
924
|
+
scope ci --baseline .reactscope/baseline --threshold 0.95
|
|
925
|
+
scope ci --checks compliance,a11y --json
|
|
926
|
+
scope ci --json -o ci-result.json
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
**TTY output:**
|
|
930
|
+
|
|
931
|
+
```
|
|
932
|
+
Scope CI Report
|
|
933
|
+
================================================
|
|
934
|
+
Components: 128 total 124 rendered 4 failed
|
|
935
|
+
|
|
936
|
+
[pass] Compliance 94.2% >= threshold 90.0%
|
|
937
|
+
[FAIL] Visual regression detected in 2 component(s): Button, TextField
|
|
938
|
+
[pass] No console errors detected
|
|
939
|
+
[FAIL] 4 component(s) failed to render
|
|
940
|
+
|
|
941
|
+
================================================
|
|
942
|
+
CI failed in 23.4s (exit code 4)
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
**JSON output (`--json`):**
|
|
946
|
+
|
|
947
|
+
```json
|
|
948
|
+
{
|
|
949
|
+
"ranAt": "2026-03-11T15:30:45.123Z",
|
|
950
|
+
"passed": false,
|
|
951
|
+
"exitCode": 4,
|
|
952
|
+
"checks": [
|
|
953
|
+
{
|
|
954
|
+
"check": "compliance",
|
|
955
|
+
"passed": true,
|
|
956
|
+
"message": "Compliance 94.2% >= threshold 90.0%",
|
|
957
|
+
"value": 0.942,
|
|
958
|
+
"threshold": 0.9
|
|
959
|
+
},
|
|
960
|
+
{
|
|
961
|
+
"check": "visual-regression",
|
|
962
|
+
"passed": false,
|
|
963
|
+
"message": "Visual regression detected in 2 component(s): Button, TextField"
|
|
964
|
+
}
|
|
965
|
+
],
|
|
966
|
+
"components": {
|
|
967
|
+
"total": 128,
|
|
968
|
+
"rendered": 124,
|
|
969
|
+
"failed": 4
|
|
970
|
+
},
|
|
971
|
+
"complianceScore": 0.942,
|
|
972
|
+
"complianceThreshold": 0.9,
|
|
973
|
+
"baselineCompared": true,
|
|
974
|
+
"wallClockMs": 23456
|
|
975
|
+
}
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
**Exit codes:**
|
|
979
|
+
|
|
980
|
+
| Code | Meaning |
|
|
981
|
+
|------|---------|
|
|
982
|
+
| `0` | All checks passed |
|
|
983
|
+
| `1` | Compliance below threshold |
|
|
984
|
+
| `2` | Accessibility violations found |
|
|
985
|
+
| `3` | Console errors during render |
|
|
986
|
+
| `4` | Visual regression detected |
|
|
987
|
+
| `5` | Component render failures |
|
|
988
|
+
|
|
989
|
+
**Pipeline steps:**
|
|
990
|
+
1. Generate manifest (scan for components)
|
|
991
|
+
2. Render all components (4 parallel by default)
|
|
992
|
+
3. Run token-compliance checks
|
|
993
|
+
4. Compare against baseline (if `--baseline` provided)
|
|
994
|
+
5. Exit with appropriate code
|
|
995
|
+
|
|
996
|
+
---
|
|
997
|
+
|
|
998
|
+
### `scope site`
|
|
999
|
+
|
|
1000
|
+
Build and serve a static HTML component gallery from `.reactscope/` output.
|
|
1001
|
+
|
|
1002
|
+
#### `scope site build`
|
|
1003
|
+
|
|
1004
|
+
Build the static HTML gallery site.
|
|
1005
|
+
|
|
1006
|
+
| Flag | Type | Default | Description |
|
|
1007
|
+
|------|------|---------|-------------|
|
|
1008
|
+
| `-i, --input <path>` | string | `.reactscope` | Path to `.reactscope` input directory |
|
|
1009
|
+
| `-o, --output <path>` | string | `.reactscope/site` | Output directory |
|
|
1010
|
+
| `--base-path <path>` | string | `/` | Base URL path prefix for subdirectory deployment |
|
|
1011
|
+
| `--compliance <path>` | string | — | Path to compliance batch report JSON |
|
|
1012
|
+
| `--title <text>` | string | `Scope — Component Gallery` | Site title |
|
|
1013
|
+
|
|
1014
|
+
```bash
|
|
1015
|
+
scope site build
|
|
1016
|
+
scope site build -o ./docs/components
|
|
1017
|
+
scope site build --base-path /docs/ --title "Acme Component Library"
|
|
1018
|
+
scope site build --compliance .reactscope/compliance.json
|
|
1019
|
+
```
|
|
1020
|
+
|
|
1021
|
+
**Files written:**
|
|
1022
|
+
|
|
1023
|
+
```
|
|
1024
|
+
.reactscope/site/
|
|
1025
|
+
├── index.html # Gallery homepage with component grid + search
|
|
1026
|
+
├── dashboard.html # Analytics dashboard
|
|
1027
|
+
├── button.html # Per-component detail pages (slugified name)
|
|
1028
|
+
├── search-page.html
|
|
1029
|
+
└── ...
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
#### `scope site serve`
|
|
1033
|
+
|
|
1034
|
+
Serve the built site locally for preview.
|
|
1035
|
+
|
|
1036
|
+
| Flag | Type | Default | Description |
|
|
1037
|
+
|------|------|---------|-------------|
|
|
1038
|
+
| `-p, --port <number>` | number | `3000` | Port to listen on |
|
|
1039
|
+
| `-d, --dir <path>` | string | `.reactscope/site` | Directory to serve |
|
|
1040
|
+
|
|
1041
|
+
```bash
|
|
1042
|
+
scope site serve
|
|
1043
|
+
scope site serve --port 8080
|
|
1044
|
+
scope site serve --dir ./docs/components --port 8080
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
**Output:**
|
|
1048
|
+
|
|
1049
|
+
```
|
|
1050
|
+
Scope site running at http://localhost:3000
|
|
1051
|
+
Serving /home/user/project/.reactscope/site
|
|
1052
|
+
Press Ctrl+C to stop.
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
---
|
|
1056
|
+
|
|
1057
|
+
## Configuration
|
|
1058
|
+
|
|
1059
|
+
### `reactscope.config.json`
|
|
1060
|
+
|
|
1061
|
+
Full configuration schema:
|
|
1062
|
+
|
|
1063
|
+
```json
|
|
1064
|
+
{
|
|
1065
|
+
"components": {
|
|
1066
|
+
"include": ["src/**/*.tsx"],
|
|
1067
|
+
"exclude": ["**/*.test.tsx", "**/*.stories.tsx"],
|
|
1068
|
+
"wrappers": {
|
|
1069
|
+
"providers": [],
|
|
1070
|
+
"globalCSS": []
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
"render": {
|
|
1074
|
+
"viewport": {
|
|
1075
|
+
"default": { "width": 375, "height": 812 }
|
|
1076
|
+
},
|
|
1077
|
+
"theme": "light",
|
|
1078
|
+
"warmBrowser": false
|
|
1079
|
+
},
|
|
1080
|
+
"tokens": {
|
|
1081
|
+
"file": "reactscope.tokens.json",
|
|
1082
|
+
"compliance": {
|
|
1083
|
+
"threshold": 0.9
|
|
1084
|
+
}
|
|
1085
|
+
},
|
|
1086
|
+
"output": {
|
|
1087
|
+
"dir": ".reactscope/",
|
|
1088
|
+
"sprites": {
|
|
1089
|
+
"format": "png",
|
|
1090
|
+
"cellPadding": 8,
|
|
1091
|
+
"labelAxes": true
|
|
1092
|
+
},
|
|
1093
|
+
"json": {
|
|
1094
|
+
"pretty": false
|
|
1095
|
+
}
|
|
1096
|
+
},
|
|
1097
|
+
"ci": {
|
|
1098
|
+
"complianceThreshold": 0.9,
|
|
1099
|
+
"failOnA11yViolations": true,
|
|
1100
|
+
"failOnConsoleErrors": false,
|
|
1101
|
+
"baselinePath": ".reactscope/baseline"
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
### `reactscope.tokens.json`
|
|
1107
|
+
|
|
1108
|
+
Design token file format:
|
|
1109
|
+
|
|
1110
|
+
```json
|
|
1111
|
+
{
|
|
1112
|
+
"$schema": "https://raw.githubusercontent.com/FlatFilers/Scope/main/packages/tokens/schema.json",
|
|
1113
|
+
"tokens": {
|
|
1114
|
+
"color": {
|
|
1115
|
+
"primary": { "value": "#3B82F6", "$type": "color" },
|
|
1116
|
+
"semantic": {
|
|
1117
|
+
"success": { "value": "{color.green.500}", "$type": "color" }
|
|
1118
|
+
}
|
|
1119
|
+
},
|
|
1120
|
+
"spacing": {
|
|
1121
|
+
"xs": { "value": "0.25rem", "$type": "dimension" }
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
```
|
|
1126
|
+
|
|
1127
|
+
Tokens can reference other tokens using `{path.to.token}` syntax.
|
|
1128
|
+
|
|
1129
|
+
---
|
|
1130
|
+
|
|
1131
|
+
## Architecture
|
|
1132
|
+
|
|
1133
|
+
The CLI is built with [Commander.js](https://github.com/tj/commander.js) and organized as a tree of command modules. The `program.ts` entry point builds the command tree at import time without executing it, keeping it testable in isolation.
|
|
1134
|
+
|
|
1135
|
+
### Directory structure
|
|
1136
|
+
|
|
1137
|
+
```
|
|
1138
|
+
src/
|
|
1139
|
+
├── cli.ts # Entry point — creates and runs the program
|
|
1140
|
+
├── program.ts # Builds the Commander command tree
|
|
1141
|
+
├── browser.ts # Playwright-based browser capture
|
|
1142
|
+
├── component-bundler.ts # esbuild IIFE bundling of components
|
|
1143
|
+
├── manifest-commands.ts # manifest list/get/query/generate
|
|
1144
|
+
├── manifest-formatter.ts # Table/JSON formatting for manifest output
|
|
1145
|
+
├── render-commands.ts # render component/matrix/all
|
|
1146
|
+
├── render-formatter.ts # Table/JSON/HTML/CSV formatting for render output
|
|
1147
|
+
├── report-formatter.ts # Report summary formatting
|
|
1148
|
+
├── tree-formatter.ts # ASCII tree formatting
|
|
1149
|
+
├── site-commands.ts # site build/serve
|
|
1150
|
+
├── tailwind-css.ts # Tailwind v4 CSS compilation
|
|
1151
|
+
├── init/
|
|
1152
|
+
│ ├── index.ts # scope init — project scaffolding
|
|
1153
|
+
│ └── detect.ts # Framework/config auto-detection
|
|
1154
|
+
├── tokens/
|
|
1155
|
+
│ └── commands.ts # tokens get/list/search/resolve/validate/...
|
|
1156
|
+
├── instrument/
|
|
1157
|
+
│ ├── renders.ts # scope instrument renders
|
|
1158
|
+
│ ├── hooks.ts # scope instrument hooks
|
|
1159
|
+
│ ├── profile.ts # scope instrument profile
|
|
1160
|
+
│ └── tree.ts # scope instrument tree
|
|
1161
|
+
├── report/
|
|
1162
|
+
│ ├── baseline.ts # scope report baseline
|
|
1163
|
+
│ ├── diff.ts # scope report diff
|
|
1164
|
+
│ └── pr-comment.ts # scope report pr-comment
|
|
1165
|
+
└── ci/
|
|
1166
|
+
└── commands.ts # scope ci pipeline
|
|
1167
|
+
```
|
|
1168
|
+
|
|
1169
|
+
### Key patterns
|
|
1170
|
+
|
|
1171
|
+
- **TTY detection** — All formatters check `process.stdout.isTTY` to switch between human-readable (table/tree) and machine-readable (JSON) output.
|
|
1172
|
+
- **Lazy singletons** — `BrowserPool` is created on demand and reused within a single command invocation.
|
|
1173
|
+
- **Error wrapping** — `safeRender()` wraps individual component renders so one failure does not abort batch operations.
|
|
1174
|
+
- **Concurrent execution** — Render commands use configurable worker pools (`--concurrency`) for parallel rendering.
|
|
1175
|
+
- **Configuration resolution** — Manifest and token file paths are resolved through a fallback chain: CLI flag → config file → default path.
|
|
1176
|
+
- **Dual export** — The package exposes both ESM and CommonJS builds; the `scope` binary points to the CJS entrypoint for maximum compatibility.
|