Skip to main content

CLI Reference

Complete reference for uiMatch CLI commands and options.

Commands Overview

uiMatch provides the following commands:

  • compare - Compare a single Figma design with implementation
  • suite - Run multiple comparisons from a JSON suite file
  • text-diff - Compare two text strings and show similarity score
  • doctor - Diagnose installation and configuration issues

compare Command

Compare a Figma design with your implementation.

Basic Syntax

Note: This assumes @uimatch/cli is already installed (globally or as a dev dependency).

npx uimatch compare \
figma=<FIGMA_REFERENCE> \
story=<URL> \
selector=<CSS_SELECTOR> \
[options]

Run Once Without Installing

If you want to try uiMatch without adding it to your project:

npx -p @uimatch/cli uimatch compare \
figma=<FIGMA_REFERENCE> \
story=<URL> \
selector=<CSS_SELECTOR> \
[options]

This explicitly tells npx which package to install (@uimatch/cli) and which binary to run (uimatch).

Required Parameters

ParameterDescriptionExample
figmaFigma file and node referenceFILE_KEY:NODE_ID or full URL
storyURL to comparehttp://localhost:3000
selectorCSS selector for target element#my-component

Common Options

Output Control

outDir=<path>            # Output directory (files not saved by default)

Size Handling

size=strict              # Sizes must match exactly (default)
size=pad # Pad smaller image with letterboxing
size=crop # Compare common area only
size=scale # Scale implementation to Figma size

Quality Gates

profile=component/strict # Pixel-perfect (pixelDiffRatio: 0.01, deltaE: 3.0)
profile=component/dev # Development (pixelDiffRatio: 0.08, deltaE: 5.0)
profile=page-vs-component # Padded comparison (pixelDiffRatio: 0.12)
profile=lenient # Prototyping (pixelDiffRatio: 0.15, deltaE: 8.0)

See Quality Gate Profiles for detailed threshold settings.

Browser Options

viewport=<WxH>           # Custom viewport size (e.g., "1920x1080")

Use environment variable UIMATCH_HEADLESS=false to show browser window during execution.

Text Matching (Experimental)

Enable text content comparison alongside pixel-based comparison to detect copy differences, typos, and missing text.

text=true                          # Enable text matching (default: false)
textMode=self|descendants # Text collection scope (default: self)
# self: Element's own text only
# descendants: Include child elements
textNormalize=none|nfkc|nfkc_ws # Normalization mode (default: nfkc_ws)
# none: No normalization
# nfkc: Unicode NFKC normalization
# nfkc_ws: NFKC + whitespace collapsing
textCase=sensitive|insensitive # Case sensitivity (default: insensitive)
textMatch=exact|contains|ratio # Matching mode (default: ratio)
# exact: Exact match required
# contains: Substring matching
# ratio: Similarity scoring
textMinRatio=0..1 # Minimum similarity threshold (default: 0.98)
# Only applies when textMatch=ratio

Note: Text matching results appear in the textMatch section of report.json when outDir is specified.

See Text Matching for detailed information on normalization, similarity scoring, and use cases.

Examples

Basic Comparison

npx uimatch compare \
figma=abc123:1-2 \
story=http://localhost:3000 \
selector="#button"

With Strict Quality Profile

npx uimatch compare \
figma=https://figma.com/file/abc123?node-id=1-2 \
story=http://localhost:6006/?path=/story/button--primary \
selector=".storybook-button" \
profile=component/strict

Mobile Viewport

npx uimatch compare \
figma=abc123:1-2 \
story=http://localhost:3000 \
selector="#mobile-nav" \
viewport=375x667

With Text Matching

Compare both visual appearance and text content to detect typos and copy differences:

npx uimatch compare \
figma=abc123:1-2 \
story=http://localhost:6006/?path=/story/accordion--default \
selector="[data-testid='accordion']" \
text=true \
textMode=descendants \
textMinRatio=0.95 \
outDir=./comparison-results

Results include a textMatch section in report.json:

{
"textMatch": {
"enabled": true,
"ratio": 0.42,
"equal": false,
"details": {
"missing": ["accordion", "vertically", "stacked"],
"extra": ["is", "it", "accessible"]
}
}
}

suite Command

Run multiple comparisons from a JSON configuration file.

Basic Syntax

npx uimatch suite path=<suite-file.json> [options]

Suite File Format

{
"name": "Component Library Tests",
"defaults": {
"profile": "component/dev"
},
"items": [
{
"name": "Button Primary",
"figma": "abc123:1-2",
"story": "http://localhost:3000/components/button",
"selector": "#button-primary"
},
{
"name": "Navigation Header",
"figma": "abc123:3-4",
"story": "http://localhost:3000/",
"selector": "header.nav"
}
]
}

Options

path=<suite.json>        # Path to suite file
outDir=<path> # Output directory (default: .uimatch-suite)
concurrency=<number> # Run comparisons in parallel (default: 4)

Example

npx uimatch suite path=tests/visual-regression.json concurrency=3

text-diff Command

Compare two text strings and show similarity score with classification.

Basic Syntax

npx uimatch text-diff <expected> <actual> [options]

Positional Arguments

ArgumentDescriptionExample
expectedThe expected text (e.g., from Figma design)"Sign in"
actualThe actual text (e.g., from implementation)"SIGN IN"

Options

