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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/agent-led-framing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"ghost-drift": patch
"ghost-expression": patch
---

Reframe skill-bundle copy to lead with the agent and drift, not the deterministic CLI. Same architecture; clearer story when an agent loads the skill.
24 changes: 17 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
# Ghost — Agent Context
# Ghost

Agents can ship UI now. The problem: what they ship drifts — wrong palette, wrong density, wrong hierarchy — because they have no canonical answer to "what does this project's design language *actually* look like."

Ghost is the layer that gives them one. The design language lives in your repo as `expression.md`. Agents read it before generating, compare against it after, and either correct the drift or codify the divergence as a deliberate change. Five tools split the loop:

- **ghost-map** — where the design system lives
- **ghost-expression** — what the design language is (the canonical artifact)
- **ghost-drift** — when generated UI strays
- **ghost-fleet** — how the language propagates across many projects
- **ghost-ui** — a reference design system to test the loop against

> **Read [`INVARIANTS.md`](./INVARIANTS.md) before making non-trivial changes.** These are hard constraints — surface conflicts, don't weigh them as preferences.

Expand All @@ -23,10 +33,10 @@ pnpm --filter ghost-expression exec ghost-expression <command>

## Environment Variables

Every CLI verb across every Ghost tool is deterministic — no API key required.
No API key is required to run Ghost. The variables below are optional.

- `OPENAI_API_KEY` / `VOYAGE_API_KEY` — optional, consumed only by `computeSemanticEmbedding` (library function in `@ghost/core`; used when a host writes an `expression.md` and wants an enriched 49-dim vector for paraphrase-robust comparison).
- `GITHUB_TOKEN` — optional, used by `resolveTrackedExpression` when fetching a tracked expression from GitHub (avoids rate limits).
- `OPENAI_API_KEY` / `VOYAGE_API_KEY` — consumed only by `computeSemanticEmbedding` (library function in `@ghost/core`; used when a host writes an `expression.md` and wants an enriched 49-dim vector for paraphrase-robust comparison).
- `GITHUB_TOKEN` — used by `resolveTrackedExpression` when fetching a tracked expression from GitHub (avoids rate limits).

Each CLI auto-loads `.env` and `.env.local` from the working directory.

