CLI Reference

June 11, 2026 · View on GitHub

The af CLI is a thin control surface for the Aesthetic Function system. It delegates all work to existing watcher and server modules — it does not own reconciliation logic.

Installation

The CLI is available after installing the monorepo:

pnpm install

Commands are run from the repository root.

Global Flags

FlagDescription
--help, -hShow help message
--versionShow version

af init

Generate an af.config.json configuration file.

af init [options]
FlagTypeDefaultDescription
--profile <name>stringdesigner-firstPolicy profile (designer-first, code-first, balanced, strict-review)
--force, -fbooleanfalseOverwrite existing af.config.json
--jsonbooleanfalseOutput generated config as JSON (no file write)

Behavior:

  • Detects project context (framework, existing artifacts like component-map.json, design-overrides.json)
  • Generates minimal valid config with framework-specific defaults
  • Interactive prompts if running in a TTY; non-interactive defaults to designer-first
  • Only writes af.config.json — does not start any processes

Examples:

# Generate default config
af init

# Generate with balanced profile, overwriting existing
af init --profile balanced --force

# Preview config without writing
af init --json

af run

Start the watcher and server as child processes.

af run [options]
FlagTypeDefaultDescription
--server-onlybooleanfalseStart server only
--watcher-onlybooleanfalseStart watcher only
--verbose, -vbooleanfalseVerbose output

Behavior:

  • Loads af.config.json and passes config-derived environment variables to child processes
  • Spawns server (packages/server/src/index.ts) and watcher (packages/watcher/src/index.ts) as independent processes
  • Handles SIGINT/SIGTERM gracefully (kills all children)
  • Returns the maximum exit code from children

Examples:

# Start both
af run

# Start server only
af run --server-only

# Start watcher only with verbose output
af run --watcher-only --verbose

af reconcile <file>

Run the full reconciliation pipeline on a source file.

af reconcile <file> [options]
FlagTypeDefaultDescription
--profile <name>stringfrom configOverride policy profile
--repo-root <path>stringauto-detectRepository root path
--format <fmt>stringhumanOutput format (human, json, ci)
--jsonbooleanfalseShorthand for --format json
--writebooleantrueWrite artifacts to design-materializations/
--no-writebooleanSkip artifact writes
--recordbooleanfalseRecord run in the timeline ledger
--strictbooleanfalseStrict CI mode (exit 1 on FAIL verdict)
--verbose, -vbooleanfalseVerbose output
--limit <n>numberDrift window limit

Pipeline steps: Parse → Resolve → Diff → Report

Examples:

# Reconcile a component
af reconcile demos/react-demo-app/src/App.tsx

# JSON output, no file writes
af reconcile demos/react-demo-app/src/App.tsx --json --no-write

# Record in ledger with strict mode
af reconcile demos/react-demo-app/src/App.tsx --record --strict

# Override profile for this run
af reconcile demos/react-demo-app/src/App.tsx --profile code-first

af status <file>

Show reconciliation status for a source file.

af status <file> [options]
FlagTypeDefaultDescription
--repo-root <path>stringauto-detectRepository root path
--jsonbooleanfalseOutput JSON format
--writebooleanfalseWrite status artifact
--verbose, -vbooleanfalseVerbose output

Examples:

af status demos/react-demo-app/src/App.tsx
af status demos/react-demo-app/src/App.tsx --json

af dashboard <file>

Show the drift dashboard for a source file or project.

af dashboard <file-or-dir> [options]

File Mode (default)

FlagTypeDefaultDescription
--limit <n>numberRun window limit
--from <runId>stringStart from specific run
--to <runId>stringEnd at specific run
--strictbooleanfalseStrict CI mode (exit 1 on FAIL)
--jsonbooleanfalseOutput JSON format
--writebooleanfalseWrite dashboard artifact
--verbosebooleanfalseVerbose output
--repo-root <path>stringauto-detectRepository root path

Project Mode (--project)

All file mode flags, plus:

FlagTypeDefaultDescription
--projectbooleanfalseEnable project-level dashboard (aggregates all files in directory)
--fail-score <n>numberScore below which verdict is FAIL
--warn-score <n>numberScore at or above which verdict is PASS
--max-signals <n>numberMax signals to display

Examples:

# File-level dashboard
af dashboard demos/react-demo-app/src/App.tsx

# Project-level dashboard
af dashboard --project demos/react-demo-app/src/

# With score thresholds
af dashboard --project demos/react-demo-app/src/ --fail-score 40 --warn-score 70

# Last 5 runs only
af dashboard demos/react-demo-app/src/App.tsx --limit 5

af ci [dir]

Run the CI gate summary for a directory.

af ci [dir] [options]
FlagTypeDefaultDescription
--limit <n>numberScan file limit
--window <n>numberTrend window size
--improving-delta <n>numberImproving trend threshold
--worsening-delta <n>numberWorsening trend threshold
--fail-on-worseningbooleanfalseExit 1 on worsening trend
--no-fail-on-worseningbooleanDo not fail on worsening
--max-files <n>numberMaximum files to process
--strictbooleanfalseStrict CI mode
--jsonbooleanfalseOutput JSON format
--writebooleanfalseWrite CI gate artifact
--verbosebooleanfalseVerbose output
--repo-root <path>stringauto-detectRepository root path

