Facetguides

Updating copied components

There is no `facet upgrade`. What `diff` and `remove` can tell you, and what they cannot.

The copy-in model means Facet can never push an update: a component in your project is a file in your repository, and nothing reaches back into it. What the CLI offers instead is visibility.

facet diff

Terminal window
npx facet-rbxts diff # every installed component
npx facet-rbxts diff button # one

Compares each copied file against what the registry would write there today. It replays the ~/ rewrite first, so your project’s alias and directory choices are not reported as changes.

The direction is registry → project. - is what the registry has and + is what your file says, so applying the + side is what “keep mine” means.

A component in the registry that is not in your project is reported and skipped.

Taking an upstream change

There is no command for this, and that is the model working as intended:

  1. facet diff button — see what moved.
  2. Decide. Most upstream changes to a component you have edited are not worth taking.
  3. If you want it, facet add button --overwrite replaces the file wholesale and your edits are gone. Commit first, then reapply what you want from the diff.

--overwrite is deliberately blunt: there is no three-way merge, because there is no base text to merge against.

facet remove

Terminal window
npx facet-rbxts remove badge
npx facet-rbxts remove badge --force

Two refusals, and they are not the same kind of refusal.

A file that differs from the registry is refused without --force. “Differs” is the closest stand-in for “you changed this”, and it also fires when only upstream moved. In the worst case you are asked about a file you never touched. That is the safe direction to be wrong in.

A component another installed component still imports is refused, and --force does not cover it. Deleting utils out from under an installed button leaves a project that does not compile.

That second check runs to a fixed point, which matters more than it sounds:

Terminal window
npx facet-rbxts remove button utils

If button turns out to be modified and stays, utils is still imported — and a single pass would already have cleared it. The plan is recomputed until nothing changes.

Directories are left alone, and so is anything you added next to the removed files.

Why there is no lock file

A facet.lock of per-file content hashes is the obvious fix for what diff cannot say, and it was dropped. A hash answers whether a file differs, not how. Showing that needs the text you started from, which means a second copy of every component committed to your repository. It also goes stale for reasons that are not edits: a formatter pass, a rename, a move.

Pinning a registry revision

The default registry moves. https://facet.astra-void.xyz/r is republished on every push to Facet’s main, so an edit reaches everyone immediately. That includes a project that ran facet add months ago and will next run facet diff.

Every push also writes an immutable copy under the commit that produced it, and a project can point at one instead:

facet.json
{ "registry": "https://facet.astra-void.xyz/r/a1b2c3d" }

revisions.json lists what exists, newest first. add, diff, list and doctor all read the field and all print which registry they used.

What pinning fixes: facet diff stops reporting upstream movement. Against a frozen revision a difference is your edit or nothing — most of what the lock file was supposed to buy.

What it does not fix: it is per-project, not per-component — “this project builds against that registry”, not “button came from that revision”. And a pinned project stops receiving fixes until someone moves the pin.

What revisions genuinely unlock is that the base text becomes something the CLI could one day fetch rather than something you store. That is not implemented.

What to actually do

  • Commit the copied files. They are source, not build output.
  • Do not expect updates. If a component is a starting point you rewrote, diff will be noisy forever — stop running it on that component.
  • Run facet doctor after upgrading anything. It catches a project set up by an older CLI: copied files current, versions under them not.