Skip to content

loom-cli

A fetcher and a comparator. It adopts a document you depend on, records where the copy came from, and later asks the publisher whether theirs has moved.

The tool arrived after the documents it manages, which turned out to be the useful way to meet it.

Eight documents, and a tool that would not guess

Section titled “Eight documents, and a tool that would not guess”

loom-cli had adopted eight documents by hand, months of prose fetched with curl into the right directory. The first thing the tool ever said about them was this:

Terminal window
$ loomctl external check
git.hypertheory-labs.dev/loom/annotating/annotating.md unlocked no origin recorded — `loomctl external add <url>` supplies it without rewriting this copy
git.hypertheory-labs.dev/loom/bedrock/loom-directory.md unlocked no origin recorded — ...
git.hypertheory-labs.dev/loom/bedrock/publication.md unlocked no origin recorded — ...
git.hypertheory-labs.dev/loom/bedrock/starting.md unlocked no origin recorded — ...
git.hypertheory-labs.dev/loom/cart/cart.md unlocked no origin recorded — ...
git.hypertheory-labs.dev/loom/externals/externals.md unlocked no origin recorded — ...

unlocked means I cannot tell you. There was an obvious thing to do instead — fetch each document and adopt whatever etag came back — and the tool refuses to, because that would assert the local copy is the one being served, which is the exact thing it was about to check. On a copy somebody had edited, it would have been wrong and silent.

That refusal is not visible as a feature. It is only visible as an artifact: six lines that decline to answer.

Supplying the origin, without an overwrite

Section titled “Supplying the origin, without an overwrite”

The path does not round-trip — .../loom/bedrock/starting.md has dropped the route, the branch, and the publisher’s .loom/published/ — so nothing but you can say where a hand-fetched copy came from. Say it once:

Terminal window
$ loomctl external add loom/bedrock starting.md
locked git.hypertheory-labs.dev/loom/bedrock/starting.md
from https://git.hypertheory-labs.dev/loom/bedrock/raw/branch/main/.loom/published/starting.md
etag "7d997a30248a88c90b23f2f9453d7cfceb03848e" (bytes verified identical; nothing was rewritten)

locked, not adopted. The bytes decide: identical, so the lock’s claim is verified rather than assumed, and not one byte of the local copy is rewritten. If they had differed, the copy would have been left exactly where it was, because a copy that differs is the only evidence that something moved while nothing was watching.

Eight documents locked. Then, on a Sunday afternoon, this:

Terminal window
$ loomctl external check
git.hypertheory-labs.dev/loom/cart/cart.md same
git.hypertheory-labs.dev/loom/externals/externals.md CHANGED staged as a polad; git.hypertheory-labs.dev/loom/externals/externals.usages.md names what to fix
1 staged in .loom/cart/current/polad — apply or discard; nothing here drifts into being kept.

The document had gained a section that afternoon. Nobody had said so, and nobody in this repository would have found out.

Two things in that line are doing work. The new copy is staged, not applied — it is a candidate, and taking it is a separate act:

Terminal window
$ loomctl external apply
applied git.hypertheory-labs.dev/loom/externals/externals.md
check git.hypertheory-labs.dev/loom/externals/externals.usages.md names what depends on this

And the staged copy carries the etag it was served with, so applying locks the bytes somebody actually read rather than whatever the publisher is serving by then.

The second is the pointer to the .usages.md. Reconciliation runs the other way: the question is not what do we rewrite here, it is given what changed in theirs, what do we change in ours — and the facets usually survive untouched. What moves is the code a usage named. When there is no such file, the tool says so, which is a finding rather than an omission:

CHANGED staged as a polad; no .usages.md — nothing records what depends on this

It never writes over the network. It has no push, no publish, no token that needs write scope. Everything it writes is a file in your working tree, and committing is yours.

It does not repair. check reports; apply is a person taking a candidate one document at a time.

It grants no access. Everything it does is possible with copy and paste — it is a mast, not a lock. What it adds over a paste is that the copy can answer where did this come from, and were we allowed to have it, which a pasted document cannot, because the evidence is gone rather than because the question is hard.

And it does not run when you are not looking. Nothing here is scheduled. A document nobody checks is a document nobody is checking.

Terminal window
$ go build -o loomctl . && ./loomctl --help
$ loomctl external list loom/bedrock # what a repository publishes
$ loomctl external add loom/bedrock starting.md
$ loomctl external check # safe anywhere; it only reads

The guarantees page is the contract: what will keep being true while the commands change, the lock file’s format, and — the part worth reading first if you are reimplementing this — what is deliberately not promised.