The Cost of Owning the Code
Shadcn/ui makes source-level control practical, but control also exposes work that a package boundary can hide. This chapter diagnoses the main costs of owning installed code: why an update can become a merge problem, which checks belong before writing and which risks remain afterward, and how registry conflicts, authentication, availability, and health signals should be interpreted. The point is not to reject the model. It is to identify the boundary at which distribution ends and project judgment begins.
A failure in this system can look deceptively simple. A component has changed, an import no longer resolves, a theme looks wrong, or an installation cannot reach its registry. Those symptoms can have different causes. Treating every problem as a bad component or a broken CLI obscures the real ownership boundary. A useful diagnosis separates local source changes, project adaptation, dependency graphs, and registry operations before choosing a remedy.
A local update is a merge, not a download
The lifecycle begins when a registry item becomes local source. At that point, the project can edit it independently of the registry's future releases. That independence is the benefit of the open-code model, but it changes what an update means. A new registry version is not automatically a replacement for the current file. It is a candidate source that must be compared with local decisions.
Suppose a team changes a Button's focus ring, adds a product-specific variant, or adjusts a Dialog's close behavior. Later, the registry publishes a revised implementation. The CLI can fetch the new source and show a diff. It can also overwrite an existing file when asked. Neither action can know whether the local change was intentional, whether it should be preserved, or whether the new version changes an assumption in the surrounding code. The mechanical operation is available; the semantic merge remains a project task.
This is why the documentation recommends committing local work before re-adding or overwriting components and reviewing the result afterward. A clean version-control boundary makes the change reversible and makes the difference between upstream source and local adaptation visible. Without that boundary, an overwrite can be mistaken for an upgrade even though it may have discarded a design decision.
The same distinction applies to migrations. A migration can rewrite imports, icons, base colors, or RTL-related classes across local files. It is useful when the project has chosen to change a convention, but it is not the same as a neutral package update. It edits the project's owned source according to a known transformation. The team must still inspect the files that the transformation touched and verify that any local intent survived.
Lower-level dependencies follow another path. If a component wraps a primitive package, a fix to that primitive may arrive through the package manager without replacing the locally owned wrapper. That separation is one of the model's strengths: the project can keep its design-system layer open while receiving improvements below it.