Expand All @@ -49,7 +59,7 @@ Run `just` to list all recipes. Key ones: `setup`, `build`, `check`, `fmt`, `tes

## Architecture

Ghost is **BYOA (bring-your-own-agent)**. Every CLI is a set of **deterministic primitives** — none of them call an LLM. Judgement work (profile, review, verify, remediate) lives in [agentskills.io](https://agentskills.io)-compatible skill bundles the host agent (Claude Code, Codex, Cursor, Goose, …) executes.
Ghost is **BYOA (bring-your-own-agent)**. The host agent — Claude Code, Codex, Cursor, Goose, whatever ships next — does the reading, deciding, and writing. The judgement work (profile, review, verify, remediate) lives in [agentskills.io](https://agentskills.io)-compatible skill bundles the agent executes. Ghost's CLIs are the calculator the agent reaches for when it needs a reproducible answer (vector math, schema validation, structural diffs); see [`INVARIANTS.md`](./INVARIANTS.md) §1 and §4 for the underlying constraints.

The repo decomposes into **five tools plus a reference design system**, each with a single responsibility:

Expand Down Expand Up @@ -90,7 +100,7 @@ Verbs are scoped to the tool that owns the artifact. The full surface across all

| Tool | Command | Description |
|------|---------|-------------|
| `ghost-map` | `inventory [path]` | Emit deterministic raw repo signals (manifests, language histogram, registry, top-level tree, git remote) as JSON. |
| `ghost-map` | `inventory [path]` | Emit raw repo signals (manifests, language histogram, registry, top-level tree, git remote) as JSON. |
| `ghost-map` | `lint [map]` | Validate `map.md` against `ghost.map/v1`. |
| `ghost-expression` | `lint [expression]` | Validate `expression.md` schema + body/frontmatter coherence. |
| `ghost-expression` | `describe [expression]` | Print section ranges + token estimates (so agents can selectively load). |
Expand All @@ -105,7 +115,7 @@ Verbs are scoped to the tool that owns the artifact. The full surface across all
| `ghost-fleet` | `view [dir]` | Compute pairwise distances + group-by tables; emit `fleet.md` + `fleet.json`. |
| `ghost-fleet` | `emit skill` | Install the `ghost-fleet` agentskills.io bundle. |

**Workflows the CLI does not do** — these are recipes the host agent follows. Each tool ships its own under `packages/<tool>/src/skill-bundle/references/`:
**Workflows (agent recipes).** Each tool ships its own skill-bundle references under `packages/<tool>/src/skill-bundle/references/`. These are the agent's job, not CLI verbs:

- **Profile** (write `expression.md` from a project) — `ghost-expression/.../profile.md`
- **Map** (write `map.md` from a repo) — `ghost-map/.../map.md`
Expand Down
21 changes: 9 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@

AI is becoming the primary author of shipped code. Humans sit in fewer diffs; the harness (guardrails, reviewers, verifiers) catches drift before it lands. In that world, ensuring every generation reflects a brand's voice is paramount. Fonts and spacing are the easy half. The hard half is character: the posture a product takes, what it refuses to do. That's where generations drift first.

Ghost closes that loop. It captures a brand as an **expression**: a human-readable `expression.md` encoding character, signature traits, and concrete decisions. It gives any agent the primitives to author against it, detect drift the moment it happens, and record the right stance: **acknowledge**, **track**, or **intentionally diverge**. Each repo owns its expression, its trajectory, and its stance. The fleet of expressions drifts in the open. Nothing gets enforced; nothing drifts silently. Deterministic arithmetic lives in Ghost's CLIs; judgment lives in whatever agent you already use.
Ghost closes that loop. It captures a brand as an **expression**: a human-readable `expression.md` encoding character, signature traits, and concrete decisions. It gives any agent what it needs to author against the expression, detect drift the moment it happens, and record the right stance: **acknowledge**, **track**, or **intentionally diverge**. Each repo owns its expression, its trajectory, and its stance. The fleet of expressions drifts in the open. Nothing gets enforced; nothing drifts silently. The agent does the reading, deciding, and writing; Ghost's CLIs are the calculator it reaches for.

## BYOA: bring your own agent

Ghost splits the work the way agents need it split: **judgement in the agent, arithmetic in the CLI**.
Every Ghost workflow runs in the host agent you already use — Claude Code, Codex, Cursor, Goose, whatever ships next. Each tool ships an [agentskills.io](https://agentskills.io)-compatible bundle of recipes for the interpretive work (profile, review, verify, remediate, fleet narrative); the agent loads the bundle, reads `expression.md` and `map.md`, makes the calls, and writes the artifacts. When it needs a reproducible number — vector distance between two expressions, schema validation, a structural diff — it calls the relevant Ghost CLI verb for the answer.

- **The CLIs**: a set of **deterministic primitives** distributed across five small tools. None of them ever call an LLM. They do vector distance, schema validation, manifest writes. Same answer every time.
- **The skill bundles**: [agentskills.io](https://agentskills.io)-compatible recipes for the interpretive work (profile, review, verify, remediate, fleet narrative). Each tool ships its own; the host agent (Claude Code, Codex, Cursor, Goose, …) runs the recipes and calls the relevant CLI for the arithmetic.

No API key is required to use any CLI verb. Judgment work lives in whichever agent you already use; each tool's `emit skill` verb installs the recipes there.
No API key is required to run any CLI verb. Each tool's `emit skill` verb installs its bundle into your agent.

## The five tools

Expand All @@ -37,7 +34,7 @@ Ghost gives agents four capabilities the design-at-scale problem actually needs:
- **Self-govern at author time**: the `review` and `verify` recipes (in the `ghost-drift` skill bundle) run an agent's output against the expression *before* a human sees it. Drift gets caught where it's cheap to fix, not after it ships.
- **Detect drift at the right time**: PR-time (via `review`), generation-time (via `verify`), or org-time (via `ghost-drift compare` on N≥3 expressions, or `ghost-fleet view` for the full elevation). Timing is load-bearing: the same drift surfaced a month later is noise; surfaced inline, it's action.
- **Remediate with structured intent**: `ack`, `track`, `diverge` are the three moves. Every stance is published with reasoning and full lineage. Drift without intent is noise; drift with intent becomes useful evidence.
- **Human-readable, diff-friendly**: `expression.md` is Markdown with YAML frontmatter (machine layer) plus a three-layer prose body (Character, Signature, Decisions). `map.md` is the same shape for topology. Humans read them, agents consume them, deterministic tools diff them. No DSL to learn.
- **Human-readable, diff-friendly**: `expression.md` is Markdown with YAML frontmatter (machine layer) plus a three-layer prose body (Character, Signature, Decisions). `map.md` is the same shape for topology. Humans read them, agents consume them, Ghost's CLIs diff them. No DSL to learn.

## Repo layout

Expand Down Expand Up @@ -79,7 +76,7 @@ ghost-expression emit skill # → ./.claude/skills/ghost-expression
ghost-fleet emit skill # → ./.claude/skills/ghost-fleet
```

Once a skill is installed, ask your agent in plain English ("profile this design language", "review this PR for drift", "compute the fleet view") and it'll follow the recipe, calling the relevant CLI for any deterministic step.
Once a skill is installed, ask your agent in plain English ("profile this design language", "review this PR for drift", "compute the fleet view") and it'll follow the recipe, calling the relevant CLI whenever it needs a reproducible answer.

