Skip to content

Migrate · 3 of 3

Keep it up to date

Copying a component is the easy half. The hard half is a year later, when a bug in it has been fixed upstream and your copy has not. This is how you find out, how you look at the change, and how you take it without losing your own edits.

The loop

terminal
# 1. what has moved on since you installed it (reads only)
npx hoverlab outdated

# 2. what actually changed in one of them
npx hoverlab diff pricing-tiers

# 3. take it — but look first
npx hoverlab update pricing-tiers --dry-run
npx hoverlab update pricing-tiers

All three read hoverlab.lock.json, which npx hoverlab add wrote when you installed. No lockfile, nothing to compare, and the commands say so rather than guess.

outdated: what changed

terminal (revisions are illustrative)
! 1 of 3 have changed in the catalog:

  pricing-tiers (block)
    3fa9c01b7d2e -> 8b17d4e02c9a  ·  updated 2026-08-12

See what changed: hoverlab diff pricing-tiers
Nothing has been written. Your copies are untouched.

outdated never writes and has no fix flag, deliberately. It compares one fingerprint per artifact, and a fingerprint difference says the catalog’s file changed — not that yours did not. Overwriting on that evidence would be the most destructive thing this CLI could do, so it does not.

A tracked id that is no longer in the catalog is listed separately as not found; it may have been renamed or retired. For CI, add --json:

terminal
npx hoverlab outdated --json
# { "tracked": 3, "outdated": [ { "id", "level", "from", "to", "updated" } ], "unknown": [] }
outdated exits 0 whether or not anything is stale, so a CI step has to read the JSON to fail on it. For example, with jq (not part of Hoverlab): npx hoverlab outdated --json | jq -e '.outdated | length == 0'

diff: what the change is

diff prints the changed lines between your copy and the catalog’s current one, for each file that artifact installed. It ignores line-ending differences, so a file that a Windows checkout turned to CRLF is not reported as changed from top to bottom. It writes nothing. There is no --json for it; use outdated --json for machines.

update: taking it safely

update is not the fix flag outdated refuses to have. It asks a different question, one the lockfile can answer: is your file byte-for-byte what the CLI wrote? If so, replacing it destroys nothing. If not, it leaves the file alone.

SituationWhat update does
File matches its recorded hashReplaces it with the catalog’s copy and re-records the revision and hashes.
You edited it — or a formatter or a line-ending conversion didRefuses that artifact, says has local changes, and points at diff. Other artifacts are unaffected.
It was installed before hashes were recordedRefuses: it cannot tell whether you edited it.
The file is gone from diskCounts as blocked, like an edited one. Only --force writes it back.
Any one file of an artifact is blockedWrites none of that artifact’s files. Half an update compiles, runs and is wrong in a way nobody thinks to look for.
--forceOverwrites the blocked files too. For when you know your edits are disposable.
--dry-runPrints the same report and writes nothing.

With no ids, update takes everything outdated lists. Name ids to take only those.

a blocked update
! pricing-tiers not updated:
    components/pricing-tiers.tsx has local changes
    See what would change: hoverlab diff pricing-tiers
    Or overwrite anyway: hoverlab update pricing-tiers --force

The merge is yours. A three-way merge on a component you have restyled is a judgement call about which of two intentions wins, and neither the CLI nor a hash can make it.

Things the lockfile does not know about

Only add records. A template from init, anything from npx shadcn add, and anything copied by hand are invisible to outdated. To see the current source next to yours, without the lockfile:

terminal
npx hoverlab show pricing-tiers

show prints the catalog’s code and writes nothing; compare it in your editor. To bring an unedited copy under tracking, npx hoverlab add pricing-tiers --force rewrites it with the catalog’s current copy and records that revision. On a file you have not edited that is an update; on one you have, it is a real overwrite, so commit first.

The revision ledger

Behind outdated is one public endpoint, with no key:

terminal
curl 'https://hoverlab5.netlify.app/api/v1/revisions?level=block&ids=pricing-tiers'

It returns version, generatedAt, count and an artifacts map of { level, revision, updated? } per id. updated is present where the catalog can state the date precisely. The CLI asks for the whole ledger, not for your ids, so the request does not reveal what you installed. The mechanism, in the order you meet it:

  1. Every artifact carries a revision. A content fingerprint per effect, block, page and template, derived from the source rather than from a version somebody remembers to bump.
  2. It is a public endpoint, with no key. /api/v1/revisions returns the whole ledger. Your lockfile never has to tell us which forty things you installed.
  3. The CLI reads your copy against it. npx hoverlab outdated lists what has moved since you installed it, with the date it changed; hoverlab diff <id> shows the lines.
  4. Applying it is your call, always. Nothing reaches into your repo and nothing phones home. The file is yours — this only tells you it is not the newest one.

The revision is derived from the file bodies alone. Retitling a block or adding a tag does not move it, so a stale-copy notice means the source changed, not the marketing.

We have not audited every vendor above for this, so the table has no column for it. What we can say is what we do.

What the twelve-month window covers

The window belongs to the commercial licence, and its wording is the licence’s, quoted rather than paraphrased:

  • Perpetual and irrevocable for anything already shipped. A refund or a lapsed subscription never reaches back into work you have delivered.
  • Twelve months of catalog updates from the date of purchase. Everything published in that window is yours permanently, whether or not you renew.
  • Subscriptions include updates for as long as they are live — there is no separate window.
  • When it ends. The licence certificate on your account shows the date beside the issue date.
  • Renewing. A renewal buys another twelve months, added to whatever is left, so renewing early costs you nothing. It appears on the certificate as the window runs out.
  • The commands are not tied to it. outdated, diff and update do not ask for a key or check a date; they work the same on every machine.

Full terms are on the licence page, and how the ledger compares with other catalogs, with dates on every row, is on the comparison page.

What leaves your machine

  • outdated fetches the whole ledger and compares locally.
  • diff and update fetch the artifacts you name, so the server sees those ids.
  • add reports the ids it installed, for the catalog’s popularity ranking, and nothing else about your project. HOVERLAB_NO_TELEMETRY=1 switches that off.

None of them writes to your repo except add and update, and update only where it can prove the file is untouched.

Something wrong or missing here? Browse the catalog — every page in it links back to the source it documents.