patties add --diff / patties update
The copy-in model's single biggest weakness is upstream drift: once a
Purpose
The copy-in model's single biggest weakness is upstream drift: once a component is stamped into the user's repo they own it, but they lose the ability to see how the catalog source moved on. shadcn answers this with diff / add --diff. patties has no update/diff path (matrix §1 diff, §2 --diff — both gap); the cli-add spec deferred it to "phase-5". With the full 60-component catalog now shipped, the matrix ranks this the highest-leverage remaining gap ("Gaps worth an RFC" #1). This spec promotes it.
Usage
patties add --diff <component> # show diff: stamped file ← catalog template
patties add --diff # diff every stamped component against the catalog
patties update <component> # re-stamp, overwriting, after showing the diff
patties update --all # update every stamped component
patties update --dry-run # show what would change, write nothing
--diff is read-only. update is the apply side; it reuses the stamper with force: true but gated behind a shown diff.
What "upstream" means here
patties has no remote registry (see [[cli/15-registry-distribution]]); the source of truth is the installed patties-ui package resolved via Bun.resolveSync("patties-ui/registry", cwd) (load-catalog.ts:20). So "upstream" = the template that ships with the currently installed patties-ui version. Updating patties-ui (bun update patties-ui) then running patties update is the drift-reconciliation loop, analogous to shadcn pulling newer registry source.
Behavior — --diff
- Load the catalog (
loadCatalog). For each selected component, resolve itsfiles[](fromintemplatesDir,toin the resolvedcomponentsDir). - For each file pair: using
Bun's text APIs; color via the existing ANSI helpers, plain when stdout is not a TTY.- destination missing → report
not stamped(skip;--diffnever stamps). - identical → report
up to date. - differ → print a unified diff (catalog as "incoming", local as "current"),
- destination missing → report
- Also diff
_internal/helpers andtokens.cssfragments the component declares (internalHelpers,tokens) so users see helper/token drift, not just the component file. - Exit
EXIT.OKalways (diff is informational); a--checkmodifier exits non-zero when any drift exists, for CI ("fail if components are stale").
Behavior — update
- Run the same diff and print it.
- Re-stamp the differing files with
force: true(reusingapplyStamp), re-merge tokens, stamp any newly-required helpers, and patch any newly-required peer deps. - Files the user has locally edited are still overwritten — that is the point of
update, and matches--forcesemantics. The shown diff is the safeguard; users commit before updating. A future--3wayis out of scope. --dry-runprints the plan and writes nothing (parity withadd --dry-run,add.ts:107).
Production guard
Both inherit the patties add guard: NODE_ENV=production → EXIT.USAGE (add.ts:34).
Acceptance criteria
- After
patties add button, editing the localbutton.tsx,patties add --diff buttonprints a unified diff and exitsEXIT.OK. patties add --diff buttonon an unmodified, current component printsup to dateand produces no diff body.patties add --diff(no name) diffs all stamped components and ignores ones not yet stamped.patties add --diff --checkexits non-zero iff at least one stamped component differs from the catalog — usable as a CI drift gate.patties update buttonoverwritesbutton.tsxwith catalog source and merges any new tokens/helpers; re-running is a no-op (up to date).patties update --dry-runwrites nothing.- Diffs are colorized on a TTY and plain when piped.