Install
$ agentstack add skill-murphytrueman-design-system-ops-token-audit ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Token audit
A skill for auditing design token architecture across whichever tiers are in use — typically primitives and semantics, with component tokens where the system uses them. Produces a structured report with severity-rated findings and a prioritised remediation list.
Context
This skill draws on the tiered token architecture model: primitives encode raw values, semantic tokens encode intent, and — where present — component tokens map intent to specific UI contexts. Not every system uses component tokens, and the absence of a component tier is not a finding. Most token debt accumulates when tiers blur — when component contexts reference primitives directly, when semantic names describe appearance rather than purpose, or when the primitive layer is treated as the only layer.
The audit is not about enforcing a particular naming convention. It's about identifying where the token structure is working against the teams using it.
Configuration
Before producing output, check for a .ds-ops-config.yml file in the project root. If present, load:
severity.*— overrides for finding severity ratings (e.g.hardcoded_color: criticalinstead of the defaulthigh)system.theming— if true, elevate hardcoded colour findings to the severity specified in configsystem.styling— pre-selects the format-specific guidance to applyintegrations.style_dictionary— if enabled, auto-parse tokens via Style Dictionary v4 (see auto-pull below)integrations.figma— if enabled, pull Figma variables as an additional token sourcerecurring.*— if this is a recurring run, load the previous report for trend comparison (see recurring workflow below)
If no config file exists, proceed with defaults and manual input as before.
Auto-pull integrations
If integrations are configured in .ds-ops-config.yml, pull data automatically before asking the user for manual input:
Style Dictionary v4 (integrations.style_dictionary.enabled: true):
- Parse the config at
integrations.style_dictionary.config_path - Extract the full token tree with resolved references and tier structure
- Use this as the primary token source — skip the manual "provide your token files" question
- If Style Dictionary v4 is installed, run
npx style-dictionary build --config [path] --dry-runto validate references without writing output
Figma variables (integrations.figma.enabled: true):
- Use the Figma MCP server to read variables from the file at
integrations.figma.file_key - Extract variable collections, modes, and resolved values
- Cross-reference Figma variables against code token files to detect mismatches (Figma says
--color-primaryis#0066CCbut the code says#0064CC— that is a finding)
GitHub (integrations.github.enabled: true):
- Search the repository for hardcoded colour/spacing values using
gh api search/codeto quantify the scope of violations before the detailed audit - Pull the token file directly from the default branch if no local file is provided
If an integration is configured but fails (e.g. auth error, rate limit), log the failure and fall back to manual input. Never block the audit because an integration is unavailable.
Step 0: Token discovery
Before asking the user for files, search the codebase for token-like patterns. This step lowers activation energy for teams where tokens exist but are not centralised — the user does not have to know where all their tokens live.
What to search for:
- CSS custom properties — scan all
.cssfiles for:rootblocks or--prefixed properties. Include scoped variants (.dark,[data-theme="..."],.theme-*). - SCSS/Sass variables — scan all
.scssand.sassfiles for$-prefixed names. Follow@importand@usechains to find partial files (_colors.scss,_variables.scss,_tokens.scss). - JSON/YAML token files — scan for files matching common token naming patterns:
tokens.json,tokens.yaml,*.tokens.json,design-tokens/**,src/tokens/**,tokens/**. Also look for DTCG-formatted files containing$typeor$valuekeys. - Style Dictionary configs — scan for
style-dictionary.config.json,config.jsonin astyle-dictionary/directory, or.style-dictionary.json. - TypeScript/JavaScript token objects — scan
.tsand.jsfiles for exports matching common patterns:export const tokens,export const theme,export default { color,as consttyped objects with token-like key hierarchies. - Tailwind configurations — scan for
tailwind.config.js,tailwind.config.ts, ortailwind.config.mjsand extract thethemeandextendblocks. - Figma Tokens / Tokens Studio — scan for
tokens.jsonin a.tokensortokensdirectory, or files exported from Tokens Studio.
How to search:
Use file system access (glob patterns, file reads) to scan the project. If GitHub integration is configured, use gh api search/code as a secondary source. If Figma integration is configured, pull Figma variables as an additional token source.
Prioritise by specificity: a dedicated tokens/ directory is more reliable than scattered CSS files. A Style Dictionary config is more reliable than raw JSON. But collect everything — fragmented token sources are themselves a finding.
Discovery output:
Produce a brief inventory before continuing:
Token sources found:
- src/tokens/colors.json (94 tokens, JSON, likely primitives)
- src/tokens/semantic.json (67 tokens, JSON, likely semantic tier)
- src/styles/variables.scss (43 variables, SCSS)
- tailwind.config.ts (theme block with 28 custom values)
Total: ~232 token-like declarations across 4 sources
If discovery finds nothing, proceed to Step 1 and ask the user for manual input. If discovery finds scattered sources across multiple formats, flag this as a finding: "Tokens exist in [N] different formats across [M] files. This fragmentation is structural debt — consider centralising to a single source of truth."
Present the discovered sources to the user and ask: "I found these token sources. Should I audit all of them, or focus on specific files?" This gives the user control without requiring them to have assembled the inventory manually.
Step 0b: Orphan detection checkpoint
Before running the full audit, do a quick pass to identify token usage:
- Declared tokens — count every token found in Step 0 (or provided manually in Step 1).
- Referenced tokens — search the codebase for references to each declared token. For CSS custom properties, search for
var(--token-name). For SCSS variables, search for$variable-nameoutside their declaration files. For JSON/DTCG tokens, search for alias references ({token.path}). For TypeScript objects, search for import and access patterns (tokens.color.primary,theme.spacing.md). - Orphaned tokens — tokens declared but never referenced anywhere in the codebase.
Produce a checkpoint summary:
Orphan detection:
- 232 tokens declared
- 189 tokens referenced (at least once)
- 43 tokens orphaned (declared but unreferenced)
Top orphans: --color-legacy-teal, --spacing-xl-deprecated, $font-heading-alt (3 more)
This tells the user the scale of the problem before the full audit begins. Orphaned tokens are maintenance burden without value — they clutter autocomplete, confuse new team members, and inflate the token count. Include orphaned tokens as findings in the main audit (category: Coverage, severity: Low unless count exceeds 20% of total, then Medium).
If the orphan count is high (>30% of total tokens), flag this prominently: "Over a third of declared tokens are unreferenced. Before auditing token quality, consider whether a cleanup pass would simplify the architecture."
Step 1: Gather the token source
If Step 0 discovered token sources, use them as the primary input — skip the manual question unless the user wants to override. If Step 0 found nothing (or was skipped because no codebase access was available), ask for the token source. Acceptable inputs:
- A JSON, YAML, or DTCG-formatted token file
- A Figma file or Tokens Studio export
- A pasted list of token names and values
- A Style Dictionary configuration
- A CSS file with custom properties (e.g.
:root { --color-primary: #5e4890; }or theme variants scoped to.dark { },[data-theme="dark"], or similar selectors) - An SCSS/Sass file with variables (e.g.
$color-primary: #5e4890;) - A TypeScript or JavaScript token object (e.g.
export const tokens = { color: { ... } }) - A Tailwind CSS configuration file (
tailwind.config.jsortailwind.config.ts) with athemeorextendblock defining custom tokens
Format-specific guidance:
For CSS custom properties: treat each -- prefixed property as a token. Infer tier from naming patterns — properties like --color-blue-500 are likely primitives, --color-action-primary are semantic, --button-background-default are component-tier. Where properties are scoped to selectors (:root, .dark, [data-theme="dark"]), treat each scope as a theme variant. References between CSS custom properties using var(--other-token) indicate tier relationships — map these the same way as JSON token references.
For SCSS variables: treat each $ prefixed variable as a token. SCSS variables that reference other variables (e.g. $color-primary: $blue-500) indicate tier relationships. If variables are split across partials (_colors.scss, _spacing.scss), the file organisation may signal tier structure.
For TypeScript/JavaScript objects: treat the exported object's key hierarchy as the token structure. Nested objects map to tiers the same way JSON tokens do. For Emotion or styled-components themes, the theme object is the token source. Common patterns include: flat exports (export const backgroundColor = { scene: '#FFF', primary: '#206EF6' }), as const typed objects (const tokens = { ... } as const), aggregated barrel exports (export const tokens = { breakpoint, fontSize, spacing }), and theme-to-CSS-variable mapping functions (mapThemeToVars()). Helper functions like mapSpacing() or packs.underline that resolve to token values are valid token references.
For Tailwind configurations: the theme block defines primitives, extend adds semantic overrides. Tailwind utility classes that reference custom tokens (e.g. bg-primary, text-color-content-default) are token references, not hardcoded values. Arbitrary values in square brackets (e.g. h-[12px], bg-[#ff0000]) are the actual hardcoded violations.
If the person pastes raw token names without values, proceed with a naming and structure audit only. Note in the output that value analysis was not possible.
Step 2: Map the tier structure
Identify which tiers are present:
Primitive tier — raw values, no semantic meaning. Examples: color.blue.500, spacing.4, font-size.base
Semantic tier — intent-driven references. Examples: color.action.primary, spacing.component.gap, text.body.size
Component tier — scoped to a specific component context. Examples: button.background.default, card.padding.inner
Flag if any tier is missing. A system with only primitives has no semantic contract. A system with only semantic tokens has no single source of truth for raw values. Both are structural problems worth naming.
Step 3: Run the audit checks
For each check, produce a PASS, WARN, or FAIL rating with specific examples.
Naming checks
Descriptive vs prescriptive naming Semantic tokens should describe purpose, not appearance.
- FAIL example:
color.semantic.blue— describes colour, not intent - PASS example:
color.action.primary— describes role
Tier leakage Component tokens should reference semantic tokens, not primitives.
- FAIL example:
button.background.default: {color.blue.500}— skips the semantic tier - PASS example:
button.background.default: {color.action.primary}— correct reference chain
Ambiguity flags Token names that could mean multiple things or require context to interpret:
- Examples to flag:
default,base,normal,alt,variant,misc,other - Each flagged token should include a suggested rename
Platform suffix abuse Token names that encode platform specifics in the name rather than in the transformation layer:
- Examples:
color.primary.ios,spacing.mobile.gap— these belong in transforms, not names
Value checks (if values are available)
Hardcoded values at semantic or component tier Any semantic or component token with a raw value rather than a reference is structural debt.
- Flag each occurrence with: token name, raw value found, and suggested reference target
Duplicate raw values without token aliases Identical raw values appearing at the primitive tier under different names without explanation.
- Flag potential duplicates and ask whether the distinction is intentional
Out-of-tier references Any token referencing a token from a higher-specificity tier.
- Example: a semantic token referencing a component token — this inverts the dependency direction
Coverage checks
Missing interaction states Review whether semantic tokens exist for all standard states: default, hover, active, disabled, focus, error, success, warning.
Missing dark mode / theme aliases If the system intends to support theming, check whether semantic tokens exist as theme-aware aliases or whether raw values are used directly.
Inconsistent component tier (only if the system uses component tokens) If the system has adopted component tokens and they exist for some components but not others in the same category, flag the inconsistency. If the system does not use component tokens at all, this is not a finding — a two-tier architecture (primitives and semantics) is a valid and common choice.
Step 3b: DTCG 2025.10 alignment assessment (conditional — include only if relevant)
Skip this section entirely if the token source is not DTCG format and the team has not mentioned DTCG migration. Most teams don't need this. Include it when the token source uses DTCG format, when the team asks about DTCG compliance, or when migration planning is the purpose of the audit.
If the token source uses DTCG format, or if the team is considering DTCG migration, run these additional checks:
Type declarations. Check whether tokens include $type fields. DTCG 2025.10 requires one of 13 types: color, dimension, fontFamily, fontWeight, duration, cubicBezier, number, strokeStyle, border, transition, shadow, gradient, typography. Flag tokens without type declarations. Flag tokens with $type values not in the DTCG type list. Classification: tokens missing $type are WARN if the team is pre-DTCG (informational — count for migration estimate), FAIL if the team has declared DTCG adoption (these tokens break tooling interoperability).
Composite token integrity. For composite types (typography, shadow, border, transition, gradient), validate sub-value compliance. A typography token where fontSize is a hardcoded value ("16px") but fontFamily is a proper reference ({font.family.body}) is a partial violation — the composite is inconsistent. A typography token where all sub-values are hardcoded is a full violation — it cannot participate in theming. Report sub-value compliance rate per composite type. Example finding: TA-14 | WARN | Composite integrity | typography.body: fontSize hardcoded (16px), fontFamily references {font.family.body} — partial violation. Remap fontSize to {dimension.font.size.body}.
Resolver and set coverage. If .resolver.json files exist, validate that every semantic token has a value in every declared mode. A semantic token declared in a resolver but missing a mode-specific value is a FAIL — the system will fall back to the default mode unpredictably, which may produce incorrect contrast ratios or broken layouts in the mi
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: murphytrueman
- Source: murphytrueman/design-system-ops
- License: MIT
- Homepage: https://www.designsystemops.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.