Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
130 changes: 99 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
# Ghost

**Design drift detection and fingerprinting for design systems.**
**Autonomous perception of organic drift across decentralized design consumers.**

Ghost detects unintentional divergence between a parent design language and its consumer implementations. It scans for drift across values, structure, and visual dimensions, generates design fingerprints for comparison, and tracks how systems evolve over time.
Ghost makes design systems legible. It continuously detects divergence between a parent design language and its consumers, generates quantitative fingerprints for comparison, tracks how systems evolve over time, and ships a reference design language as a shadcn-compatible component registry.

## Why Ghost?

Design languages drift. Teams override tokens, hardcode colors, restructure components, and make visual changes that silently diverge from the source of truth. Drift can be neutral. Sometimes organic. Sometimes a mistake. Sometimes intentional. Ghost catches this drift.
Design languages drift — and drift degrades trust. When interfaces lose coherence, the experience suffers regardless of how good the underlying capabilities are. Ghost perceives this drift across an ecosystem so teams can reason about it and act with intent.

- **Multi-dimensional scanning** - Detect token overrides, hardcoded values, structural divergence, and pixel-level visual regressions
- **Design fingerprinting** - Generate a 64-dimensional numeric profile of any design system for quantitative comparison
- **Evolution tracking** - Acknowledge, adopt, or intentionally diverge from a parent system with full lineage history
- **Fleet analysis** - Compare fingerprints across an ecosystem to identify clusters and outliers
- **LLM-powered interpretation** - Optionally use Claude or OpenAI for richer fingerprint generation
- **3D visualization** - Explore fingerprint similarity space in an interactive Three.js viewer
- **Continuous scanning** — Detect token overrides, hardcoded values, structural divergence, and pixel-level visual regressions across every consumer
- **Design fingerprinting** — Generate a 64-dimensional profile of any design system — a continuous signal, not a binary check
- **Intent tracking** — Acknowledge, adopt, or intentionally diverge from a parent system. Every stance is published with reasoning and full lineage
- **Fleet observability** — Compare fingerprints across an ecosystem to see the full picture: clusters, outliers, and how consumers relate to each other and the source
- **LLM-aided interpretation** — Optionally use Claude or OpenAI for richer fingerprint generation and drift analysis
- **3D visualization** — Explore fingerprint similarity space in an interactive Three.js viewer
- **Composable design language** — A full shadcn-compatible registry of atomic components, design tokens, and a live catalogue — building blocks that interfaces compose from

## Getting Started

