From design-system-ops
Generates YAML index files (.ai/index/) for design system codebases: component inventory, relationship graph, summary stats. Enables fast AI agent queries on components and dependencies.
npx claudepluginhub murphytrueman/design-system-opsThis skill uses the workspace's default tool permissions.
A skill for generating a pre-computed, machine-readable index of a design system's codebase. The index contains three pieces: a component inventory, a relationship graph, and summary statistics. Together they form a queryable map that eliminates the need for AI agents or developers to explore the codebase from scratch every time they need to understand the system.
Audits design system component libraries for usage signals, complexity, duplication, and coverage gaps, producing tiered findings, inventory, and prioritized recommendations.
Indexes codebases instantly with zero-dep skeleton (<4s), tree-sitter AST graph in SQLite, Mermaid architecture diagrams, and smart context for 95% token compression in AI analysis.
Generates structured design inventory for frontend sources—tokens, components, screens, features—via code analysis, Playwright inspection, or hybrid. Captures snapshots for design gap analysis with inventory.md and screenshots.
Share bugs, ideas, or general feedback.
A skill for generating a pre-computed, machine-readable index of a design system's codebase. The index contains three pieces: a component inventory, a relationship graph, and summary statistics. Together they form a queryable map that eliminates the need for AI agents or developers to explore the codebase from scratch every time they need to understand the system.
When an AI agent needs to work with a design system codebase, it has two options: explore or navigate. Exploration means scanning directories, grepping for imports, reading files one by one. Navigation means loading a pre-computed index and reasoning over cached data.
The difference matters. Exploration is slow, incomplete, and non-deterministic. An agent scanning src/components might miss components in src/layouts, src/pages, or utility directories that don't follow naming conventions. It might report a deeply-nested component as "unused" because it can't trace the dependency chain. It might recreate an existing component because it didn't find it.
A pre-computed index front-loads this cost. The agent loads the index once — typically a few thousand tokens — and gets a complete picture of what exists, where things live, and how they relate. Follow-up questions become cheap because the agent reasons over cached data instead of triggering new file reads.
This skill generates that index. Run it after adding or removing components, and commit the output alongside the code.
Before producing output, check for a .ds-ops-config.yml file in the project root. If present, load:
system.framework — pre-selects framework detection (React, Vue, Svelte, Astro, Angular, etc.)system.component_paths — overrides default component directory scanningsystem.category_model — atomic design, functional, or custom categorisationintegrations.* — enables auto-pull for component datarecurring.* — enables comparison with previous indexIf integrations are configured in .ds-ops-config.yml, pull data automatically:
Figma MCP (integrations.figma.enabled: true):
integrations.figma.file_keyStorybook (integrations.storybook.enabled: true):
integrations.storybook.url/index.jsonGitHub (integrations.github.enabled: true):
gh api search/code to count import references across consuming repositoriesIf an integration fails, log it and proceed with manual scanning.
Scan the project root to determine:
src/components/, src/lib/, components/, packages/, and any paths in tsconfig.json or framework configatoms/, molecules/, organisms/), functional (forms/, navigation/, feedback/), flat, or monorepo packagesAsk for or confirm (skip questions already answered by config or detection):
utils/ directory with reusable UI primitives)internal/ directories, components not re-exported from barrel files)Framework detection rules:
| Signal | Framework |
|---|---|
.jsx / .tsx files with JSX returns | React |
.vue files with <template> blocks | Vue |
.svelte files | Svelte |
.astro files | Astro |
.component.ts with @Component decorator | Angular |
customElements.define() | Web Components |
| Mixed signals | Ask the user |
For every component file found, extract:
.metadata.ts, .metadata.json, description in Storybook, JSDoc/TSDoc block, or Figma description)What counts as a component:
Category assignment:
uncategorised and flag for manual reviewProduce the inventory in YAML for readability and token efficiency:
components:
Button:
path: src/components/atoms/Button/Button.tsx
category: atoms
metadata: true
Card:
path: src/components/molecules/Card/Card.tsx
category: molecules
metadata: true
DataTable:
path: src/components/organisms/DataTable/DataTable.tsx
category: organisms
metadata: false
For every component in the inventory, trace two relationships:
How to trace relationships:
uses Button and Button usedBy CardDeep tracing rules:
uses: [] (empty) are leaf nodes — they have no internal dependencies on other system components. These are the terminal nodes in the graph.usedBy: [] (empty) are root nodes — nothing else in the system depends on them. If they're also not used directly in pages, they're orphan candidates.Instance counting: Import count and instance count are different metrics. A page might import Button once but render it five times. Instance counting requires parsing templates, not just import statements.
<ComponentName tags in templates/JSX for instance counts<slot /> and someone writes <Button><Icon /></Button>, the Icon instance belongs to the parent scope, not to Button's internals. Don't recurse into slot content for instance counting.relationships:
Card:
uses: [Text, Button, Icon]
usedBy: [ProductCard, UserProfile]
Button:
uses: [Icon]
usedBy: [Card, Form, Nav, Modal, Dialog, Header]
Icon:
uses: []
usedBy: [Button, Card, Nav, MenuItem, Alert]
Tooltip:
uses: []
usedBy: [CopyButton]
CopyButton:
uses: [Tooltip]
usedBy: [CodeBlock]
This format makes dependency chains explicit. An agent reading this graph knows immediately that Tooltip is actively used (by CopyButton, which is used by CodeBlock) even though no page imports Tooltip directly.
Compute aggregate metrics that give an at-a-glance picture of system health:
summary:
totalComponents: 55
componentsWithMetadata: 54
relationshipsMapped: 302
categories:
atoms: 18
molecules: 15
organisms: 12
templates: 4
pages: 6
orphanedComponents: 2
mostDependedOn:
- name: Icon
fanIn: 14
- name: Button
fanIn: 11
- name: Text
fanIn: 9
highestFanOut:
- name: Header
fanOut: 8
- name: ProductCard
fanOut: 6
metadataCoverage: 98%
averageInstancesPerComponent: 9.6
Key metrics to compute:
uses arrays)uses: [] and usedBy: [] — these are standalone and may be unusedGenerate three output files to be committed alongside the codebase:
component-inventory.ymlThe full component inventory from Step 2.
component-relationships.ymlThe full relationship graph from Step 3 plus the summary statistics from Step 4.
query-protocols.mdA markdown file with instructions for how to use the index. This file teaches AI agents (or developers) how to read the map:
# Query protocols
When answering questions about the design system codebase:
1. Check the index first. Before reading any source file, check whether the
answer exists in component-inventory.yml or component-relationships.yml.
2. Never re-read relationship files. If the relationship graph has already
been loaded in this session, reason over the cached data.
3. Follow-up questions should be cheap. After the initial index load,
subsequent questions should require zero or minimal file reads.
## Common query patterns
### "What components exist?"
→ Read component-inventory.yml. The full list with paths and categories.
### "Where is [Component] used?"
→ Check component-relationships.yml → relationships → [Component] → usedBy.
### "What does [Component] depend on?"
→ Check component-relationships.yml → relationships → [Component] → uses.
### "Is [Component] actually used?"
→ Check usedBy. If usedBy is non-empty, it's used. If usedBy is empty,
check whether it appears in any page or layout file directly.
### "What atoms appear on [Page]?"
→ Trace the dependency chain: Page → imports → their imports → ...
until you reach components with uses: []. Those are the atoms.
### "If I change [Component], what breaks?"
→ Follow the usedBy chain recursively. Direct consumers are in usedBy.
Indirect consumers are the usedBy of those consumers. Continue until
you reach page/layout level.
### "Should I create a new component for [pattern]?"
→ Check the inventory for existing components that might serve the need.
Check relationships to understand composition options. A new component
is warranted only if no existing component or composition covers it.
Default output location: .ai/index/ in the project root. This keeps the index files co-located with the codebase and clearly namespaced.
.ai/
index/
component-inventory.yml
component-relationships.yml
query-protocols.md
Recommend to the user:
If recurring.enabled: true in config, compare the new index against the previous one and produce a delta report:
This delta is valuable for tracking system evolution over time and catching unintentional structural changes.