Build a Component Audit Skill for Claude Code
A Claude Code skill that audits every component in your library. Checks docs, props, accessibility, and token usage in one slash command.
What you will need
Installed and running in your terminal
React, Vue, Svelte, or web components in a src/components/ folder
To create the skill, run it on a real library, customize for your stack
Optional but the skill checks for stories if it is set up
Your component library has 87 components. Three of them are documented. Twelve use hardcoded hex codes. Nobody knows which ones have stories, which ones are accessible, or which ones still get used. Every quarter, someone says “we should really audit the library.” Every quarter, nobody does.
This guide gives you a Claude Code skill that walks every file in src/components/, checks five things, and outputs a single table you can paste into a doc, a Linear board, or your next design system review. Type /audit-components and the audit happens while you make coffee.
The SKILL.md
Copy this whole block into a new file.
---
name: audit-components
description: Audit every component in src/components/ for documentation,
semantic token usage, accessibility, prop types, and Storybook coverage.
Use when the user mentions component audit, library health, component
review, or runs /audit-components. Outputs a markdown table.
---
# Component Audit
You are auditing a component library. One component per row in the output
table. Be specific about what is missing. Quote file paths.
## Step 1: Discover components
Look at the project root. Identify the component directory in this order:
1. `src/components/`
2. `app/components/`
3. `packages/ui/src/`
4. `components/`
5. Check `package.json` for `"main"` or `"exports"` to find non-standard locations
Also detect the framework from file extensions and dependencies:
- React: `.tsx`, `.jsx`
- Vue: `.vue`
- Svelte: `.svelte`
- Web Components: `.ts` with `customElements.define`
A "component" is one of:
- A folder with an `index.{tsx,jsx,ts,vue,svelte}` and same-named file
- A standalone `Component.{tsx,jsx,vue,svelte}` file (PascalCase name)
Skip folders matching: `__tests__/`, `__mocks__/`, `node_modules/`,
`dist/`, `.next/`, `storybook-static/`.
## Step 2: Run five checks per component
### Check 1: Has a description
Look for a JSDoc block or framework equivalent above the component
declaration. Pass if any of these exist:
- JSDoc `/** ... */` with a non-empty description on the line above the export
- A `// ` comment of at least 10 words above the export
- TypeScript interface with `/** description */` on the props type
- Vue: `<docs>` block or comment at the top of `<script>`
- Svelte: comment at the top of `<script>`
Fail if the file starts with code and has no description anywhere.
### Check 2: Uses semantic tokens
Scan for hardcoded values. Fail on any of:
- Hex colors: `#[0-9a-f]{3,8}` (except in comments)
- RGB/RGBA: `rgb(`, `rgba(`
- HSL: `hsl(`
- Named colors in styles: `red`, `blue`, etc. inside style props or CSS
- Pixel values that are not `0` or `1px` (those can be intentional)
- Magic numbers in spacing (e.g. `padding: 13px`)
Pass only if all colors and spacing reference a token (CSS variable,
theme function, or token import).
### Check 3: Accessible
For interactive elements (`button`, `input`, `select`, `textarea`,
`a`, anything with `onClick` or `onPress`):
- Has `aria-label`, `aria-labelledby`, or visible text content
- Has `role` if it is a non-semantic element (`div`/`span` acting as a button)
- Form controls have associated `label` (htmlFor or wrapping)
- Images have `alt` (empty string is OK if decorative)
For non-interactive components (cards, layout), pass automatically unless
they contain interactive children that fail.
### Check 4: Prop types defined
- TypeScript: has an explicit `interface Props` or `type Props`,
not `(props: any)` or untyped destructure
- JavaScript: has `propTypes` defined or default props
- Vue: `defineProps()` with type
- Svelte: typed `export let` declarations
Fail if props are used inside the component but not declared anywhere.
### Check 5: Has a Storybook story
Check for these patterns alongside the component:
- `Component.stories.{ts,tsx,js,jsx,mdx}`
- `Component.story.{ts,tsx}`
- A `stories/` folder containing the component
If Storybook is not set up at all (no `.storybook/` folder, no Storybook
in `devDependencies`), skip this check entirely and add a single line at
the bottom of the report: "Storybook not detected, skipped story check."
## Step 3: Output
Write a single markdown table with this structure:
```markdown
# Component Audit
**Components scanned:** {count}
**Path:** `{components dir}`
**Framework:** {React | Vue | Svelte | Web Components}
## Summary
| Check | Pass | Fail | % |
|--------------------|------|------|------|
| Has Description | {n} | {n} | {%} |
| Uses Tokens | {n} | {n} | {%} |
| Accessible | {n} | {n} | {%} |
| Has Story | {n} | {n} | {%} |
| Prop Types Defined | {n} | {n} | {%} |
**Health score:** {average across all five checks} %
## Per-component results
| Component | Description | Tokens | A11y | Story | Props | Issues |
|-----------|-------------|--------|------|-------|-------|--------|
| Button | yes | yes | yes | yes | yes | none |
| Card | no | yes | yes | no | yes | Missing description, missing story |
| Modal | yes | no | no | yes | yes | 3 hex colors at L42, L51, L67. Missing aria-label on close button |
## Top fixes by impact
The five components with the most failed checks, ordered by how many
other files import them. Fixing these unblocks the most consumers.
1. `Modal` (4 fails, imported by 12 files)
2. `Card` (2 fails, imported by 9 files)
...
```
## Rules
- One row per component. Group by folder if there are sub-components.
- Quote line numbers when you flag a hardcoded value or missing label.
- Never silently skip components. If you cannot read a file, list it under
"Could not parse" at the bottom.
- If a component is marked `@deprecated` in JSDoc, exclude it from the
health score but still list it with a note.
## When to skip
- Files matching `*.test.*`, `*.spec.*`, `*.stories.*`
- Files inside `__internal__/` or directories starting with `_`
- Components with the comment `// audit:skip` at the top
How to install this skill
Personal:
mkdir -p ~/.claude/skills/audit-components
nano ~/.claude/skills/audit-components/SKILL.md
Team:
mkdir -p .claude/skills/audit-components
nano .claude/skills/audit-components/SKILL.md
git add .claude/skills/audit-components
git commit -m "Add component audit skill"
If your components live somewhere unusual (a monorepo, a separate package), consider also adding a .design-system/components.json with the path so the skill picks it up automatically:
{
"componentsDir": "packages/ui/src/components",
"framework": "react",
"storybookDir": ".storybook"
}
Example invocations
/audit-components
Run a component audit on this library
Check every component for token usage and accessibility
Which components are missing Storybook stories?
You can scope to a folder: /audit-components packages/ui/src/forms audits only the form components.
What it actually does
- Finds your components. It autodetects the components directory using common locations and your framework based on file extensions. No config needed for typical setups.
- Walks every component. One row per component, including nested sub-components. Skips tests, stories, mocks, and anything explicitly marked.
- Runs five checks per row. Description (JSDoc or top-of-file comment), token usage (no hex/rgb/named colors, no magic spacing), accessibility (labels and roles for interactive elements), prop types (typed interface or PropTypes), and Storybook coverage (story file exists).
- Builds a single table. Component name in the first column, five checks in the next five, issues summary in the last column.
- Adds a top-fixes list. Components are ranked by failed-checks count, weighted by how many other files import them. Highest-impact fixes first.
The whole audit on a 100-component library takes about a minute.
Customize for your team
Match your stack. If you use Lit, Stencil, or Qwik, add the framework detection to Step 1 and update the prop types check to match the framework’s conventions.
Add a documentation check. If your team writes docs in MDX next to components (e.g. Button.mdx), add Check 6:
### Check 6: Has MDX documentation
Pass if a `Component.mdx` or `Component.docs.mdx` exists alongside the
component file. Fail otherwise.
Tune the token rules. If your team allows certain hardcoded values (0, 1px, 100%, auto), document the allow-list in Check 2 so they do not get flagged.
Add a usage check. Cross-reference each component against the rest of the codebase. Components with zero imports get flagged as “candidate for deprecation.”
Add a visual regression check. If you use Chromatic or Playwright snapshots, add Check 7: “Has a baseline screenshot.”
Output format. Swap the markdown table for CSV or JSON if you want to feed the result into a dashboard.
What you get
- A repeatable health check that runs in under a minute on any component library
- A single-table format you can paste into a Notion doc, a Slack thread, or a Linear board
- A top-fixes list ranked by impact so you know exactly where to start
- A health score you can track over time
Run it before every release. Run it during onboarding so new designers see the gaps. Run it before pitching a refactor so you have the data, not vibes.
Common pitfalls
Skill flags valid hex inside primitive token files. If you keep raw hex values in tokens/primitives.json or colors.ts, the token check will scream. Add those paths to the skip list at the top of Step 1.
False fails on dynamic components. A button that gets its aria-label from a prop will fail static analysis. The skill should detect aria-label={...} as a pass, not just literal strings.
Storybook check is too strict. If your team uses CSF 3 with meta.title hierarchies, make sure the regex matches your file naming. Adjust Step 5 if you use index.stories.ts instead of Component.stories.ts.
Sub-components inflate the count. A Modal with Modal.Header, Modal.Body, Modal.Footer becomes four rows. If you want them grouped, add a rule: “Group exports from the same file as one row, list sub-components in parentheses.”
Health score that looks great but hides the truth. A score of 92% sounds good until you realize the failing 8% are your most-used components. Always read the top-fixes list, not just the score.
Install the skill and run it on your real component library
-
Create the skill file in your project
In your project root, create the skill file:
mkdir -p .claude/skills/audit-componentsThen create
.claude/skills/audit-components/SKILL.mdand paste the full SKILL.md body from this guide into it. Save..claude/skills/audit-components/SKILL.mdexists in your repo- The frontmatter block (
name,description) is at the very top of the file - Running
/audit-componentsin Claude Code is recognized as a skill, not a generic prompt
-
Run the audit and count the top three failures
In Claude Code, run
/audit-components. When the table lands, pick the three rows with the most “no” marks. Write them down. Then look at how often each of those three components gets imported across the codebase.- You have a markdown table with one row per component and five check columns
- The top three failing components are named, not vague (“Modal, DataTable, Dropdown”, not “a few components”)
- For each of the three, you know roughly how many other files import it
- The next pull request you open fixes one of the three, not a random component you saw first
Finished this lesson?
Mark it complete to track your progress through "Design System Automation".
The guides alone saved me a full day of work every sprint.
- All guides, prompts, and templates
- Starter kits and templates
- New content every week
- Priority support