Expand Down Expand Up @@ -57,18 +58,25 @@ ghost compare system-a.json system-b.json
ghost viz system-a.json system-b.json system-c.json
```

**Run the ghost-ui catalogue:**

```bash
just dev
# or: cd packages/ghost-ui && pnpm dev
```

## CLI Commands

| Command | Description |
| --------------- | ---------------------------------------------------------------------------- |
| `ghost scan` | Detect design drift against a registry |
| `ghost profile` | Generate a design fingerprint from a registry, codebase, or via LLM |
| `ghost compare` | Compare two fingerprints with optional temporal analysis |
| `ghost ack` | Acknowledge current drift and record a stance (aligned, accepted, diverging) |
| `ghost adopt` | Shift parent baseline to a new fingerprint |
| `ghost diverge` | Mark a fingerprint dimension as intentionally diverging |
| `ghost fleet` | Compare N fingerprints across an ecosystem |
| `ghost viz` | Launch interactive 3D fingerprint visualization |
| `ghost scan` | Detect design drift against a registry |
| `ghost profile` | Generate a design fingerprint from a registry, codebase, or via LLM |
| `ghost compare` | Compare two fingerprints with optional temporal analysis |
| `ghost ack` | Acknowledge current drift and publish a stance (aligned, accepted, diverging) |
| `ghost adopt` | Shift parent baseline to a new fingerprint |
| `ghost diverge` | Mark a fingerprint dimension as intentionally diverging with reasoning |
| `ghost fleet` | Compare N fingerprints for ecosystem-wide observability |
| `ghost viz` | Launch interactive 3D fingerprint visualization |

## Configuration

Expand Down Expand Up @@ -104,17 +112,17 @@ export default defineConfig({

## How It Works

### Drift Scanning
### Scanning

Ghost scans at three levels:
Ghost perceives drift at three levels:

1. **Values** - Detects hardcoded colors, token overrides, and missing tokens by comparing your styles against the registry
2. **Structure** - Diffs component files between your implementation and the registry source
3. **Visual** - Renders components with Playwright and performs pixel-level comparison using pixelmatch
1. **Values** Detects hardcoded colors, token overrides, and missing tokens by comparing styles against the registry
2. **Structure** Diffs component files between a consumer implementation and the registry source
3. **Visual** Renders components with Playwright and performs pixel-level comparison using pixelmatch

### Design Fingerprinting
### Fingerprinting

A fingerprint is a 64-dimensional vector capturing a system's design characteristics:
A fingerprint is a 64-dimensional vector — a continuous representation of a system's design characteristics:

| Dimensions | Category | What it captures |
| ---------- | ------------ | -------------------------------------------------------------- |
Expand All @@ -126,17 +134,58 @@ A fingerprint is a 64-dimensional vector capturing a system's design characteris

Fingerprints can be generated deterministically from extracted material, from a shadcn-compatible registry, or with LLM assistance for richer interpretation.

### Evolution Tracking
### Intent Tracking

Ghost tracks design lineage and published intent through:

- **`.ghost-sync.json`** — Per-dimension stances toward the parent: aligned, accepted, or diverging — each with recorded reasoning
- **`.ghost/history.jsonl`** — Append-only fingerprint history for temporal analysis
- **Temporal comparison** — Velocity and trajectory classification to understand where a system is heading, not just where it is

### Fleet Observability

Ghost tracks design lineage through:
Compare fingerprints across multiple systems to make an ecosystem legible. Ghost calculates pairwise distances, identifies a centroid, and clusters systems by similarity — surfacing which consumers are coherent, which are drifting, and where gaps exist.

- **`.ghost-sync.json`** - A manifest recording per-dimension stances toward the parent (aligned, accepted, diverging)
- **`.ghost/history.jsonl`** - Append-only fingerprint history for temporal analysis
- **Temporal comparison** - Velocity and trajectory classification to understand drift trends
## Ghost UI

### Fleet Analysis
Ghost UI (`@ghost/ui`) is the project's reference design language — atomic, composable interface primitives published as a shadcn-compatible registry. It serves as both a living design system and the concrete baseline Ghost scans consumers against.

### What's included

- **49 primitive components** — Foundational building blocks (accordion, button, card, dialog, form, table, tabs, etc.) built on Radix UI and styled with Tailwind CSS
- **48 AI-native elements** — Components for conversational and agentic interfaces: prompt input, message, code block, chain of thought, file tree, terminal, tool, and more — the pieces intelligent interfaces compose from
- **Design tokens** — A full token system (colors, spacing, typography, radii, shadows) defined as CSS custom properties with light and dark mode support
- **Theme system** — Runtime theme switching with presets, a live theme panel for editing tokens, and CSS variable export
- **HK Grotesk typeface** — Self-hosted display font (300–900 weights) paired with system sans-serif for body text
- **Live catalogue** — An interactive documentation site (React + Vite) with component demos, foundations pages, and a bento showcase

### Registry

Ghost UI publishes a `registry.json` conforming to the [shadcn registry schema](https://ui.shadcn.com/docs/registry). Consumers can install individual components directly:

```bash
npx shadcn@latest add --registry https://your-ghost-ui-host/registry.json button card dialog
```

Compare fingerprints across multiple systems to get an ecosystem-wide view. Ghost calculates pairwise distances, identifies a centroid, and optionally clusters systems by similarity.
Ghost itself can profile the registry to generate a fingerprint, then scan downstream consumers against it to detect drift:

```bash
ghost profile --registry ./packages/ghost-ui/registry.json
ghost scan --config ghost.config.ts
```

### Catalogue development

```bash
# dev server with hot reload
just dev

