Shadcn Sync
SkillDev toolsRun and reconcile the shadcn component sync (`bun run shadcn:update`). Use when refreshing shadcn components, or when a sync regresses a local customization or breaks the build.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Shadcn Sync skill
What this skill tells your AI
The instructions your AI receives, as published by nrjdalal/zerostarter in .agents/skills/shadcn-sync/SKILL.md and read by ahel’s review.
bun run shadcn:update tears the whole ui/ layer down to the registry and re-applies every local override programmatically. It is self-reconciling: a clean tree goes in, a clean tree comes back. The only diff you should ever see is the residual, a genuine upstream change to a component.
Under the hood the command is bash .github/scripts/shadcn-update.sh && bun i. The script, from web/next, runs rm -rf components.json src/components/ui -> shadcn init -> shadcn add -a; then, at repo root, .github/scripts/shadcn-customize.ts -> bun run format (oxfmt). The trailing bun i belongs to the wrapper, not the script: it reconciles the lockfile after customize.ts restores it from HEAD.
Procedure
- Run on a clean tree:
bun run shadcn:update. It refuses on a dirty blast radius, so commit or stash first. - Review
git diff; expect it empty. Every non-empty hunk must be a real registry change to a component, never override churn. - Type-check:
cd web/next && bun run build(orbun run check-types), which covers every.tsx, including unused ones likecalendar.tsx. Must pass. - Commit only the residual registry deltas.
What shadcn-customize.ts reconciles
Two strategies. Each guard is idempotent and throws when its target is absent, so an upstream shape change fails loudly rather than silently dropping an override.
Restore from HEAD (RESTORE list), files the sync re-scaffolds but we own outright:
bun.lock+web/next/package.json+ rootpackage.json:add -arewrites deps offcatalog:to pinned ranges, and adds every dependency a registry item declares to the root catalog even when no component imports it (calendardeclaresdate-fns;react-day-picker10 needs no such peer). The rootcatalogis the source of truth, so reset all three to HEAD. A dependency a component really needs still surfaces: step 3's type-check fails, and the catalog is bumped by hand, as #796 did for@shadcn/react.web/next/src/app/layout.tsx:initinjectsnext/font/google; we self-host instead (see thefontsskill).web/next/src/lib/utils.ts:initdrops the repo helpersslugifyandisActive(and internalgenerateId).
Patch in place, registry components we extend, located by AST shape with ts-morph (so attribute or param reordering can't break them) plus one guarded string swap for CSS:
button.tsx, Base UI render wiring (render,nativeButton={!render},render={render})checkbox.tsx, the indeterminate state: Base UI setsdata-indeterminate(neverdata-checked), so the registry's check-only indicator paints a partial selection identically to a checked one. Fills the box ondata-indeterminateand swaps the glyph to a minus. The guard tests for the patch before the target, since the swapped-in ternary still contains the<RiCheckLine />it replaced.spinner.tsx,React.ComponentProps<RemixiconComponentType>typingsidebar.tsx, optionalchildrenlabel onSidebarTriggerglobals.css,--font-sansrepointed at the brand DM Sans variable (--font-dm-sans), and both--sidebarlines (:root+.dark) flushed tovar(--background)(PR #566)
calendar.tsx carries no override and tracks the registry as-is (we pin react-day-picker to ^10; the registry component is v10-compatible).
Notes
- Add overrides only through
shadcn-customize.ts, never by hand, becauseadd -aoverwritesui/every run. Extend theRESTORElist, or add a fail-loud ts-morph patch (or guarded CSS string swap). add -are-adds ALL components, so unused ones (calendar.tsx,chart.tsx, …) reappear every run. That is expected; do not delete them to chase a dead-code report.
Signals
- GitHub stars
- 63
- Forks
- 11
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
shadcn-sync- Source
- github.com/nrjdalal/zerostarter