### Quick start

Expand Down Expand Up @@ -145,7 +142,7 @@ just dev

## CLI Commands

Every verb is a deterministic primitive — pure inputs → pure outputs, no LLM in the loop. Verbs are scoped to the tool that owns the artifact.
Verbs are scoped to the tool that owns the artifact. Pure inputs → pure outputs, no API key required.

| Tool | Command | Description |
| --- | --- | --- |
Expand Down Expand Up @@ -178,7 +175,7 @@ The interpretive verbs from the pitch (*author, self-govern, detect, remediate*)
| `remediate` | `ghost-drift` | Suggest minimal fixes for drift | "fix this drift" |
| `target` | `ghost-fleet` | Synthesize fleet narrative | "describe this fleet" |

These are instructions, not code. The agent executes them using its normal tools (file search, reading, editing) plus the relevant Ghost CLI for any deterministic step. (`discover` and `generate` are intentionally not migrated — see [`docs/ideas/phase-0-decisions.md`](./docs/ideas/phase-0-decisions.md).)
These are instructions, not code. The agent executes them using its normal tools (file search, reading, editing) plus the relevant Ghost CLI when it needs a reproducible answer. (`discover` and `generate` are intentionally not migrated — see [`docs/ideas/phase-0-decisions.md`](./docs/ideas/phase-0-decisions.md).)

## Configuration

Expand All @@ -197,7 +194,7 @@ Each CLI auto-loads `.env` and `.env.local` from the working directory.

What the agent reads when it authors, reviews, or remediates. The canonical artifact is **`expression.md`** (owned by `ghost-expression`): a Markdown document with YAML frontmatter (machine layer) plus a three-layer prose body. Human-readable, LLM-consumable, diff-friendly:

- **Frontmatter**: 49-dimensional embedding, palette, spacing, typography, surfaces, roles, provenance. What deterministic tools read.
- **Frontmatter**: 49-dimensional embedding, palette, spacing, typography, surfaces, roles, provenance. The machine layer.
- **`# Character`**: the opening atmosphere read, evocative not technical. What an agent quotes to stay on-brand.
- **`# Signature`**: 3–7 distinctive traits that make _this_ system unlike its peers. The drift-sensitive moves.
- **`# Decisions`**: abstract, implementation-agnostic choices with evidence. Each decision is embedded so `ghost-drift compare --semantic` can match semantically.
Expand All @@ -208,7 +205,7 @@ Generate one with the `profile` recipe (in the `ghost-expression` skill bundle).

What every Ghost tool reads to learn the topology of a repo. The canonical artifact is **`map.md`** (owned by `ghost-map`): YAML frontmatter against the `ghost.map/v1` schema (languages, build system, package manifests, registry, design-system paths, UI surface globs, feature areas) plus a short prose body (Identity, Topology, Conventions). The repo's own `map.md` lives at the root.

Generate one with the `map` recipe (in the `ghost-map` skill bundle). The agent reads `ghost-map inventory` (deterministic raw signals) and synthesizes the prose layer.
Generate one with the `map` recipe (in the `ghost-map` skill bundle). The agent reads `ghost-map inventory` (raw repo signals as JSON) and synthesizes the prose layer.

