Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
8de07db
Add spec for /adhd:install-design-system-docs-route
hhff May 11, 2026
c3c5d5b
spec: clarify re-run semantics for install-design-system-docs-route
hhff May 11, 2026
51b7222
Add implementation plan for /adhd:install-design-system-docs-route
hhff May 11, 2026
47a4368
Scaffold lib/install-design-system-docs-route with cli stub
hhff May 11, 2026
8c37cba
token-parser: extract colors/spacing/typography/radius/shadows from g…
hhff May 11, 2026
b3e9372
token-parser: clarify @theme parsing assumptions and switch on domain
hhff May 11, 2026
c897452
prop-parser: extract component prop interface (unions, primitives, op…
hhff May 11, 2026
140745c
prop-parser: align names with push-component sibling
hhff May 11, 2026
cc1079e
slug: component path → URL slug + collision disambiguation
hhff May 11, 2026
71cd1cd
slug: extract pathSegments helper to dedupe path normalization
hhff May 11, 2026
f437659
next-config-patcher: idempotent conditional pageExtensions patch
hhff May 11, 2026
bc1c657
next-config-patcher: align naming with sibling lib conventions
hhff May 11, 2026
827d349
robots-patcher: idempotent Disallow entry for the docs route
hhff May 11, 2026
6242cb2
templates: layout, index, component page, PropToggle (marker-prefixed…
hhff May 11, 2026
54059c6
route-installer: write the 4 page files; detect existing installs via…
hhff May 11, 2026
764d071
cli: wire all subcommands (parse-tokens, parse-props, slug, patch-*, …
hhff May 11, 2026
c75f63e
Add /adhd:install-design-system-docs-route skill
hhff May 11, 2026
ed6275f
SKILL: clarify Phase 6 exit-code handling and Phase 2 update-in-place…
hhff May 11, 2026
433881b
config: offer to install the design-system docs route as an optional …
hhff May 11, 2026
b386569
README + marketplace: document /adhd:install-design-system-docs-route
hhff May 11, 2026
794ff5c
Fix two bugs surfaced by a real-world install in reactor-webapp
hhff May 11, 2026
fda97b4
docs-route: sidebar+viewer layout, expanded token domains, Tailwind-d…
hhff May 11, 2026
1d41637
docs-route: diagnose globals.css gaps + error boundary at component r…
hhff May 11, 2026
999fda0
install-docs-route SKILL: batch Phase 3 questions into one wizard prompt
hhff May 11, 2026
f149df2
setup-design-system-docs-route: rename + flip to static imports
hhff May 11, 2026
b744394
setup-design-system-docs-route: extract tokenDomains, prune landing page
hhff May 11, 2026
6acd374
sync-docs: rename from setup-design-system-docs-route
hhff May 11, 2026
44fb0c6
sync-docs: collapse tokenDomains.tsx into the layout
hhff May 11, 2026
1d84ab0
sync-docs: inline PropToggle, drop error.tsx, bake prop schemas
hhff May 11, 2026
728652e
sync-docs: render-where wizard option adds Vercel-preview mode
hhff May 11, 2026
7e06588
pull-component + pull-design-system: offer to sync docs route on success
hhff May 11, 2026
d10704f
lint + push/pull-component: add --annotate flag
hhff May 12, 2026
07043c2
lint + push/pull-component: offer to annotate when --annotate wasn't …
hhff May 12, 2026
156f54f
lint STRUCT001: widen exemption to multi-child shape-only frames
hhff May 12, 2026
47bcbd8
lint STRUCT007 + STRUCT010: stronger diagnostic copy for variant-inte…
hhff May 12, 2026
254e60d
lint: recursive STRUCT001 exemption + softer annotation category + /t…
hhff May 12, 2026
e86214b
sync-docs: eliminate explicit \`any\` from generated files
hhff May 12, 2026
5e9819a
lint STRUCT003: surface raw hex, honor paint styles, catch mixed-pain…
hhff May 12, 2026
aa4cf1f
sync-docs: trace globals.css for serverless tokens-page deploys
hhff May 12, 2026
5d76ff0
lint STRUCT011: check Figma variable names against the project's conv…
hhff May 12, 2026
ad1e340
lint STRUCT011: add Tailwind-domain "did you mean?" hints
hhff May 12, 2026
6fe405c
pull-component: STRUCT011 now blocks the pull (no escape)
hhff May 12, 2026
bc1dacd
lint STRUCT011: two bug fixes from real lint output
hhff May 12, 2026
5fbf4a6
pull-component: Phase 2.7 — opportunistic variable discovery
hhff May 12, 2026
ee8bcd8
lint STRUCT011: one concrete rename target per variable
hhff May 12, 2026
ff63be7
lint annotate: scope-aware cleanup so scoped lints don't wipe other f…
hhff May 12, 2026
aa38f66
lint engine: merge Tailwind v4 defaults so vars like \`white\` aren't…
hhff May 12, 2026
c1576d6
add /adhd:pull-all-components and /adhd:push-all-components bulk skills
hhff May 12, 2026
cbbb4b0
sync-docs: open-in-Figma link + proper PascalCase component name
hhff May 12, 2026
364d889
sync-docs: "Last built" timestamp in sidebar header
hhff May 12, 2026
c89231c
lint STRUCT011: group by target collection + clarify "Move to" vs "Re…
hhff May 12, 2026
63c9c2c
lint-engine: STRUCT012 + per-layer STRUCT011 annotations
hhff May 12, 2026
46af87d
push/pull-tokens: rename from -design-system + --dry-run preview
hhff May 12, 2026
bc68e9e
lint: STRUCT013 + --fix for Tailwind-default duplicates
hhff May 12, 2026
ae0ef7f
lint: reject --fix + --dry-run as incompatible
hhff May 12, 2026
f7cac18
push-tokens: subtract Tailwind defaults from codeOnly + resolve @them…
hhff May 12, 2026
c3eadeb
push-tokens: --include-tailwind to seed full palette + bucket dry-run…
hhff May 12, 2026
1f9a874
push-tokens: round-trip canonicalization + skip font families + alias…
hhff May 12, 2026
bd22dca
push-tokens: 7-question disposition wizard runs on every push
hhff May 12, 2026
520c452
push-tokens: drop --include-tailwind (subsumed by dispositions wizard)
hhff May 12, 2026
f229fa4
push-tokens: text/*/line-height paths push as FLOAT+LINE_HEIGHT (not …
hhff May 12, 2026
0ab6cbc
push-tokens: alias-aware collection lookup (stop duplicating Color / …
hhff May 12, 2026
c5e4b22
lint: STRUCT014 + --fix for alias-equivalent collection duplicates
hhff May 12, 2026
ec5f5e8
pull-component: per-component fingerprint short-circuit (skip when no…
hhff May 12, 2026
c107d03
lint: STRUCT015/016 — per-layer errors block pulls when bindings are …
hhff May 12, 2026
eb38fed
lint: kill the "color/primary" false-conflict at its root
hhff May 12, 2026
a321871
lint: stop the engine crashing on numeric vars + resolve var(--X) chains
hhff May 12, 2026
63dabdf
pull-component: interactive STRUCT015/016 resolution with alias-aware…
hhff May 12, 2026
ef10c0d
push-component: interactive STRUCT015/016 resolution mirroring pull
hhff May 12, 2026
f8d65cf
pull/push-component: rename "Skip" → "Annotate only — don't sync this…
hhff May 12, 2026
645b1dd
pull/push-component: drop --annotate flag, auto-annotate on abort, "D…
hhff May 12, 2026
9ee8fb3
lint: include the synthesized Tailwind utility scale in default-primi…
hhff May 12, 2026
17ae95d
pull/push-component: "Auto-fix" option + explicit "Add as semantic" l…
hhff May 13, 2026
91707ec
pull-component: Phase 2.7 inherits the per-variable + auto-fix prompt…
hhff May 13, 2026
dbfa0bc
pull-component: Phase 2.7 — replace "Cancel" with explicit "Annotate …
hhff May 13, 2026
eb0ce0c
pull/push-component: shorten resolution-prompt labels
hhff May 13, 2026
258eaf4
lint: drop --annotate / --fix flags, always run interactive resolutio…
hhff May 13, 2026
cf8ce21
pull-component: simple-layout-driven scaffold branch — actually gener…
hhff May 13, 2026
47f8011
pull-component: INSTANCE-of-tracked-component branch + dependency pre…
hhff May 13, 2026
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
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
{
"name": "adhd",
"source": "./plugins/adhd",
"description": "Push, pull, and lint design tokens between Tailwind v4 and Figma; push and pull React components with preflight validation."
"description": "Push, pull, and lint design tokens between Tailwind v4 and Figma; push and pull React components with preflight validation; install a live design-system docs route into your Next.js consumer app."
}
]
}
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jobs:
run: node --test plugins/adhd/lib/push-component/__tests__/
- name: Run pull-component tests
run: node --test plugins/adhd/lib/pull-component/__tests__/
- name: Run sync-docs tests
run: node --test plugins/adhd/lib/sync-docs/__tests__/

hygiene:
name: project hygiene
Expand Down
97 changes: 87 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@ Then install ADHD itself:

All three commands are persistent — Claude Code remembers the marketplaces and the enabled plugins across sessions. Run them once per machine.

After install, six slash commands are available:
After install, nine slash commands are available:

| Command | Args | Direction | What it does |
|---|---|---|---|
| `/adhd:config` | — | — | Interactive wizard that produces `adhd.config.ts`. Verifies the official Figma plugin is installed + authenticated before anything else. |
| `/adhd:lint` | `[<figma-url>]` | read-only | Validates the Figma file (whole file or scoped) against the local design system + structure best-practices |
| `/adhd:push-design-system` | — | code → Figma | Pushes globals.css variables + named styles into Figma directly via the remote MCP |
| `/adhd:pull-design-system` | — | Figma → code | Pulls Figma variables + named styles into globals.css |
| `/adhd:push-component` | `<path> [--max-variants <n>]` | code → Figma | Pushes a React component to Figma as a structured Component Set with variant properties + variable bindings, plus a preflight lint check |
| `/adhd:pull-component` | `<path \| figma-url> [--allow-unbound]` | Figma → code | Pulls a Figma Component Set into a React source file; updates lookup tables and union types only (function body untouched) |
| `/adhd:lint` | `[<figma-url>]` | always interactive | Validates the Figma file (whole file or scoped) against the local design system + structure best-practices, then walks every violation through a per-rule resolution wizard. Per violation, designers pick from auto-fix in Figma (rebind to canonical / consolidate duplicates), add in code, take Figma's value, take code's value, annotate only, or skip. No flags — annotation and fix behavior are per-violation choices. |
| `/adhd:push-tokens` | `[--dry-run]` | code → Figma | Pushes globals.css variables + named styles into Figma directly via the remote MCP. Runs an interactive 7-question wizard on every invocation to set per-domain push policy: push the full Tailwind palette or only your semantic colors? Push the full spacing scale or only your authored tokens? Skip opacity entirely? Route shadows through effect styles? `--dry-run` previews exactly what would be added or skipped (reflecting your wizard answers) without writing. |
| `/adhd:pull-tokens` | `[--dry-run]` | Figma → code | Pulls Figma variables + named styles into globals.css. `--dry-run` previews without writing. |
| `/adhd:push-component` | `<path> [--max-variants <n>]` | code → Figma | Pushes a React component to Figma as a structured Component Set with variant properties + variable bindings, plus a preflight lint check. Per-variable STRUCT015/STRUCT016 resolution prompts let you sync mismatches in either direction; annotations land automatically on any abort. |
| `/adhd:push-all-components` | `[--continue-on-error] [--max-variants <n>]` | code → Figma | Bulk version of `push-component` — iterates over every entry in `adhd.config.ts`'s components map. Sequential, halt-on-first-failure by default. |
| `/adhd:pull-component` | `<path \| figma-url> [--allow-unbound]` | Figma → code | Pulls a Figma Component Set into a React source file. Scaffold mode generates real JSX for vector-driven (inline SVG) and simple-layout-driven components; complex layouts get a stub the developer fills in. INSTANCE children that reference tracked components in `adhd.config.ts` are emitted as `<TrackedComponent />` imports rather than inlined markup — a Phase 2.8 pre-flight aborts with a "pull this first" message when an instance's source isn't tracked. Per-variable STRUCT015/STRUCT016 resolution prompts let you sync mismatches in either direction; annotations land automatically on any abort. Records an 8-char fingerprint + ISO `pulledAt` in `adhd.config.ts`; subsequent pulls short-circuit (no lint, no diff, no commit) when the Figma extract + pull-relevant config still hash to the same value. |
| `/adhd:pull-all-components` | `[--continue-on-error] [--allow-unbound]` | Figma → code | Bulk version of `pull-component` — iterates over every entry in `adhd.config.ts`'s components map. Sequential, halt-on-first-failure by default. Components whose stored fingerprint matches the fresh Figma extract are reported as `unchanged` and skipped (no lint, no diff, no commit). |
| `/adhd:sync-docs` | — | install | Generates a design-system docs route in your Next.js consumer app. Tokens read live from globals.css; components are statically imported from adhd.config.ts at setup time — re-run after editing the components map. Excluded from production builds by default. |

Every command above drives Figma exclusively through the `figma@claude-plugins-official` plugin. `/adhd:config` checks it's installed + authenticated up front so setup errors surface where you can fix them, not mid-pipeline.

Expand Down Expand Up @@ -66,8 +69,10 @@ Then:
```
/adhd:lint # validate the whole Figma file
/adhd:lint https://figma.com/design/<KEY>?node-id=12-2 # validate a single page/frame/component
/adhd:push-design-system # apply (code → Figma; will prompt before writing)
/adhd:pull-design-system # apply (Figma → code; will prompt before writing)
/adhd:push-tokens # apply (code → Figma; will prompt before writing)
/adhd:push-tokens --dry-run # preview what would change without writing
/adhd:pull-tokens # apply (Figma → code; will prompt before writing)
/adhd:pull-tokens --dry-run # preview what would change without writing
/adhd:push-component app/components/avatar/index.tsx # push a React component to Figma
```

Expand All @@ -83,7 +88,20 @@ Pass any Figma URL that includes a `node-id` query parameter — `/adhd:lint` wi
/adhd:lint https://www.figma.com/design/PBCAkpPnvGXWrz6H7qfH3V/ADHD-Reference?node-id=91-18
```

The scoped report covers the same rules (STRUCT001–010 + variable mismatches), just narrowed to the selected subtree. The URL must point at the file configured in `adhd.config.ts`; mismatched file keys abort with a fix-up message.
The scoped report covers the same rules (STRUCT001–016 + variable mismatches), just narrowed to the selected subtree. The URL must point at the file configured in `adhd.config.ts`; mismatched file keys abort with a fix-up message.

### Annotate violations in Figma

`/adhd:lint` is always interactive — every violation goes through a per-rule wizard with "Annotate only" as one of the options. Picking it pushes the violation to Figma as a node-bound annotation in a dedicated **"lint"** category (orange); picking anything else either resolves the issue directly (auto-fix in Figma, add in code, take Figma's value, take code's value) or skips it (no annotation, no fix). Stale annotations from prior runs get cleaned up automatically when their nodes drop out of the picks list — designer-authored annotations and any non-"lint" category are never touched.

For `/adhd:push-component` and `/adhd:pull-component`, annotation is **automatic on any abort** — when the SKILL aborts due to preflight violations (including a "Don't sync" pick on the per-variable STRUCT015/STRUCT016 prompts), every blocking violation is pushed to Figma before exit. On successful runs the same annotation script clears prior-run annotations from the scope so Figma stays clean. No flag needed.

```
/adhd:lint # whole file — walks every violation
/adhd:lint https://www.figma.com/design/<KEY>?node-id=91-18 # scoped — walks every violation
/adhd:push-component app/components/avatar/index.tsx # annotates on abort
/adhd:pull-component https://www.figma.com/design/<KEY>?node-id=91-18 # annotates on abort
```

### Push a component

Expand All @@ -110,6 +128,65 @@ The skill parses the component's TypeScript prop unions, generates a temp previe

The skill reads the Figma Component Set, diffs it against the React file's `Record<Union, string>` lookup tables, prompts on each divergence, and rewrites only those tables (plus union type members). Function body, JSX, hooks, handlers, and imports are never modified.

### Design system docs route

Run once in your consumer repo:

```
/adhd:sync-docs
```

This generates a documentation page that reads your `globals.css` live at
request time and statically imports the components listed in
`adhd.config.ts`. The default URL is `/-docs` (the hyphen prefix telegraphs
"internal"), and files live under a Next.js route group at
`app/(design-system)/-docs/`. The page is a sidebar-and-viewer layout:

- Sidebar: lists every Tailwind v4 token domain (colors, spacing, typography,
font families, font weights, tracking, leading, radius, shadows,
breakpoints, easing, animation), plus every component tracked in
`adhd.config.ts`. Click a row to load that route in the main pane.
- Token pages: render whatever your `@theme` (or `@theme inline`) block
declares for that domain. Empty domains link to Tailwind v4's docs for the
defaults you're inheriting.
- Component pages: each component gets its own route with URL-driven prop
toggles, derived from the component's TypeScript prop interface.

The setup command asks **where the docs route should render** with three
options:

- **Dev only** (default) — files use `.design-system.tsx`; `pageExtensions`
in `next.config.ts` gates on `process.env.NODE_ENV === 'production'`. The
production build literally doesn't see the files.
- **Dev + Vercel preview** — same file extension, but `pageExtensions`
gates on `process.env.VERCEL_ENV === 'production' || (!VERCEL && NODE_ENV === 'production')`.
The route renders on local dev *and* Vercel preview deploys, but stays out
of Vercel production (and out of any non-Vercel production deploy too, so
CI builds don't accidentally ship it).
- **Everywhere** — no `pageExtensions` patch; route files use plain `.tsx`
and ship in production. The layout's metadata still emits `<meta
name="robots" content="noindex, nofollow" />` so it won't be indexed.

#### Re-running after `adhd.config.ts` changes

The setup command generates a `componentMap.tsx` with explicit static
imports per component. After **adding, renaming, or removing entries** in
`adhd.config.ts`'s `components` map, re-run
`/adhd:sync-docs` to regenerate the static imports.
Tokens don't need this — they're read from `globals.css` at request time.

Files where you've removed the `// design-system-docs-route` marker comment
are preserved across re-runs.

The static-import architecture is deliberate: it keeps the docs route's
bundle scoped to exactly your tracked components, sidestepping the
`Cannot apply unknown utility class …` failure mode that broad dynamic
imports trigger under Tailwind v4 (legacy shadcn classes in unrelated parts
of your codebase get bundled and explode during PostCSS).

You can also trigger the install at the end of `/adhd:config` if you're
setting up ADHD for the first time.

### Figma file structure

The Figma file must follow the structure mandated in the spec — a `Primitives` collection (no modes) and a `Semantic` collection (Light + Dark modes). The skill validates this and surfaces fix-up guidance on failure.
Expand Down Expand Up @@ -137,7 +214,7 @@ cd example
```
.
├── plugins/adhd/ # The plugin source
│ ├── skills/ # config, lint, push-design-system, pull-design-system
│ ├── skills/ # config, lint, push-tokens, pull-tokens
│ ├── lib/ # zero-deps Node libraries (lint-engine, design-system)
│ └── .claude-plugin/ # plugin manifest
├── docs/superpowers/
Expand Down
Loading
Loading