Skip to content

What `loomctl` guarantees

Not what it does — --help says that, and the commands will change. This is what will keep being true while they do.


It grants no access, and records where the copy came from

Section titled “It grants no access, and records where the copy came from”

loomctl reads what your credentials already let you read. Everything it does is possible with copy and paste. It is a mast, not a lockthe point is to make the wrong thing deliberate, not impossible.

What it adds over a paste is provenance. A pasted document cannot answer “where did this come from, and were we allowed to have it” — not because the question is hard, but because the evidence is gone.

No push, no publish, no POST, no token that needs write scope. Every byte it writes is a file in your working tree. Committing and pushing are yours, because the consequences of a push land on people a tool cannot experience.

A credential given to loomctl should never carry write scope, and if one does, nothing here will use it.

Freshness is a conditional request against the publisher’s ETag

Section titled “Freshness is a conditional request against the publisher’s ETag”

Stored verbatim, opaque, never a hash we compute. A fetch that normalises anything breaks a local digest and reports a change that did not happen.

This is externals’ rule and loomctl is a second holder of it. It is stated here so that the tool holding it is a fact somebody can find, and so that breaking it is visible rather than silenta specimen was written in this repository that computed a hash instead, and it was wrong within a day.

The URL in a lock is resolved. A short form follows whatever the default branch is at the time you ask, so a branch rename would report as a change in the document.

Nothing is overwritten. A document that moved upstream is written to a staging area as a candidate, and taking it is a separate act. A local copy that differs from what the publisher serves is left aloneit is the only evidence that something changed while nothing was watching.

add adopts what is absent and refuses what is already adopted. A document that is present but unlocked is locked only when the bytes are identical to what the publisher serves, so a lock’s claim — this copy is the one being served — is verified rather than assumed.

.loom/externals/.locks, one record per adopted document, tab-separated, ordered by path.

path <TAB> url <TAB> etag [ <TAB> visibility ]
  • pathrelative to .loom/externals/, and for a person to read. It does not round-trip to a URL; it drops the route, the branch, and the publisher’s .loom/published/.
  • urlthe resolved origin, branch and all.
  • etagthe publisher’s, verbatim, including its quotes.
  • visibilityoptional. What the source could be read as when it was fetched: public or not-public. Never privatean anonymous request tells those two apart and nothing finer.

Records with three fields remain valid. A repository does not stop working because the tool learned something new.

The command surface. Names, flags and output are --help’s business and may change. Nothing should parse them.

The generated orientation file’s format. It is byte-deterministic within a version so that its diff is readable; it is not stable across versions.

That visibility is precise. The signal distinguishes public from not-public and nothing finer, so it cannot see two repositories private to different people — which is the case where adopting between private repositories genuinely widens access. The tool says so where it reports it, rather than implying a verdict it has not earned.

That anything is checked when you are not looking. Nothing here runs on a schedule, and a document nobody checks is a document nobody is checking.

What is promised about the things that are not promised

Section titled “What is promised about the things that are not promised”

The command surface may change. This page will say when it does.

A consumer whose README tells a person to type loomctl external add loom/<repo> <doc>.md depends on that command by name — not by parsing it, which is why no check would ever catch a rename. The thing that moved would not be a document they adopted.

So the exclusion is narrower than “you are on your own”. We do not promise the surface holds; we promise that a change to it lands here, on a page you can lockand a lock on this page reports 200 the day a command is renamed.

That is the whole mechanism, and it costs one section:

Append-only, newest last. Nothing yet — the commands have not been renamed since this page existed.


Verified fetchable by somebody who is not us on 2026-09-08.

This page is a copy of a document published by loom/loom-cli, rendered here. The source is https://git.hypertheory-labs.dev/loom/loom-cli/raw/branch/main/.loom/published/guarantees.md and is what the copy is checked against.

What of ours depends on it: .loom/externals/git.hypertheory-labs.dev/loom/loom-cli/guarantees.usages.md