with one click
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.