$npx -y skills add strongeron/storybook-workbench --skill sb-inventoryAudit a React+Vite app for real-vs-slop components (by actual imports), the dominant design system, and real prop-value usage at call sites. Use for 'what components do I have', 'which are dead', 'audit this vibe-coded app'.
| 1 | # sb-inventory — ground truth, not trust |
| 2 | |
| 3 | Vibe-coded apps ship ~30% slop. This skill replaces "trust the AGENTS.md / CLAUDE.md / DESIGN.md" with |
| 4 | "see what's actually imported." Read `CONTEXT.md` for the real/vendor/dead/kind vocabulary. |
| 5 | (The dominant design system here comes from **code** signals, never from a doc. If a `DESIGN.md` |
| 6 | brief is present, `sb-health` cross-checks its claimed colors against the code — it drifts/lies the |
| 7 | same way an `AGENTS.md` does.) |
| 8 | |
| 9 | ## Run it |
| 10 | |
| 11 | ```bash |
| 12 | SKILL=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}} |
| 13 | CORE=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}} |
| 14 | "$SKILL/scripts/inventory-project.sh" # writes .storybook/project-inventory.json (atomic) |
| 15 | ``` |
| 16 | |
| 17 | The script is the ground truth — do NOT recompute by hand. Read the JSON and **cite its fields**. |
| 18 | For the known detector gotchas (what the discovery scripts get right vs. wrong across validation runs), |
| 19 | load `references/field-learnings.md` **only when a count looks surprising** (a 0, an outlier, a |
| 20 | suspected false orphan). **Do NOT load it** for a clean first-pass inventory whose numbers look right — |
| 21 | the JSON fields stand on their own. |
| 22 | |
| 23 | ## Report (read these fields, in this order) |
| 24 | |
| 25 | 1. **Stack** — `libraries` (react/vite/tailwind v4|v3/shadcn/radix/baseui/r3f). |
| 26 | 2. **Dominant design system** — `designSystem.dominant` (one of tailwind-v4/shadcn/dtcg/css-vars/ |
| 27 | none) + `mixed` flag. If `mixed` → tell the user the project is in transition; suggest `sb-health`. |
| 28 | 3. **The user's own components** — `components.realCount` / `deadCount` are **domain components |
| 29 | only**. Cite `components.real[]` (most-imported first) as the priority list for stories. |
| 30 | 4. **Vendor** — `components.vendorCount` + `byKind.vendor` = shadcn `components/ui/` primitives. |
| 31 | Call these out *separately*: "you also have N installed shadcn primitives — not your code, not |
| 32 | slop, don't write stories for them first." |
| 33 | 5. **Modules / support / scaffold** — `moduleCount` (`byKind.module` = types/helpers/hooks/utils/ |
| 34 | lib/api — non-component source), `supportCount` (`byKind.scaffold|support` = test/factory/mock + |
| 35 | SB init tutorial). All excluded from the headline AND the `real[]` most-imported list, so that |
| 36 | list is your prod **components**, not a `types.ts` that's imported everywhere. Mention if non-zero. |
| 37 | 6. **Tokens** — used vs orphan. **Stories** — `orphanStories` (stories importing a component that no longer |
| 38 | exists) AND **`components.storyCoverage`** — own components written vs. needed: `{real, storyFiles, |
| 39 | withColocatedStory, withStory, needsCount, needsStory[]}`. Read coverage from **`withColocatedStory`** |
| 40 | (own components with their *own* `<name>.stories.*`) and **`storyFiles`** (distinct story files that |
| 41 | exist) — those are the hard counts. **`withStory` is a loose upper bound**: it also counts a component |
| 42 | as covered when *any* story merely imports it (e.g. a dialog story importing a form to mock it), so it |
| 43 | over-reports — treat `withColocatedStory ≤ real_coverage ≤ withStory`. `needsStory[]` is the "stories |
| 44 | needed" worklist (the inverse of orphanStories); `refresh-usage.sh` keeps it current so `sb-stories` |
| 45 | can work down `needsStory[]`. |
| 46 | |
| 47 | **The fix that matters here:** the "real" list and headline are the user's authored components — |
| 48 | NOT 40 shadcn primitives, types, or helpers. That was the #1 inventory complaint; the `vendor`/ |
| 49 | `support`/`scaffold` buckets exist so the headline stays clean. |
| 50 | |
| 51 | ## Surface it as a story |
| 52 | |
| 53 | Scaffold the `ProjectInventory` wrapper so the agent + designer share the view: |
| 54 | |
| 55 | ```bash |
| 56 | "$CORE/scripts/scaffold-wrapper.sh" ProjectInventory # → .storybook/wrappers/ (+ icons.tsx) |
| 57 | ``` |
| 58 | |
| 59 | Title `Foundations/Inventory`. The wrapper reads the same JSON; no emoji (uses the shared icon set). |
| 60 | |
| 61 | ## Real prop usage (not just real-vs-slop) |
| 62 | |
| 63 | `importers` tells you a component is *used*; it does NOT tell you **which props/variants the app |
| 64 | actually renders**. A shadcn `Button` may declare 6 variants but prod only ships 2 — the rest are |
| 65 | catalog padding. Run the usage extractor after the inventory: |
| 66 | |
| 67 | ```bash |
| 68 | "$CORE/scripts/extract-component-usage.sh" # → .storybook/component-usage.json (atomic) |
| 69 | ``` |
| 70 | |
| 71 | Per component (own + shadcn primitives, key |