--case-sensitive         # Perform case-sensitive comparison (default: case-insensitive)
--threshold=<number> # Similarity threshold (0-1, default: 0.9)

Note: Options must use = syntax (e.g., --threshold=0.8). Space-separated format (--threshold 0.8) is not supported.

Output Format

Returns a JSON object with the following fields:

{
kind: 'exact-match' | 'whitespace-or-case-only' | 'normalized-match' | 'mismatch',
similarity: number, // 0-1 range
expected: string, // Original expected text
actual: string, // Original actual text
normalizedExpected: string, // Normalized expected text
normalizedActual: string, // Normalized actual text
equalRaw: boolean, // True if raw texts are identical
equalNormalized: boolean // True if normalized texts are identical
}

Classification Types

KindDescriptionExample
exact-matchTexts are identical without any modification"Login" vs "Login"
whitespace-or-case-onlyTexts differ only in whitespace, case, or NFKC normalization"Sign in" vs "SIGN IN"
normalized-matchTexts are similar after normalization (above threshold)"Submit" vs "Submitt" (0.92)
mismatchTexts are fundamentally different (below threshold)"Login" vs "Sign in" (0.45)

Text Normalization

The comparison applies the following normalization steps:

  1. NFKC Unicode normalization - Converts full-width characters to half-width
  2. Whitespace collapsing - Collapses consecutive whitespace into single space
  3. Trim - Removes leading/trailing whitespace
  4. Case normalization - Converts to lowercase (unless --case-sensitive is used)

Examples

Basic Comparison

npx uimatch text-diff "Sign in" "SIGN  IN"

Output:

{
"kind": "whitespace-or-case-only",
"similarity": 1.0,
"equalRaw": false,
"equalNormalized": true
}

Case-Sensitive Comparison

npx uimatch text-diff "Submit" "submit" --case-sensitive

Output:

{
"kind": "whitespace-or-case-only",
"similarity": 1.0,
"equalRaw": false,
"equalNormalized": false
}

With Custom Threshold

npx uimatch text-diff "Hello World" "Helo World" --threshold=0.6

Output:

{
"kind": "normalized-match",
"similarity": 0.91,
"equalRaw": false,
"equalNormalized": false
}

Full-Width Character Handling

npx uimatch text-diff "Button123" "Button123"

Output:

{
"kind": "whitespace-or-case-only",
"similarity": 1.0,
"equalRaw": false,
"equalNormalized": true
}

Use Cases

  • Text label validation - Compare Figma text labels with implementation
  • Localization testing - Verify translated text maintains similarity
  • Typography debugging - Identify subtle text differences (case, whitespace, unicode)
  • Component testing - Validate text content in UI components

Programmatic Usage

For programmatic use, import compareText from @uimatch/core:

import { compareText } from '@uimatch/core';

const result = compareText('Expected', 'Actual', {
caseSensitive: false,
similarityThreshold: 0.9,
});

console.log(result.kind); // 'exact-match' | 'whitespace-or-case-only' | ...
console.log(result.similarity); // 0.0 - 1.0

See API Reference for details.

Environment Variables

Set these in .env or your environment:

FIGMA_ACCESS_TOKEN=your_token_here       # Required for Figma API access
UIMATCH_LOG_LEVEL=info|debug|silent # Logging verbosity (default: info)
UIMATCH_HEADLESS=true|false # Playwright headless mode (default: true)
# Set to 'false' to show browser window
# Applies to compare/suite/doctor commands

Exit Codes

  • 0 - All comparisons passed
  • 1 - One or more comparisons failed
  • 2 - Invalid arguments or configuration error

Advanced Usage

Content Basis

Control which area to use for calculating pixel difference ratio:

contentBasis=union          # Union of both content areas (default)
contentBasis=intersection # Intersection of both areas (recommended for pad mode)
contentBasis=figma # Use Figma's content area only
contentBasis=impl # Use implementation's content area only

Best Practice: Use intersection with size=pad to exclude letterboxing from metrics.

Custom Anchor Plugins

Use custom selector resolution plugins:

selectorsPlugin=@my-company/custom-anchor-plugin

See Plugins for details on creating custom plugins.

Quality Gate Profiles

uiMatch uses quality gate profiles to manage thresholds instead of individual CLI flags.

ProfileUse CasepixelDiffRatiodeltaEDescription
component/strictDesign system components0.01 (1%)3.0Pixel-perfect comparison
component/devDevelopment workflow0.08 (8%)5.0Relaxed for iteration
page-vs-componentPadded comparisons0.12 (12%)5.0Accounts for letterboxing
lenientPrototyping0.15 (15%)8.0Very relaxed thresholds
customCustom settings--Uses .uimatchrc.json

Using Profiles

# Pixel-perfect comparison
npx uimatch compare figma=... story=... selector=... profile=component/strict

# Development workflow
npx uimatch compare figma=... story=... selector=... profile=component/dev

Custom Configuration

For fine-grained control, create .uimatchrc.json:

{
"comparison": {
"acceptancePixelDiffRatio": 0.01,
"acceptanceColorDeltaE": 3.0
}
}

Tips

  1. Start with lenient profile (profile=lenient) and tighten as needed
  2. Use UIMATCH_HEADLESS=false during development to see browser window
  3. Name your comparisons for easier debugging in CI logs
  4. Group related comparisons in suite files for organization

See Also