con un clic
tokextract
// Extract a design system (DTCG tokens + DESIGN.md + audit) from any SwiftUI codebase
// Extract a design system (DTCG tokens + DESIGN.md + audit) from any SwiftUI codebase
| name | tokextract |
| description | Extract a design system (DTCG tokens + DESIGN.md + audit) from any SwiftUI codebase |
| trigger_phrases | ["extract design tokens from this repo","run tokextract","audit my SwiftUI design system","what design tokens does this app use","recover the design system from this codebase"] |
Reverse-engineers an implicit SwiftUI design system into three artifacts:
tokens.json — W3C DTCG 2025.10 design tokens (all 9 categories)DESIGN.md — LLM-readable brand narrative companion (Google @google/design.md alpha format)audit.md — Drift report: magic numbers, near-duplicate colors, off-scale values, Liquid Glass violations, harmonization recommendationsInvoke as: /tokextract --path <swift-repo> [--output <dir>] [--no-llm]
When invoked, run this pipeline. Each step is restartable; if any LLM task fails,
re-running picks up where it left off (findings.raw.json is durable).
--no-llm mode skips Steps 2, 3, 4, 6, 7 entirely. Steps 1, 5, 8 still run.
node ${CLAUDE_PLUGIN_ROOT}/dist/extract.js parse \
--path <path> \
--output <out> \
[--no-llm] \
[--max-files 2000] \
[--delta-e-threshold 2.5] \
[--skip <categories>] \
[--target-os <ver>] \
[--vendor-namespace <s>] \
[--force-color-space srgb|display-p3|oklch]
This emits:
<out>/.tokextract/findings.raw.json — AST + regex extraction results for all 9 categories<out>/.tokextract/clusters.json — color cluster analysis<out>/.tokextract/numericClusters.json — numeric cluster analysis (spacing/radius/shadow)<out>/.tokextract/drift.json — off-scale numeric values<out>/.tokextract/meta.json — vendor namespace + target OS<out>/.tokextract/llm-tasks.json — manifest of pending LLM passes (unless --no-llm)<out>/.tokextract/prompts/normalize-<category>-<n>.md — per-category normalize promptsRead <out>/.tokextract/llm-tasks.json. For each task with status: "pending" and pass: "normalize":
Spawn an Agent subagent with:
subagent_type: "general-purpose"model: task.recommendedModel (e.g. "claude-haiku-4-5-20251001")description: task.id (e.g. "normalize-color-1")prompt: contents of task.promptPath, prepended with:Read the prompt below and write your structured JSON response to <task.responsePath>
using the Write tool. Validate that your output matches the Mapping[] schema before writing.
Reply with exactly the word "done" after writing.
---
[contents of task.promptPath]
Independent tasks (different categories or chunks) can run in parallel.
After all tasks complete, verify each task.responsePath exists.
node ${CLAUDE_PLUGIN_ROOT}/dist/extract.js plan-harmonize \
--output <out> \
[--model-harmonize claude-sonnet-4-6]
This reads clusters.json + numericClusters.json and appends a harmonize task to llm-tasks.json.
If there are no clusters, this is a no-op.
Read <out>/.tokextract/llm-tasks.json. For the task with pass: "harmonize" and status: "pending":
Spawn one Agent subagent with task.recommendedModel against the harmonize prompt.
The subagent writes <out>/.tokextract/llm-out/mapping.harmonize.json directly via the Write tool.
node ${CLAUDE_PLUGIN_ROOT}/dist/extract.js emit \
--output <out> \
[--no-llm]
This:
<out>/.tokextract/llm-out/<out>/tokens.json, <out>/audit.md, <out>/DESIGN.md (stub in --no-llm)<out>/preview.html — self-contained visual review of the extracted system (open it directly in a browser; no server, no build step)<out>/.tokextract/previous/tokens.json (if it exists) → appended to audit.mdtokens.json to <out>/.tokextract/previous/tokens.json for diff on next runnode ${CLAUDE_PLUGIN_ROOT}/dist/extract.js plan-narrate \
--output <out> \
[--model-narrate claude-sonnet-4-6]
This reads tokens.json + audit.md and appends a narrate task to llm-tasks.json.
Read <out>/.tokextract/llm-tasks.json. For the task with pass: "narrate" and status: "pending":
Spawn one Agent subagent with task.recommendedModel against the narrate prompt.
The subagent reads tokens.json + audit.md and writes <out>/DESIGN.md directly via the Write tool.
This is the highest-leverage LLM step — the subagent generates the full brand narrative prose.
node ${CLAUDE_PLUGIN_ROOT}/dist/extract.js finalize \
--output <out> \
[--no-llm]
Runs the DESIGN.md lint pass (8 rules: broken-ref, missing-primary, contrast-ratio, orphaned-tokens, token-summary, missing-sections, missing-typography, section-order). Prints a summary of what was extracted.
| Flag | Default | Description |
|---|---|---|
--path <dir> | (required) | Swift repo root |
--output <dir> | <path>/.tokextract-out | Output directory |
--no-llm | false | Skip LLM passes (CI-safe, mechanical token names) |
--max-files <n> | 2000 | Hard limit on .swift files |
--delta-e-threshold <n> | 2.5 | CIEDE2000 distance for near-duplicate clustering |
--model-normalize <id> | claude-haiku-4-5-20251001 | Model for normalize pass |
--model-harmonize <id> | claude-sonnet-4-6 | Model for harmonize pass |
--model-narrate <id> | claude-sonnet-4-6 | Model for narrate pass |
--skip <cats> | (none) | Comma-separated categories to skip |
--force-color-space <s> | (auto) | Override color space: srgb | display-p3 | oklch |
--target-os <ver> | (auto-detect) | Target iOS version; gates Liquid Glass (26) and @Entry (18) |
--vendor-namespace <s> | (from Info.plist) | Override $extensions vendor key |
--self-critique | false | Enable self-critique pass after narrate |
--verbose | false | Verbose output with per-category counts |
<output-dir>/
├── tokens.json # W3C DTCG 2025.10 — canonical machine truth (all 9 categories)
├── DESIGN.md # Brand narrative (stub until narrate pass runs)
├── audit.md # Drift report (7 sections: magic numbers, near-duplicates,
│ # orphaned tokens, off-scale values, glass violations,
│ # harmonization, changes since last extraction)
├── preview.html # Self-contained visual review (swatches, ΔE clusters, type scale)
└── .tokextract/ # Internal state — delete to force clean re-run
├── findings.raw.json
├── clusters.json
├── numericClusters.json
├── drift.json
├── meta.json # vendorNamespace + targetOs
├── llm-tasks.json
├── prompts/
│ ├── normalize-color-1.md
│ ├── normalize-typography-1.md
│ ├── harmonize.md
│ └── narrate.md
├── llm-out/
│ ├── mapping.color.1.json
│ ├── mapping.typography.1.json
│ └── mapping.harmonize.json
└── previous/
└── tokens.json # Snapshot for diff on next run
--max-files exceeded → hard abort with clear error (don't silently degrade)error in manifest; re-run to retryassetMissing: true, severity: errorplan-harmonize no-ops cleanlyThis is a Claude Code plugin distributed through the conorluddy marketplace. To install:
# Add the marketplace (one-time):
/plugin marketplace add conorluddy/tokextract
# Install the plugin:
/plugin install tokextract@tokextract
The plugin is shipped pre-built — no npm install step required at install time.
For local development (modifying the plugin source), build from the source repo:
cd /Users/conor/Development/Extoken/plugins/tokextract
npm install
npm run build
After rebuilding, refresh the installed plugin: /plugin marketplace update tokextract.