mcpField
S
shadcn-detection

shadcn-detection

github.com/fusengineDevelopment3441 installsUpdated 2w ago
Repository

About shadcn-detection

shadcn-detection is a project-analysis skill for developers and agents working with shadcn/ui. It combines an authoritative CLI check with weighted signals to identify Base UI, Radix, React Aria, mixed, or fresh-setup states before component work.

Key features

  1. 01Authoritative shadcn CLI probe
  2. 02Dependency and configuration scanning
  3. 03Source import and attribute analysis
  4. 04Package manager detection from lockfiles
  5. 05Base, Radix, Aria, mixed, or none verdict

Use cases

  1. 01Checking a project's shadcn/ui base before adding components
  2. 02Identifying mixed primitives that require migration
  3. 03Choosing base-specific component patterns

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/fusengine/claude-plugins --skill shadcn-detection

After installing, type/shadcn-detectionin Claude Code to confirm it loaded.

Details

From the project README
Detects which of the three shadcn/ui component bases a project uses: Base UI (`base`, default for new projects since July 2026), Radix (`radix`, fully supported) or React Aria (`aria`, added July 2026). Authoritative signal first (`shadcn info --json` -> `config.base`), then a 5-signal weighted scan: package.json dependencies, components.json's style prefix, source import patterns, data-attribute conventions (`data-state` vs `data-open` vs `data-entering`), and the lockfile-detected package manager.

Produces a Base UI / Radix / React Aria / Mixed (migration needed) / None (fresh setup) verdict that gates every downstream shadcn component or migration task.

shadcn Detection

Agent Workflow (MANDATORY)

Before detection, spawn agents in parallel, one Agent call each with a name:

  1. fuse-ai-pilot:explore-codebase - Scan project structure
  2. fuse-ai-pilot:research-expert - Verify latest primitive patterns

After: Use results to configure component workflow.


Overview

FeatureDescription
CLI probe (authoritative){runner} shadcn@latest info --json -> .config.base = base | radix | aria (plus .config.style, .components, .links)
Package scanDetect @base-ui/react, radix-ui / @radix-ui/*, react-aria-components
Config checkAnalyze components.json style prefix (base-*, radix-*/new-york, aria-*)
Import analysisScan source for import patterns
Attribute scandata-state= (Radix) vs data-open (Base UI) vs data-entering/data-placement (React Aria)
Package managerDetect bun/npm/pnpm/yarn via lockfile
BasePackageStyle prefixCompositionDocs
Base UI (default)@base-ui/reactbase-*render prop/docs/components/base/<name>
Radixradix-ui (legacy @radix-ui/react-*)radix-*, legacy new-yorkasChild/docs/components/radix/<name>
React Ariareact-aria-componentsaria-*Trigger wrapper (DialogTrigger > Button + Dialog), slot, onPress/docs/components/aria/<name>

Known cross-base dependencies (NOT a mixed project): radix-* Combobox imports @base-ui/react (Radix has no Combobox); Questionnaire and MessageScroller import @shadcn/react on every base; every current component imports cn from the cn package.


Critical Rules

  1. ALWAYS run detection before any component work
  2. CHECK all 5 signals for maximum accuracy
  3. HANDLE mixed state as migration case, never ignore
  4. CACHE result for session duration, no re-detection needed
  5. DETECT package manager via lockfile priority order

Architecture

project/
├── package.json            # Step 1: deps scan
├── components.json         # Step 2: style field
├── bun.lock|bun.lockb|pnpm-lock.yaml|yarn.lock|package-lock.json  # Step 5: PM
└── src/|components/|app/   # Step 3-4: imports + attrs

→ See detection-script.md for complete example


5-Step Detection Algorithm

Step 0: if components.json exists, {runner} shadcn@latest info --json gives the base directly; the weighted scan below confirms it and catches mixed projects.

StepSignalWeight
1package.json deps (@base-ui/react, radix-ui / @radix-ui/*, react-aria-components)40%
2components.json style prefix (base-*, radix-*/new-york, aria-*)20%
3Import patterns in source files25%
4Data attributes (data-state= / data-open / data-entering)15%
5Package manager (lockfile → bunx/npx/pnpm dlx/yarn dlx)-

Decision Table

Each base gets its own score (0-100).

ScoresResultAction
Only Base UI >50Base UIUse Base UI patterns (render)
Only Radix >50RadixUse Radix patterns (asChild)
Only React Aria >50React AriaUse React Aria patterns (trigger wrapper, onPress)
Two or more >0 (after discounting the known cross-base deps above)MixedMigration needed
All 0NoneFresh setup: init defaults to Base UI; pass -b radix or -b aria to choose

Best Practices

DO
  • Run detection BEFORE any component work
  • Check all 5 signals for accuracy
  • Handle "mixed" state as migration case
DON'T
  • Assume Radix (or Base UI, the new default) without checking
  • Skip components.json analysis
  • Ignore data-attribute signals
  • Count @base-ui/react from a Radix-style Combobox as a mixed project

Reference Guide

Concepts
TopicReferenceWhen to Consult
Radix Patternsradix-patterns.mdIdentifying Radix UI signals
Base UI Patternsbaseui-patterns.mdIdentifying Base UI signals
Algorithmdetection-algorithm.mdUnderstanding scoring logic, React Aria signals
Templates
TemplateWhen to Use
detection-script.mdRunning detection on a project

Comments

Markdown supported