Skip to content
Back to skills

Token Audit

ASecurity

Scan CSS files (and component TS/TSX colour literals) for hardcoded values that should use design tokens, and report violations — including near-twins of existing tokens. Use when asked to check for hardcoded values, raw colours or pixel values, or audit token usage and design system compliance.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added November 6, 2026
developmenttypescriptgogit

Security analysis

A100/100

Scanned November 11, 2026

npx -y skills add robritacca-dotcom/rift-ds --skill token-audit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Token Audit?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Token Audit
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/robritacca-dotcom-token-audit/badge)](https://www.skillsdirectory.com/skills/robritacca-dotcom-token-audit)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: token-audit
description: Scan CSS files (and component TS/TSX colour literals) for hardcoded values that should use design tokens, and report violations — including near-twins of existing tokens. Use when asked to check for hardcoded values, raw colours or pixel values, or audit token usage and design system compliance.
icon: manage_search
displayDescription: "Scans CSS files for hardcoded hex colours, raw rgb() values, pixel values, and transition timings that should reference design tokens, plus component TS/TSX files for colour-shaped literals. Flags near-twins of existing tokens as their own finding class. Reports file, line number, offending value, and recommended token replacement. Accepts a single component, all-components, or website as scope."
invoke: ["check for hardcoded values","token audit","audit [component] CSS","are there raw colours"]
---

# token-audit

Scan CSS files for hardcoded values that should use design tokens, and report violations.

## When invoked

Use this skill when asked to check for hardcoded values, audit token usage, find raw colours or pixel values, or check design system compliance — phrases like "check for hardcoded values", "token audit", "are there any raw colours", "audit [component] CSS".

## What is already automated

`scripts/validate-token-usage.mjs` already fails the build on any `var(--…)` reference to a custom property nothing defines, so unresolvable-token references need no hand-check; this skill hunts for raw values that never reference a token at all. `scripts/validate-action-colour.mjs` fails it on a component that starts using `--color-action-primary-bg` without a sanctioned role, but its `SANCTIONED` table is per component, not per selector: a decorative use added inside a component already listed passes the build, so that residue is this skill's to catch. Two more categories are fully build-enforced and need no hand-check: media-query widths (`scripts/validate-breakpoints.mjs` holds every `@media` width, and every media-query string in TypeScript, to the breakpoint set) and z-index (`scripts/validate-stacking.mjs` requires a `--layer-*` token for any value of 10 or more). A value either one accepts under a `ds-allow(breakpoint)` or `ds-allow(stacking)` directive is sanctioned, not a finding. Over the library's own stylesheets (`src/components`, `src/chat`), `scripts/validate-raw-values.mjs` now fails the build on the plain strays too: literal colours, motion timings, font sizes, line heights, letter spacing, font weights, and off-scale padding, margin, gap and radius, unless a directive covers them. For library scope this skill's remaining job is judgement the script cannot make: near-twins, the right replacement token, a directive whose reason no longer holds, icon sizing done through `font-size`, and a row control's `height` or `min-height` written as a literal that matches a `--control-height-*` step (40px or 32px in the base theme), which the script does not check: a control that shares a row takes the token, so it moves with the density lever and lines up with its neighbours. Website CSS is outside the gate and still fully this skill's.

## Instructions

1. **Determine scope.** Accept one of:
   - A specific component name (e.g. `Avatar`) → scans `src/components/Avatar/Avatar.css`
   - `all-components` → scans all `src/components/**/*.css` and the chat widget's stylesheets, `src/chat/*.css`
   - `website` → scans all `website/src/**/*.css` (which includes the `.module.css` files)
   - A specific file path

   **The site background is outside every CSS scope, and deliberately so.** Its blob colours are token *names* in `website/src/data/shader-background.json`, resolved at runtime and handed to the GPU — no CSS file names them, so a `website` scan will pass without ever looking at what actually picks the site-wide background palette. Do not hand-audit it: `scripts/validate-shader-background.mjs` already fails the build if any blob references a token that is not in the registry, which is a stronger guarantee than this skill can offer. The scene half of that palette lives beside it: with a scene picked from the header, the background's colours are the `--color-ambient-*` roles each scene lists in `src/components/ShaderScene/scenes.ts` (the `SITE_BACKGROUNDS` rows in `website/src/lib/shaders/background-storage.ts` carry only params), and `scripts/validate-site-backgrounds.mjs` holds every row's scene, params and the scenes' colour roles to what exists. Say so in the report rather than leaving a reader to assume the surface went unexamined.

   **The chart series palette is the second out-of-CSS surface.** `src/components/Chart/palette.ts` emits `var(--color-chart-series-N, <light-theme hex>)` references that SVG paint resolves live — so charts follow a theme switch — and the literal hexes are cascade fallbacks, deliberate and not violations. Do not hand-audit those either: `scripts/validate-token-references.mjs` fails the build if a fallback stops matching what its token resolves to. Nor is the chart palette the only guarded mirror — the mirror checks in `scripts/validate-token-references.mjs` and `scripts/validate-theme-mirrors.mjs` are between them the authoritative list of out-of-CSS token surfaces (the hand mirrors split across the two scripts), and a new mirror lands in one of them, not here. Mention the shader background and those scripts' mirrors in the report the same way, so no reader assumes those surfaces went unexamined.

2. **Read the token files in `src/tokens/` first** to know what tokens are available and what raw values they map to — primitives (raw hex/px), the light *and* dark semantic files, typography (font size, weight, line-height), and motion (`tokens-motion.css` — durations and easings; its JS-side counterpart, the shared constants in `src/tokens/motion.ts`, is outside this skill's CSS scope). The fastest authoritative index of names is the **generated** `src/tokens/registry.json` — every semantic token with its category, machine-readable (never edit it — it regenerates from the CSS). It holds no values: for what each token resolves to per theme and breakpoint, read the generated `website/public/skill/rift-design-system/references/tokens.md`, which `scripts/token-values.mjs` resolves from the token CSS on every build, instead of following `var()` chains by hand.

3. **Scan each CSS file** in scope for violations:

   **Flag as violations:**
   - Hardcoded hex colours: `#rrggbb`, `#rgb`, `#rrggbbaa`
   - Raw `rgb()` or `rgba()` calls that could map to a semantic colour token
   - Pixel values for `padding`, `margin`, `gap`, `border-radius`, `font-size`, `line-height` that correspond to a known token (cross-reference the primitives file)
   - Hardcoded font weights (e.g. `font-weight: 600`) where a typography token exists
   - Icon sizing done wrong: `font-size` set directly on a Material Symbols icon, or raw pixel icon dimensions matching an `--icon-size-*` step — the fix is setting `--icon-size` to a step from the `--icon-size-*` scale (`src/tokens/registry.json` is the list; the icon font reads that one property for size, width, and height)
   - Hardcoded `transition`/`animation` durations and easings (`0.2s`, `ease`, literal cubic-beziers) where a `--motion-duration-*`/`--motion-ease-*` token matches — component and website CSS is fully migrated, so any literal timing is a violation unless a directive sanctions it

   **Do NOT flag:**
   - Files within `src/tokens/` themselves (these define the tokens)
   - `0px`, `0`, `100%`, `50%` — these are structural, not token-replaceable
   - **Any value sanctioned by a `ds-allow` directive** — the one and only signal that an off-token value is deliberate. `/* ds-allow(<category>): <reason> */` inside a comment covers the declaration/rule/section it sits at; `/* ds-allow-file(<category>): <reason> */` in a file header covers the whole file for that category. Enumerate the current sanctions with `grep -rn "ds-allow" src website/src --include='*.css'` (the same scope `validate-css-directives.mjs` scans); the category set and grammar are build-enforced by `scripts/validate-css-directives.mjs`. This skill deliberately names no components: an off-token value with **no** directive is a violation, and the fix is either a token or a new directive at the site (plus a design.md note) — never an exception added to this skill
   - `1px` border widths — acceptable
   - Values inside `calc()` that are genuine arithmetic, not replaceable with a single token
   - CSS variable declarations themselves (lines starting with `--`)

   **Hunt near-twins, not just strays.** A raw value that is *almost* an existing token is a typo recorded as a decision, and the legality check alone never sees it — it can even sit under a `ds-allow`. Compare every collected raw value against the resolved values in the generated token reference (step 2) **and against the other raw values in scope**: a colour within a few points per channel of a token (including cross-notation twins — a hex, an `hsl()`, and an `rgb()` of the same colour are one value written three ways), or a spacing value one pixel off a neighbouring scale step. Report a near-twin as its own finding class, distinct from a plain stray, naming what it is a twin of — `path/to/GadgetTile.css:17 — #0E6D8E → near-twin of var(--color-action-primary-bg), probably a mistyped copy` (a fictional example by design — `GadgetTile` is not a real component). A twin of a token is repaired by pointing at the token; a twin pair of raw values collapses into whichever one is sanctioned.

   **Component TS/TSX files are in scope for colour-shaped literals.** The CSS glob is not the whole surface: hex, `rgb()`/`rgba()`, and `hsl()` literals also live in component `.ts`/`.tsx` files (under `src/components/` and `src/chat/` alike), where no `ds-allow` mechanism exists. Scan them too, and judge each hit against the mirror checks in `scripts/validate-token-references.mjs` and `scripts/validate-theme-mirrors.mjs` (between them the authoritative list of sanctioned out-of-CSS token surfaces — the chart palette, every `getCSSVar` fallback, and the remaining hand mirrors split across the two). A literal outside those mirrors is a finding to judge, not skip — deliberately theme-frozen fixture data can be legitimate, but a near-twin of a token in it is still a typo.

4. **For each violation**, output:
   - File path (relative to repo root)
   - Line number
   - The offending value
   - Recommended token replacement (if a clear match exists in the token files)

   Format (fictional values): `path/to/file.css:42 — #7A1F3D → var(--color-gadget-accent-bg)`

5. **Summarise** at the end:
   - `X violation(s) found`
   - `Y acceptable raw value(s) noted (documented exceptions)`
   - If zero violations: "No token violations found. CSS is token-compliant."

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in development →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.