npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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 --help

Requirements: 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 serve

Commands 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 config

Interactive 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 30000

Output: 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-props

Output:

Button
├── div
│   ├── span
│   └── svg
└── FocusRing

scope 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 --json

TTY 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:        45ms

scope 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      2

JSON 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 json

TTY 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 json

scope 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.png

JSON 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 csv

CSV output:

component,variant,size,renderTimeMs,width,height
Button,primary,sm,145,100,36
Button,primary,md,148,120,48
Button,secondary,sm,142,100,36

scope 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 ./screenshots

Progress 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:

  1. --file flag
  2. tokens.file in reactscope.config.json
  3. reactscope.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 json

JSON 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 json

Table 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      dimension

scope 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 dimension

scope 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.success

Text output:

color.semantic.success → {color.green.500}
  {color.green.500} → #22C55E

scope 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.json

Success output:

✓ Token file is valid: reactscope.tokens.json

Error 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 found

scope 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.js

scope 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-flags

JSON 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.html

Text 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 height

scope 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.json

TTY 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:

  1. Generate manifest (scan for components)
  2. Render all components (4 parallel by default)
  3. Run token-compliance checks
  4. Compare against baseline (if --baseline provided)
  5. 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.json

Files 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 8080

Output:

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 pipeline

Key patterns

  • TTY detection — All formatters check process.stdout.isTTY to switch between human-readable (table/tree) and machine-readable (JSON) output.
  • Lazy singletonsBrowserPool is created on demand and reused within a single command invocation.
  • Error wrappingsafeRender() 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 scope binary points to the CJS entrypoint for maximum compatibility.