### Author + self-govern loop

Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/app/docs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const sections: {
name: "CLI Reference",
href: "/docs/cli",
description:
"Sixteen deterministic primitives across four tools — ghost-map, ghost-expression, ghost-drift, ghost-fleet. Plus the skill recipes the host agent runs.",
"Sixteen verbs across four tools — ghost-map, ghost-expression, ghost-drift, ghost-fleet. Plus the skill recipes the host agent runs.",
icon: <BookOpen className="size-8" strokeWidth={1.5} />,
},
{
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/app/tools/fleet/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const cards: {
name: "Skill bundle",
href: "https://github.com/block/ghost/tree/main/packages/ghost-fleet/src/skill-bundle",
description:
"The target recipe — synthesize the fleet.md prose narrative from the deterministic view output.",
"The target recipe — synthesize the fleet.md prose narrative from the view output.",
icon: <Network className="size-8" strokeWidth={1.5} />,
},
];
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/app/tools/map/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default function GhostMapLanding() {
<AnimatedPageHeader
kicker="ghost-map"
title="Topology"
description="The navigation card every Ghost tool reads. map.md answers “where is the design system, which folders matter?” — language-agnostic, validated against ghost.map/v1, generated by the host agent from the deterministic inventory."
description="The navigation card every Ghost tool reads. map.md answers “where is the design system, which folders matter?” — language-agnostic, validated against ghost.map/v1, written by the host agent from the raw inventory."
/>

<div
Expand Down
10 changes: 5 additions & 5 deletions apps/docs/src/components/docs/workflow-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1135,9 +1135,9 @@ export function WorkflowContent() {
))}
</div>
<p className="reveal mt-8 text-sm text-muted-foreground max-w-[52ch] leading-relaxed">
Ghost never calls an LLM itself. The agent writes the expression; the
CLI lints, compares, and diffs it deterministically. The final step of
every profile is <code>ghost-expression lint</code> which validates
The agent writes the expression. The CLI is the calculator it reaches
for: lint, compare, diff — same answer every time. The final step of
every profile is <code>ghost-expression lint</code>, which validates
the schema and flags body/frontmatter incoherence before anything else
touches it.
</p>
Expand Down Expand Up @@ -1203,7 +1203,7 @@ export function WorkflowContent() {
</StepLead>
<ReviewSection />
<p className="reveal mt-8 text-sm text-muted-foreground max-w-[52ch] leading-relaxed">
The agent reaches for deterministic primitives as it needs them:{" "}
The agent reaches for the CLI as it needs reproducible answers:{" "}
<code className="rounded bg-muted px-1.5 py-0.5 text-xs font-mono">
ghost-drift compare
</code>{" "}
Expand Down Expand Up @@ -1383,7 +1383,7 @@ export function WorkflowContent() {
</code>{" "}
is a CLI verb. <em>Generate</em>, <em>review</em>, and <em>verify</em>{" "}
are skill recipes: instructions your host agent follows, calling the
deterministic primitives as it goes. <em>Verify</em> is the
CLI when it needs a reproducible answer. <em>Verify</em> is the
schema-discipline mechanism: each dimension gets classified as{" "}
<em>tight</em>, <em>leaky</em>, or <em>uncaptured</em> — a map of
where the expression needs sharpening.
Expand Down
28 changes: 14 additions & 14 deletions apps/docs/src/content/docs/cli-reference.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: CLI Reference
description: Sixteen deterministic primitives across four tools. Everything interpretive lives in the skill bundles.
description: Sixteen verbs across four tools. Everything interpretive lives in the skill bundles your host agent runs.
kicker: Docs
section: guide
order: 20
Expand All @@ -9,12 +9,12 @@ slug: cli

<DocSection title="Overview">

Ghost's CLIs are deterministic primitives. None of them call an LLM. The
canonical artifacts are **`expression.md`** (owned by `ghost-expression`)
and **`map.md`** (owned by `ghost-map`) — Markdown files with YAML
frontmatter (machine layer) plus a prose body. Most commands accept a path
to the relevant artifact; they default to `./expression.md` or `./map.md`
in the current directory.
The CLIs are the calculator your host agent reaches for when it needs a
reproducible answer. The canonical artifacts are **`expression.md`** (owned
by `ghost-expression`) and **`map.md`** (owned by `ghost-map`) — Markdown
files with YAML frontmatter (machine layer) plus a prose body. Most commands
accept a path to the relevant artifact; they default to `./expression.md` or
`./map.md` in the current directory. No API key required.

Verbs are scoped to the tool that owns the artifact:

Expand All @@ -37,7 +37,7 @@ this reference — so these docs can't drift from the binaries.

`map.md` is the navigation card every Ghost tool reads to learn the
topology of a frontend repo. `ghost-map` ships two verbs: `inventory`
(deterministic raw signals as JSON, the input the agent reads to author
(raw repo signals as JSON, the input the agent reads to author
`map.md`) and `lint` (validate against `ghost.map/v1`).

<CliHelp tool="ghost-map" command="inventory" hideDescription />
Expand Down Expand Up @@ -94,10 +94,10 @@ whole file.

A typical `expression.md` runs 3–5k tokens. The `# Decisions` block alone
is usually 60–80% of that, and an agent reviewing a single component change
rarely needs every dimension. `describe` is the deterministic answer to
"what's in this file and where" — the recall safety rule (when in doubt,
load the whole `# Decisions` block) lives in the review/remediate skill
recipes.
rarely needs every dimension. `describe` answers "what's in this file and
where" with the same answer every time — the recall safety rule (when in
doubt, load the whole `# Decisions` block) lives in the review/remediate
skill recipes.

<CliHelp tool="ghost-expression" command="describe" hideDescription />

Expand Down Expand Up @@ -309,8 +309,8 @@ once, then ask your agent in plain English:

Source for each recipe lives under
`packages/<tool>/src/skill-bundle/references/`. The agent executes the
steps with its normal tools and calls the relevant CLI for any
deterministic work.
steps with its normal tools and calls the relevant CLI when it needs a
reproducible answer.

Each recipe also declares `handoffs` in its frontmatter — structured
next-step suggestions that point at another skill (e.g. `profile` →
Expand Down
Loading
Loading