From tokextract
Extract a design system (DTCG tokens + DESIGN.md + audit) from any SwiftUI codebase
How this skill is triggered — by the user, by Claude, or both
Slash command
/tokextract:extractThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Reverse-engineers an implicit SwiftUI design system into three artifacts:
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.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub conorluddy/tokextract --plugin tokextract