Skip to content
React 19No peer dependencies

Updating components

Edit the components you copy in, then update them safely: add never overwrites an edited component, and doctor shows what you changed, what the new version changes, and which call sites an update would break.

Found something wrong, or missing? Open an issue on the bug tracker.

On this page

Components are copied into your project so that you can change them. The moment you do, you have a fork — and a fork needs two things a package manager never had to provide: a guarantee that updating will not destroy your changes, and a way to see what an update would actually do to your code.

What add does with a component that is already there

npx @grampro/kit add Button
  • Untouched since it was installed — it is updated in place.
  • Changed — it is left alone. add names the files that differ, prints how to see more, and exits with status 1. The component is still installed and still works; nothing was removed.
code
✗ Button was not replaced: it has changes made since it was installed.
    changed: react/Button.tsx
  See what you changed and what 2.7.2 changes:  npx @grampro/kit doctor Button
  Replace it anyway, losing those changes:      npx @grampro/kit add Button --force

Other components in the same command are still installed or updated. Only --force replaces a changed component, and it discards your changes when it does.

Before 2.7.2, add replaced an already-installed component unconditionally and reported success, including when it held your edits. If you have run add on a component you had changed, check it with doctor.

doctor

npx @grampro/kit doctor              # every installed componentnpx @grampro/kit doctor DatePicker   # just onenpx @grampro/kit doctor --json       # the same report, for scripts and agents

It compares three versions of each component: the one you installed, your copy as it is now, and the one this version of the CLI carries. It compares them as contracts — props, the values a prop accepts, handlers, exports and agent operations — rather than as text, because a text diff shows which lines moved but not what breaks. Then it reads your source for the places you use the component.

code
Doctor · src/component-lib/ · kit 2.7.2

  Button        your changes · conflict with 2.7.2
    files       changed core/types.ts, react/Button.tsx
    yours       ! prop size: removed
                ! prop variant: values removed "ghost"
                + prop tone  "info" | "warn"
    upstream    ! prop size: values removed "xl"
                + prop variant: values added "link"
    conflict    prop size: you removed; upstream values removed
    merges      prop variant → "danger" | "link" | "outline" | "primary" | "secondary"  (both edits combine)
    would break src/App.tsx:3  <Button tone>
    choices     keep your copy (nothing to do), or replace it with 2.7.2
                and lose your changes: npx @grampro/kit add Button --force

  Switch        untouched · 2.7.2 available, but it breaks call sites below
    upstream    ! prop legacyColor: removed
    would break src/Settings.tsx:3  <Switch legacyColor>
    update      npx @grampro/kit add Switch

  Up to date: DatePicker

It never writes anything.

Reading the report

LineMeans
filesFiles changed, deleted or added since the component was installed.
yoursWhat your edits changed in the component's contract. "No contract changes" means you changed the implementation only.
upstreamWhat the newer version changes, measured from the version you installed.
conflictYou and upstream changed the same thing incompatibly — for example, you removed a prop that upstream changed.
mergesYou both changed the same thing, but compatibly. For a set of accepted values, the combined set is shown.
would breakCall sites in your code that pass something the replacement would not accept.

! is a change that can break a caller, ~ one that changes behaviour without breaking callers, + something new.

would break covers both directions. An untouched component whose new version drops a prop you use is listed, and so is an edited component whose call sites depend on a prop you added — because replacing it with --force would take that prop away.

Components installed before 2.7.2

From 2.7.2, every install records what was written: a hash of each file and a copy of the contract, in .install-manifest.json inside the component's folder. Commit it with the component.

Components installed earlier have no such record. If one is unchanged, it is recognised from its passport and updated normally, and gets a record from then on. If it differs from the current version, there is no telling an older untouched copy from an edited one, so add keeps it and doctor reports it as may contain your changes, comparing it with the current version instead.

For agents and CI

doctor --json gives the full report — every change, conflict, merge and affected call site, plus a verdict per component.

The MCP server's install_component follows the same rule as add. When it keeps an edited component it returns the component under kept, with the reason, and the agent skill tells agents not to retry with --force. An agent asked to "install Button" has not been asked to discard the Button you already changed.

TypeScript

Comparing contracts reads your edited components with the TypeScript compiler API. Without TypeScript in the project, doctor still reports which files changed and what upstream changed, and says that the rest needs TypeScript.

TypeScript 7 does not provide that API. If your project uses TypeScript 7, install TypeScript 6 alongside it under another name — your build keeps using 7:

npm i -D typescript-6@npm:typescript@6