# production build
just build-ui

# rebuild the shadcn registry
just build-registry
```

## Project Structure

Expand All @@ -154,6 +203,20 @@ packages/
ghost-cli/ CLI interface
src/
viz/ 3D visualization (Three.js, PCA projection)
ghost-ui/ Reference design language (@ghost/ui)
src/
components/
ui/ Primitive components (Radix + Tailwind)
ai-elements/ AI-native components (chat, code, agents)
theme/ ThemeProvider and theme toggle
theme-panel/ Live token editor panel
docs/ Catalogue pages, demos, and bento showcase
contexts/ Theme and theme-panel context providers
hooks/ Shared React hooks
lib/ Utilities, registry helpers, theme presets
styles/ Design tokens and global CSS
fonts/ HK Grotesk woff2 files
registry.json shadcn-compatible component registry
```

## Development
Expand All @@ -170,8 +233,13 @@ pnpm test

# lint and format
pnpm check

# run ghost-ui dev server
just dev
```

A `justfile` is included for common workflows — run `just` to see all available recipes.

## Project Resources

| Resource | Description |
Expand Down
16 changes: 15 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,23 @@
}
}
},
"css": {
"parser": {
"cssModules": false,
"tailwindDirectives": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
}
},
"overrides": [
{
"includes": ["packages/ghost-ui/**"],
"linter": {
"enabled": false
}
}
]
}
14 changes: 14 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ test:
test-watch:
pnpm test:watch

# ── Run ──────────────────────────────────────────────────────

# Run ghost-ui catalogue dev server
dev:
cd packages/ghost-ui && pnpm dev

# Build ghost-ui catalogue (static export)
build-ui:
cd packages/ghost-ui && pnpm build

# Build ghost-ui shadcn registry
build-registry:
cd packages/ghost-ui && pnpm build:registry

# ── Utilities ────────────────────────────────────────────────

# Clean build artifacts
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"test": "vitest run",
"test:watch": "vitest",
"typecheck": "tsc --build",
"build:ui": "pnpm --filter @ghost/ui build",
"check": "biome check . && pnpm typecheck && pnpm check:file-sizes",
"check:file-sizes": "node scripts/check-file-sizes.mjs",
"fmt": "biome format --write .",
Expand Down
52 changes: 52 additions & 0 deletions packages/ghost-cli/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import type { DesignFingerprint } from "@ghost/core";
import {
compareFingerprints,
computeTemporalComparison,
diff,
formatCLIReport,
formatComparison,
formatComparisonJSON,
formatDiffCLI,
formatDiffJSON,
formatFingerprint,
formatFingerprintJSON,
formatJSONReport,
Expand Down Expand Up @@ -239,6 +242,54 @@ const compareCommand = defineCommand({
},
});

const diffCommand = defineCommand({
meta: {
name: "diff",
description:
"Compare local components against registry with drift analysis",
},
args: {
component: {
type: "positional",
description: "Component name (optional, all if omitted)",
required: false,
},
config: {
type: "string",
description: "Path to ghost config file",
alias: "c",
},
format: {
type: "string",
description: "Output format: cli or json",
default: "cli",
},
},
async run({ args }) {
try {
const config = await loadConfig(args.config);
const results = await diff(config, args.component || undefined);

const output =
args.format === "json"
? formatDiffJSON(results)
: formatDiffCLI(results);

process.stdout.write(output);

const hasBreaking = results.some((r) =>
r.components.some((c) => c.severity === "error"),
);
process.exit(hasBreaking ? 1 : 0);
} catch (err) {
console.error(
`Error: ${err instanceof Error ? err.message : String(err)}`,
);
process.exit(2);
}
},
});

const main = defineCommand({
meta: {
name: "ghost",
Expand All @@ -249,6 +300,7 @@ const main = defineCommand({
scan: scanCommand,
profile: profileCommand,
compare: compareCommand,
diff: diffCommand,
fleet: fleetCommand,
ack: ackCommand,
adopt: adoptCommand,
Expand Down
Loading
Loading