Examples:

# Basic CI gate
af ci demos/react-demo-app/src/

# Strict mode for CI pipelines
af ci demos/react-demo-app/src/ --strict --fail-on-worsening

# JSON output with custom thresholds
af ci demos/react-demo-app/src/ --json --window 5 --worsening-delta 10

af artifacts <subcommand>

Inspect reconciliation artifacts.

af artifacts list <source-file>

List all artifacts for a source file.

af artifacts list demos/react-demo-app/src/App.tsx [options]

af artifacts inspect <artifact-path>

Inspect a specific artifact file.

af artifacts inspect design-materializations/demos__react-demo-app__src__App.figma-reconcile.json [options]

af artifacts trace <source-file>

Trace the full pipeline for a source file.

af artifacts trace demos/react-demo-app/src/App.tsx [options]

Common Flags

FlagTypeDefaultDescription
--repo-root <path>stringauto-detectRepository root path
--jsonbooleanfalseOutput JSON format
--verbose, -vbooleanfalseVerbose output

af design <subcommand>

Design adapter commands. All commands are read-only — they do not write to Figma or trigger reconciliation.

Common Flags

FlagTypeDefaultDescription
--jsonbooleanfalseOutput JSON format
--verbose, -vbooleanfalseVerbose output with trace details
--adapter <id>stringfirst availableUse a specific adapter

af design pull

Pull full design data (tokens, components, and styles).

af design pull [options]

af design tokens

Pull and normalize design tokens to canonical vocabulary.

af design tokens [options]

af design inspect <name>

Inspect a specific design component.

af design inspect ButtonPrimary [options]

# Inspect all components
af design inspect --all [options]

af design screenshot

Capture a design screenshot (PNG).

af design screenshot [options]

# Screenshot a specific node
af design screenshot --node 123:456

# Save to file
af design screenshot --out screenshot.png

af design component [name]

List or inspect design components.

# List all components
af design component

# Inspect a specific component
af design component ButtonPrimary

af design drift [name]

Cross-surface drift analysis — compares component metadata across Figma, Storybook, code (AST), and an optional dspack contract file. Read-only: it does not modify reconciliation, and the contract file is never written.

af design drift [component-name] [options]
FlagTypeDefaultDescription
--jsonbooleanfalseOutput JSON format
--verbose, -vbooleanfalseVerbose output with trace details
--include-uncorroboratedbooleanfalseInclude uncorroborated story-derived variants
--dspack <file>stringdspack contract file to compare against (overrides contract.dspackPath in af.config.json)

Contract surface: when a dspack file is supplied (flag or config), its declared components, props, and enum variants participate in the comparison. Findings where the contract declares something code lacks are genuine drift (warn). Findings where code has something the contract lacks are tagged contract-staleness: (info) — the snapshot may be out of date; regenerate it with dspack-export. Relative paths resolve against the current directory, then the repo root.

Examples:

# Compare a component across all available surfaces
af design drift Button

# Compare against a dspack contract (works even with Figma/Storybook down)
af design drift Button --dspack ./my-system.dspack.json

# Analyze every component the contract declares
af design drift --dspack ./my-system.dspack.json --json
// af.config.json
{
  "contract": {
    "dspackPath": "./my-system.dspack.json"
  }
}

pnpm Scripts

These scripts are available at the monorepo root alongside the af CLI:

CommandDescription
pnpm dev:serverStart the relay server
pnpm dev:watcherStart the file watcher
pnpm devStart all packages in parallel
pnpm buildBuild all packages
pnpm testRun all tests
pnpm typecheckRun TypeScript checks
pnpm tunnelExpose server via cloudflared
pnpm test:sendSend test operations

Direct Watcher Commands

These bypass the CLI and run watcher modules directly:

CommandDescription
pnpm --filter @aesthetic-function/watcher figma:reconcile <file>Full reconciliation (primary entry point)
pnpm --filter @aesthetic-function/watcher figma:status <file>Reconciliation status
pnpm --filter @aesthetic-function/watcher figma:dashboard <file>Drift dashboard
pnpm --filter @aesthetic-function/watcher figma:ci <dir>CI gate summary
pnpm --filter @aesthetic-function/watcher figma:sourcesDiscover sources for multi-file reconciliation
pnpm --filter @aesthetic-function/watcher figma:index <file>Index existing artifacts
pnpm --filter @aesthetic-function/watcher figma:timeline <file>Show/record timeline ledger
pnpm --filter @aesthetic-function/watcher figma:drift <file>Compute drift diffs
pnpm --filter @aesthetic-function/watcher figma:project-dashboard <dir>Project-level dashboard

Architecture Notes

  • The CLI is a thin dispatcher. It delegates all commands to existing watcher/server modules via fork() with TypeScript execution (tsx).
  • Config resolution: af.config.json → env vars → child processes. Environment variables already set by the user take precedence over config file values.
  • The CLI requires a monorepo context (must find pnpm-workspace.yaml in a parent directory).
  • All delegated modules are independently runnable via the pnpm --filter commands above.

For full architectural details, see architecture-reference.md.