@agent-scope/cli
v1.20.0
Published
CLI for Scope — capture, replay, and generate tests from the command line
Readme
@agent-scope/cli
CLI for Scope — capture, replay, and analyze React components from the command line.
Table of Contents
Installation
npm install -g @agent-scope/cli
# or use it locally in a project
npm install --save-dev @agent-scope/cli
npx scope --helpRequirements: Node.js 18+, Playwright browsers (installed automatically on first run).
Quick Start
# 1. Scaffold configuration in your React project
scope init
# 2. Scan your components and build the manifest
scope manifest generate
# 3. Render all components to screenshots
scope render all
# 4. Build a static component gallery site
scope site build
# 5. Preview it
scope site serveCommands Reference
scope init
Scaffold a Scope project — creates reactscope.config.json, an empty reactscope.tokens.json, and the .reactscope/ output directory.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| -y, --yes | boolean | false | Accept all detected defaults without prompting |
| --force | boolean | false | Overwrite existing reactscope.config.json |
Auto-detection: Scope detects your framework (Next.js, Vite, Create React App, etc.), TypeScript support, and likely component file patterns before prompting.
Example:
scope init
scope init --yes # non-interactive, accept all defaults
scope init --force # overwrite existing configInteractive output:
🚀 scope init — project configuration
Press Enter to accept the detected value shown in brackets.
Detected framework: Next.js
Component include patterns (comma-separated) [src/**/*.tsx]:
Component exclude patterns (comma-separated) [**/*.test.tsx,**/*.stories.tsx]:
Token file location [reactscope.tokens.json]:
Output directory [.reactscope/]:
✅ Scope project initialised!
Created files:
/home/user/project/reactscope.config.json
/home/user/project/reactscope.tokens.json
/home/user/project/.reactscope/
Next steps: run `scope manifest` to scan your components.Files written:
| Path | Description |
|------|-------------|
| reactscope.config.json | Project configuration |
| reactscope.tokens.json | Design tokens stub |
| .reactscope/ | Output directory |
| .gitignore | .reactscope/ entry added |
scope capture
Capture a React component tree from a live URL and output raw JSON.
scope capture <url>| Flag | Type | Default | Description |
|------|------|---------|-------------|
| -o, --output <path> | string | stdout | Write JSON to file instead of stdout |
| --pretty | boolean | false | Pretty-print JSON output |
| --timeout <ms> | number | 10000 | Max wait time for React to mount |
| --wait <ms> | number | 0 | Additional wait after page load before capture |
Example:
scope capture http://localhost:5173
scope capture http://localhost:5173 --pretty -o capture.json
scope capture http://localhost:5173 --timeout 30000Output: PageReport JSON containing the full component tree, hooks, console entries, errors, and suspense boundaries.
scope tree
Display the React component tree from a live URL as an ASCII tree in the terminal.
scope tree <url>| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --depth <n> | number | unlimited | Max depth to display |
| --show-props | boolean | false | Include prop names next to components |
| --show-hooks | boolean | false | Show hook counts per component |
| --timeout <ms> | number | 10000 | Max wait time for React to mount |
| --wait <ms> | number | 0 | Additional wait after page load |
Example:
scope tree http://localhost:5173
scope tree http://localhost:5173 --depth 3 --show-propsOutput:
Button
├── div
│ ├── span
│ └── svg
└── FocusRingscope report
Capture and display a human-readable summary of a React app.
scope report <url>| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --json | boolean | false | Output as structured JSON instead of human-readable text |
| --timeout <ms> | number | 10000 | Max wait time for React to mount |
| --wait <ms> | number | 0 | Additional wait after page load |
Example:
scope report http://localhost:5173
scope report http://localhost:5173 --jsonTTY output:
Scope Report for http://localhost:5173
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Components: 24 total (18 function, 4 memo, 2 forwardRef)
Max depth: 6
Hooks: 42 total (12 useState, 8 useEffect, ...)
Error boundaries: 2
Suspense boundaries: 1 (1 resolved)
Console entries: 3 (1 warn, 2 error)
Capture time: 45msscope manifest
Manage the component manifest — a catalogue of all React components in your project with their metadata.
The manifest is stored at .reactscope/manifest.json by default.
scope manifest generate
Scan source files and generate the component manifest.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --root <path> | string | cwd | Project root directory |
| --output <path> | string | .reactscope/manifest.json | Output path |
| --include <globs> | string | from config | Comma-separated glob patterns to include |
| --exclude <globs> | string | from config | Comma-separated glob patterns to exclude |
scope manifest generate
scope manifest generate --root /path/to/project --output manifest.json
scope manifest generate --include "src/**/*.tsx" --exclude "**/*.stories.tsx"Files written: .reactscope/manifest.json
scope manifest list
List all components in the manifest.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --format <fmt> | json\|table | auto (TTY→table, pipe→json) | Output format |
| --filter <glob> | string | — | Filter by component name glob |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
scope manifest list
scope manifest list --filter "Button*"
scope manifest list --format json | jq '.[] | select(.complexityClass == "complex")'Table output (TTY):
NAME FILE COMPLEXITY HOOKS CONTEXTS
Button src/Button.tsx simple 2 0
SearchPage src/SearchPage.tsx complex 5 2JSON output (pipe):
[
{
"name": "Button",
"file": "src/Button.tsx",
"complexityClass": "simple",
"hookCount": 2,
"contextCount": 0
}
]scope manifest get <name>
Get full details of a single component by name.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --format <fmt> | json\|table | auto | Output format |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
scope manifest get Button
scope manifest get Button --format jsonTTY output:
Component: Button
File: src/Button.tsx
Export: named
Display Name: Button
Complexity: simple
Memoized: true
Forwarded Ref: false
HOC Wrappers: none
Hooks: useState, useCallback
Contexts: none
Composes: Icon
Composed By: ButtonGroup
Side Effects: none
Props (3):
variant: "primary" | "secondary" — optional [default: "primary"]
size: "sm" | "md" | "lg" — optional [default: "md"]
disabled: boolean — optional [default: false]scope manifest query
Query components by attributes.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --context <name> | string | — | Find components consuming a context |
| --hook <name> | string | — | Find components using a specific hook |
| --complexity <class> | simple\|complex | — | Filter by complexity class |
| --side-effects | boolean | false | Find components with any side effects |
| --has-fetch | boolean | false | Find components with fetch calls |
| --format <fmt> | json\|table | auto | Output format |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
scope manifest query --hook useState --complexity complex
scope manifest query --context AuthContext
scope manifest query --has-fetch --format jsonscope render
Render components to PNG screenshots or JSON using esbuild bundling and Playwright.
scope render <component> (or scope render component <component>)
Render a single component.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --props <json> | string | {} | Inline props JSON |
| --viewport <WxH> | string | 375x812 | Viewport size |
| --theme <name> | string | — | Theme name from the token system |
| -o, --output <path> | string | .reactscope/renders/<component>.png | Write PNG to file |
| --format <fmt> | png\|json | auto (TTY→png, pipe→json) | Output format |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
scope render Button
scope render Button --props '{"variant":"primary","size":"lg"}'
scope render Button --viewport 1280x800 --format json
scope render Button -o screenshots/button.pngJSON output:
{
"component": "Button",
"props": { "variant": "primary" },
"width": 120,
"height": 48,
"renderTimeMs": 145,
"screenshot": "iVBORw0KGgoAAAANSUhEUgAA...",
"computedStyles": {}
}Files written (TTY mode):
.reactscope/renders/<component>.png.reactscope/renders/<component>.json
scope render matrix <component>
Render a component across a matrix of prop combinations (Cartesian product).
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --axes <spec> | string | — | Axis definitions, e.g. 'variant:primary,secondary size:sm,md,lg' |
| --contexts <ids> | string | — | Composition context IDs, comma-separated |
| --stress <ids> | string | — | Stress preset IDs, comma-separated |
| --sprite <path> | string | .reactscope/renders/<component>-matrix.png | Write sprite sheet |
| --format <fmt> | json\|png\|html\|csv | auto | Output format |
| --concurrency <n> | number | 8 | Max parallel renders |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
scope render matrix Button --axes 'variant:primary,secondary size:sm,md,lg'
scope render matrix Button --axes 'variant:primary,secondary' --format html > matrix.html
scope render matrix Button --axes 'variant:primary,secondary size:sm,md' --format csvCSV output:
component,variant,size,renderTimeMs,width,height
Button,primary,sm,145,100,36
Button,primary,md,148,120,48
Button,secondary,sm,142,100,36scope render all
Render all components in the manifest.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --concurrency <n> | number | 4 | Max parallel renders |
| --output-dir <dir> | string | .reactscope/renders | Output directory |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
| --format <fmt> | json\|png | png | Output format |
scope render all
scope render all --concurrency 8 --output-dir ./screenshotsProgress output (stderr):
Rendering 128 components (concurrency: 4)…
Rendering 128/128 Button [===================> ] 95%Files written per component:
| Path | Description |
|------|-------------|
| .reactscope/renders/<component>.png | Screenshot |
| .reactscope/renders/<component>.json | Structured render data |
| .reactscope/renders/<component>.error.json | Error details (if failed) |
scope tokens
Manage and validate design tokens from reactscope.tokens.json.
Token file resolution order:
--fileflagtokens.fileinreactscope.config.jsonreactscope.tokens.json(default)
scope tokens get <path>
Resolve a token path to its computed value.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --file <path> | string | — | Override token file path |
| --format <fmt> | json\|text | auto | Output format |
scope tokens get color.semantic.success
# Output: #22C55E
scope tokens get color.semantic.success --format jsonJSON output:
{
"path": "color.semantic.success",
"value": "{color.green.500}",
"resolvedValue": "#22C55E",
"type": "color"
}scope tokens list [category]
List tokens, optionally filtered by category or type.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --type <type> | string | — | Filter by token type (color, dimension, fontFamily, etc.) |
| --file <path> | string | — | Override token file path |
| --format <fmt> | json\|table | auto | Output format |
scope tokens list
scope tokens list color
scope tokens list --type color --format jsonTable output:
PATH VALUE RESOLVED TYPE
color.primary {color.blue.500} #3B82F6 color
color.semantic.success {color.green.500} #22C55E color
spacing.xs 0.25rem 0.25rem dimensionscope tokens search <value>
Find which tokens match a computed value. Supports fuzzy color matching.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --type <type> | string | — | Restrict search to a token type |
| --fuzzy | boolean | false | Return nearest match even if no exact match |
| --file <path> | string | — | Override token file path |
| --format <fmt> | json\|table | auto | Output format |
scope tokens search "#22C55E"
scope tokens search "#22C55E" --fuzzy
scope tokens search "0.25rem" --type dimensionscope tokens resolve <path>
Show the full resolution chain for a token (useful for debugging alias chains).
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --file <path> | string | — | Override token file path |
| --format <fmt> | json\|text | auto | Output format |
scope tokens resolve color.semantic.successText output:
color.semantic.success → {color.green.500}
{color.green.500} → #22C55Escope tokens validate
Validate the token file for errors (circular references, missing references, type mismatches).
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --file <path> | string | — | Override token file path |
| --format <fmt> | json\|text | auto | Output format |
scope tokens validate
scope tokens validate --file custom-tokens.jsonSuccess output:
✓ Token file is valid: reactscope.tokens.jsonError output:
✗ Token file has 2 error(s): reactscope.tokens.json
CIRCULAR_REFERENCE [color.a]: Token references itself via chain
MISSING_REFERENCE [color.b]: Referenced token "color.missing" not foundscope tokens compliance
Check token compliance scores — how many computed CSS values in rendered components map back to design tokens.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --file <path> | string | — | Override token file path |
| --format <fmt> | json\|table | auto | Output format |
| --threshold <n> | number | 0.90 | Fail if compliance is below this value (0–1) |
scope tokens impact
Analyze the impact of token changes — which components will be affected if a token value changes.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --token <path> | string | — | Token path to analyze impact for |
| --file <path> | string | — | Override token file path |
| --format <fmt> | json\|table | auto | Output format |
scope tokens preview
Preview the visual effect of token changes before committing them.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --set <path=value> | string | — | Token override, e.g. color.primary=#FF0000 |
| --file <path> | string | — | Override token file path |
| --format <fmt> | json\|html | auto | Output format |
scope tokens export
Export tokens in various formats for consumption by other tools.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --format <fmt> | css\|tailwind\|json\|scss | css | Export format |
| --file <path> | string | — | Override token file path |
| -o, --output <path> | string | stdout | Write to file |
scope tokens export --format css -o tokens.css
scope tokens export --format tailwind -o tailwind-tokens.jsscope instrument
Structured runtime instrumentation for analyzing React component behavior during interactions.
scope instrument renders <component>
Trace re-render causality chains during an interaction sequence.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --interaction <json> | string | [] | Interaction sequence JSON |
| --json | boolean | false | Force JSON output |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
Interaction steps are JSON arrays with action, target, and optional fields:
scope instrument renders SearchPage \
--interaction '[{"action":"click","target":"button"},{"action":"type","target":"input","text":"hello"}]'Supported actions: click, type, wait, hover, blur, focus, scroll
JSON output:
{
"component": "SearchPage",
"interaction": [{"action": "click", "target": "button"}],
"summary": {
"totalRenders": 12,
"uniqueComponents": 5,
"wastedRenders": 2,
"interactionDurationMs": 450
},
"renders": [
{
"component": "SearchPage",
"renderIndex": 0,
"trigger": "state_change",
"propsChanged": false,
"stateChanged": true,
"contextChanged": false,
"memoized": false,
"wasted": false,
"chain": [{"component": "SearchPage", "trigger": "state_change"}],
"cascade": {
"totalRendersTriggered": 8,
"uniqueComponents": 3,
"unchangedPropRenders": 2
}
}
],
"flags": [
{
"id": "RENDER_CASCADE",
"severity": "warning",
"component": "SearchPage",
"detail": "State change in SearchPage triggered 8 downstream re-renders"
}
]
}Heuristic flags: WASTED_RENDER, RENDER_CASCADE
scope instrument hooks <component>
Profile per-hook-instance data for a component.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --props <json> | string | {} | Inline props JSON |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
| --format <fmt> | json\|text | json | Output format |
| --show-flags | boolean | false | Show heuristic flags only |
scope instrument hooks Button
scope instrument hooks Button --props '{"variant":"primary"}' --show-flagsJSON output:
{
"component": "Button",
"components": [
{
"name": "Button",
"source": {"file": "src/Button.tsx", "line": 42},
"hooks": [
{
"index": 0,
"type": "useState",
"currentValue": true,
"updateCount": 0
},
{
"index": 1,
"type": "useCallback",
"dependencyValues": ["variant"],
"recomputeCount": 0,
"cacheHitRate": 0
}
],
"flags": ["MEMO_INEFFECTIVE"]
}
],
"flags": ["MEMO_INEFFECTIVE"]
}Heuristic flags: WASTED_RENDER, MEMO_INEFFECTIVE, EFFECT_EVERY_RENDER, MISSING_CLEANUP, STALE_CLOSURE, STATE_UPDATE_LOOP
scope instrument profile <component>
Capture a full interaction-scoped performance profile (JS timing, layout, paint, layout shifts).
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --interaction <json> | string | [] | Interaction steps |
| --props <json> | string | {} | Inline props JSON |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
| --format <fmt> | json\|text | json | Output format |
| --show-flags | boolean | false | Show heuristic flags only |
scope instrument profile Button
scope instrument profile SearchPage \
--interaction '[{"action":"type","target":"input","text":"hello"}]'JSON output:
{
"component": "Button",
"totalRenders": 5,
"uniqueComponents": 3,
"wastedRenders": 1,
"timing": {
"js": 45,
"layout": 12,
"paint": 8
},
"layoutShifts": {
"count": 0,
"cumulativeScore": 0
},
"flags": [],
"interaction": []
}Heuristic flags: WASTED_RENDER, MEMO_INEFFECTIVE, EFFECT_EVERY_RENDER, MISSING_CLEANUP, HIGH_RENDER_COUNT, LAYOUT_SHIFT_DETECTED, SLOW_INTERACTION
scope instrument tree <component>
Output a structured instrumentation tree of a rendered component, annotated with render counts, timing, and context usage.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --sort-by <field> | renderCount\|depth | depth | Sort nodes by field |
| --limit <n> | number | — | Limit to first N nodes (depth-first) |
| --uses-context <name> | string | — | Filter to components using a specific context |
| --provider-depth | boolean | false | Annotate with context-provider nesting depth |
| --wasted-renders | boolean | false | Filter to components with wasted renders |
| --format <fmt> | json\|tree | auto (TTY→tree, pipe→json) | Output format |
| --manifest <path> | string | .reactscope/manifest.json | Path to manifest |
scope instrument tree SearchPage
scope instrument tree SearchPage --sort-by renderCount --limit 20
scope instrument tree SearchPage --wasted-renders
scope instrument tree SearchPage --format json | jq '.children[]'TTY (tree) output:
SearchPage
├── div
│ ├── SearchInput [renders:1 45.32ms]
│ │ ├── input [renders:1]
│ │ └── ClearButton [memo] [renders:1]
│ └── ResultsList [ctx:ListContext] [renders:2 12.01ms]
│ └── ResultItem [consumer] [renders:3]JSON output:
{
"component": "SearchPage",
"type": "function",
"renderCount": 1,
"lastRenderDuration": 45.32,
"memoized": false,
"memoSkipped": 0,
"props": {"query": ""},
"propsChanged": false,
"state": {"searchTerm": ""},
"stateChanged": false,
"contexts": [],
"contextChanged": false,
"depth": 0,
"children": []
}scope report baseline / diff / pr-comment
Sub-commands for capturing and comparing baseline snapshots (visual regression workflow).
scope report baseline
Capture a complete baseline snapshot (manifest + renders + compliance data).
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| -o, --output <dir> | string | .reactscope/baseline | Output directory |
| --components <glob> | string | — | Only baseline matching components |
| --manifest <path> | string | — | Use an existing manifest instead of regenerating |
| --viewport <WxH> | string | 375x812 | Viewport size |
scope report baseline
scope report baseline -o ./baselines/main
scope report baseline --components "Button,TextField"Files written:
.reactscope/baseline/
├── manifest.json # Full component manifest
├── compliance.json # Token compliance batch report
└── renders/
├── Button.json # Structured render output
├── Button.png # Screenshot
├── Button.error.json # Error details (if failed)
└── ...scope report diff
Compare current renders against a baseline snapshot and report regressions.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| -b, --baseline <dir> | string | .reactscope/baseline | Baseline directory |
| --threshold <px> | number | 10 | Pixel dimension threshold for regression |
| --format <fmt> | json\|text\|html | auto | Output format |
scope report diff
scope report diff --baseline ./baselines/main --threshold 5
scope report diff --format html > regression-report.htmlText output:
Visual Regression Report
========================
Regressions detected: 3
Button
Expected: 120×48px
Actual: 125×50px
Δ: +5px width, +2px height
SearchPage
Expected: 800×600px
Actual: 805×595px
Δ: +5px width, -5px heightscope report pr-comment
Generate a Markdown-formatted GitHub PR comment with regression findings.
scope report pr-comment
scope report pr-comment --baseline ./baselines/main | gh pr comment --body-file -Output: Markdown suitable for posting as a GitHub PR comment.
scope ci
Run a complete non-interactive CI pipeline: manifest generation → rendering → compliance checks → visual regression comparison.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| -b, --baseline <dir> | string | — | Baseline directory for regression comparison |
| --checks <list> | string | all | Comma-separated checks: compliance,a11y,console-errors,visual-regression |
| --threshold <n> | number | 0.90 | Compliance pass threshold (0–1) |
| --viewport <WxH> | string | 375x812 | Viewport size |
| --json | boolean | false | Emit structured JSON to stdout |
| -o, --output <path> | string | — | Write CI result JSON to file |
scope ci
scope ci --baseline .reactscope/baseline --threshold 0.95
scope ci --checks compliance,a11y --json
scope ci --json -o ci-result.jsonTTY output:
Scope CI Report
================================================
Components: 128 total 124 rendered 4 failed
[pass] Compliance 94.2% >= threshold 90.0%
[FAIL] Visual regression detected in 2 component(s): Button, TextField
[pass] No console errors detected
[FAIL] 4 component(s) failed to render
================================================
CI failed in 23.4s (exit code 4)JSON output (--json):
{
"ranAt": "2026-03-11T15:30:45.123Z",
"passed": false,
"exitCode": 4,
"checks": [
{
"check": "compliance",
"passed": true,
"message": "Compliance 94.2% >= threshold 90.0%",
"value": 0.942,
"threshold": 0.9
},
{
"check": "visual-regression",
"passed": false,
"message": "Visual regression detected in 2 component(s): Button, TextField"
}
],
"components": {
"total": 128,
"rendered": 124,
"failed": 4
},
"complianceScore": 0.942,
"complianceThreshold": 0.9,
"baselineCompared": true,
"wallClockMs": 23456
}Exit codes:
| Code | Meaning |
|------|---------|
| 0 | All checks passed |
| 1 | Compliance below threshold |
| 2 | Accessibility violations found |
| 3 | Console errors during render |
| 4 | Visual regression detected |
| 5 | Component render failures |
Pipeline steps:
- Generate manifest (scan for components)
- Render all components (4 parallel by default)
- Run token-compliance checks
- Compare against baseline (if
--baselineprovided) - Exit with appropriate code
scope site
Build and serve a static HTML component gallery from .reactscope/ output.
scope site build
Build the static HTML gallery site.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| -i, --input <path> | string | .reactscope | Path to .reactscope input directory |
| -o, --output <path> | string | .reactscope/site | Output directory |
| --base-path <path> | string | / | Base URL path prefix for subdirectory deployment |
| --compliance <path> | string | — | Path to compliance batch report JSON |
| --title <text> | string | Scope — Component Gallery | Site title |
scope site build
scope site build -o ./docs/components
scope site build --base-path /docs/ --title "Acme Component Library"
scope site build --compliance .reactscope/compliance.jsonFiles written:
.reactscope/site/
├── index.html # Gallery homepage with component grid + search
├── dashboard.html # Analytics dashboard
├── button.html # Per-component detail pages (slugified name)
├── search-page.html
└── ...scope site serve
Serve the built site locally for preview.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| -p, --port <number> | number | 3000 | Port to listen on |
| -d, --dir <path> | string | .reactscope/site | Directory to serve |
scope site serve
scope site serve --port 8080
scope site serve --dir ./docs/components --port 8080Output:
Scope site running at http://localhost:3000
Serving /home/user/project/.reactscope/site
Press Ctrl+C to stop.Configuration
reactscope.config.json
Full configuration schema:
{
"components": {
"include": ["src/**/*.tsx"],
"exclude": ["**/*.test.tsx", "**/*.stories.tsx"],
"wrappers": {
"providers": [],
"globalCSS": []
}
},
"render": {
"viewport": {
"default": { "width": 375, "height": 812 }
},
"theme": "light",
"warmBrowser": false
},
"tokens": {
"file": "reactscope.tokens.json",
"compliance": {
"threshold": 0.9
}
},
"output": {
"dir": ".reactscope/",
"sprites": {
"format": "png",
"cellPadding": 8,
"labelAxes": true
},
"json": {
"pretty": false
}
},
"ci": {
"complianceThreshold": 0.9,
"failOnA11yViolations": true,
"failOnConsoleErrors": false,
"baselinePath": ".reactscope/baseline"
}
}reactscope.tokens.json
Design token file format:
{
"$schema": "https://raw.githubusercontent.com/FlatFilers/Scope/main/packages/tokens/schema.json",
"tokens": {
"color": {
"primary": { "value": "#3B82F6", "$type": "color" },
"semantic": {
"success": { "value": "{color.green.500}", "$type": "color" }
}
},
"spacing": {
"xs": { "value": "0.25rem", "$type": "dimension" }
}
}
}Tokens can reference other tokens using {path.to.token} syntax.
Architecture
The CLI is built with 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.
Directory structure
src/
├── cli.ts # Entry point — creates and runs the program
├── program.ts # Builds the Commander command tree
├── browser.ts # Playwright-based browser capture
├── component-bundler.ts # esbuild IIFE bundling of components
├── manifest-commands.ts # manifest list/get/query/generate
├── manifest-formatter.ts # Table/JSON formatting for manifest output
├── render-commands.ts # render component/matrix/all
├── render-formatter.ts # Table/JSON/HTML/CSV formatting for render output
├── report-formatter.ts # Report summary formatting
├── tree-formatter.ts # ASCII tree formatting
├── site-commands.ts # site build/serve
├── tailwind-css.ts # Tailwind v4 CSS compilation
├── init/
│ ├── index.ts # scope init — project scaffolding
│ └── detect.ts # Framework/config auto-detection
├── tokens/
│ └── commands.ts # tokens get/list/search/resolve/validate/...
├── instrument/
│ ├── renders.ts # scope instrument renders
│ ├── hooks.ts # scope instrument hooks
│ ├── profile.ts # scope instrument profile
│ └── tree.ts # scope instrument tree
├── report/
│ ├── baseline.ts # scope report baseline
│ ├── diff.ts # scope report diff
│ └── pr-comment.ts # scope report pr-comment
└── ci/
└── commands.ts # scope ci pipelineKey patterns
- TTY detection — All formatters check
process.stdout.isTTYto switch between human-readable (table/tree) and machine-readable (JSON) output. - Lazy singletons —
BrowserPoolis created on demand and reused within a single command invocation. - Error wrapping —
safeRender()wraps individual component renders so one failure does not abort batch operations. - Concurrent execution — Render commands use configurable worker pools (
--concurrency) for parallel rendering. - Configuration resolution — Manifest and token file paths are resolved through a fallback chain: CLI flag → config file → default path.
- Dual export — The package exposes both ESM and CommonJS builds; the
scopebinary points to the CJS entrypoint for maximum compatibility.
