ctx repair
ctx repair checks every page ctx has synced before, and for each one whose base snapshot is missing or no longer matches, fetches the right version from the server and records it again. It also corrects page shas that older servers or ctx builds recorded wrongly. Your working files are never changed.
When you’d reach for it
Section titled “When you’d reach for it”Rarely by hand. Online ctx status, ctx pull and ctx push run the same repair automatically, over the server listing they fetch anyway. ctx repair is for doing it on demand, all at once, and seeing the result:
ctx statuslists pages underUNVERIFIEDand suggestsctx repair.ctx show --at basefails withbase_unavailableand the advicectx repair.- You just upgraded from a ctx version that kept no base snapshots, or an older ctx or
ctx mcpprocess (an agent session started before the upgrade) has been rewriting.contexo/.sync/state.jsonbehind the new one.
Status gives its automatic repair at most 20 seconds and skips it when another ctx process holds the lock, so a large project can stay partly unverified after a status. ctx repair waits for the lock instead.
ctx repair is a ctx-only command. The VS Code extension never calls it: repair is an optional capability in ctx version --json, and the extension relies on the automatic repair instead.
Synopsis
Section titled “Synopsis”ctx repairctx repair --dry-runctx repair --json| Flag | Type | Default | Description |
|---|---|---|---|
--dry-run | bool | false | report what would be repaired; write nothing |
--json | bool | false | emit the ctx.repair.v1 JSON document |
--dry-run makes exactly the same server reads and reports the same result, but writes nothing.
--json prints a ctx.repair.v1 document (see Output below) and turns failures into the one-line error envelope described in JSON output and exit codes.
| Flag | Type | Default | Description |
|---|---|---|---|
--root | string | project root directory (default: current directory) |
What it fixes
Section titled “What it fixes”A page needs repair when .contexo/.sync/state.json records a sha for it, but the base snapshot for that sha is missing, belongs to another sha, or has been edited since it was written. For each such page ctx fetches the server’s version at the recorded sha and decides:
- Your file already equals the server version. ctx adopts it: that version becomes the base, at the commit the server reports for it.
- An older base for the page is still intact. This is the case of an older binary that moved the page’s recorded sha to a teammate’s version after a push conflict, without merging anything. ctx keeps the older base and points the recorded sha back at it (reason
kept_previous_base). If your file differs from that base and the server has moved past it, it also records a conflict, so your next push cannot silently overwrite the teammate’s version: you settle it withctx resolveinstead. - Otherwise the server version becomes the base.
Whenever the commit the server reports differs from the one recorded, the recorded sha is corrected. The usual cause is the old server bug that recorded the repo’s HEAD instead of the page’s own last commit (reason path_sha_fixed).
Working files are never written. Only .contexo/.sync/ changes, in this order: base files, conflict files, bases.json, conflicts.json, then state.json. Just before writing, ctx re-reads state.json; a page whose recorded sha changed meanwhile (an older binary takes no lock) is skipped with state_changed.
How many requests it makes
Section titled “How many requests it makes”Repair is careful with the server’s rate limit, which teammates and agents behind the same network share:
- Pages whose recorded sha is still the one in the server listing are read from the current version: a single bulk request when there are more than 8 of them, otherwise one read for each.
- Every other page needs the server’s history (the
pages.atserver capability). Repair makes at most 50 of these history reads per run, at most 4 at a time. - The first failure that is not about one page (a 429 rate limit, a network or server error, a rejected token) stops all requests not yet started.
Pages left over are reported as skipped, not as an error: budget_exhausted past the 50-read budget, the failure’s code (for example rate_limited) after a stop, or server_unsupported when the server cannot read history at all. Run ctx repair again to continue: each run picks up the pages still unverified. The human summary prints a “run again” hint when the budget ran out.
Output
Section titled “Output”The human summary is one line of counts, then one line per repaired page with its old and new sha and the reason, then the skips grouped by reason. When nothing needs repair it says so.
With --json, the ctx.repair.v1 document has these keys, in this order:
| Key | Holds |
|---|---|
schema |
"ctx.repair.v1" |
dry_run |
whether --dry-run was passed |
server_capabilities |
the capabilities the server advertised in its response headers |
backfilled |
pages whose base was written at their recorded sha: path, sha |
repaired |
pages whose recorded sha changed: path, old_sha, new_sha, reason (path_sha_fixed or kept_previous_base) |
skipped |
pages left alone: path, reason |
unverified |
the paths of the skipped pages |
warnings |
a base_repair_skipped warning when anything was skipped |
Every array is present and never null. Skipped pages still exit 0.
Examples
Section titled “Examples”Upgrading an older project left it with no base snapshots at all, and one page whose recorded sha was the repo’s HEAD rather than its own commit. A dry run first:
ctx repair --dry-run✔ Dry run: would backfill 3, repair 1, skip 0 (nothing written)
wiki/concepts/webhook-retries.md a4b2c1d3 → 7d25c6bf path_sha_fixedThe same repair for real, as JSON. Three bases were backfilled at the shas already recorded; the fourth page’s sha was corrected to its own commit:
ctx repair --json{
"schema": "ctx.repair.v1",
"dry_run": false,
"server_capabilities": [
"pages.at",
"push.expect_absent",
"write.path_sha"
],
"backfilled": [
{
"path": "wiki/concepts/stripe-subscription.md",
"sha": "a4b2c1d3e5f60718293a4b5c6d7e8f9012345678"
},
{
"path": "wiki/entities/billing-worker.md",
"sha": "3b8e1a0947c2f6d85e90a1b2c3d4e5f60718293a"
},
{
"path": "wiki/entities/invoice-service.md",
"sha": "e5a3b9c807162534435261708f9e0d1c2b3a4958"
}
],
"repaired": [
{
"path": "wiki/concepts/webhook-retries.md",
"old_sha": "a4b2c1d3e5f60718293a4b5c6d7e8f9012345678",
"new_sha": "7d25c6bf018a3e4d5c6b7a8990f1e2d3c4b5a697",
"reason": "path_sha_fixed"
}
],
"skipped": [],
"unverified": [],
"warnings": []
}The command’s own help text:
ctx repair --helpRepair finds every synced page whose base snapshot under .contexo/.sync is missing or
no longer matches, fetches the base from the server and records it. It also fixes page
shas that older servers or ctx builds recorded wrongly (the repo HEAD instead of the
page's own commit). Working files are never changed. Pages it cannot verify are
reported as skipped; with --dry-run it makes the same reads and writes nothing.
Usage:
ctx repair [flags]
Flags:
--dry-run report what would be repaired; write nothing
-h, --help help for repair
--json emit the ctx.repair.v1 JSON document
Global Flags:
--root string project root directory (default: current directory)How it works
Section titled “How it works”- Checks that
.contexo/exists, then resolves the server, token and repo id. No credentials isnot_authenticated(exit 4 with--json); norepo_idisrepo_not_configured(exit 5). - Takes
.contexo/.sync/lock, waiting up toCONTEXO_LOCK_TIMEOUT(default 10 seconds), then fails withbusy(exit 12). - Lists the repo’s pages once and reads the server’s capabilities from that response.
- Finds the pages that need repair, fetches what they need within the budget above, and decides each one.
- Unless
--dry-run, writes the result, then prints the summary or the document.
Common errors
Section titled “Common errors”With --json the exit codes are 0, 4, 5, 7, 8 and 12 (plus 1 and 3). Without --json, any failure is a message and exit 1.
busy (exit 12): another ctx process, often an agent’s push or pull, held the lock past CONTEXO_LOCK_TIMEOUT. Run it again when that finishes.
network, server_error or rate_limited (exit 7) on the listing: the repair never started. These are retryable. A failure after the listing does not fail the command; it shows up as skipped pages.
repo_not_found (exit 8): the server has no repo with that id. Check repo_id with ctx remote.
not_authenticated (exit 4), server_unresolved or repo_not_configured (exit 5): see ctx login and ctx remote.
See also
Section titled “See also”ctx status: where unverified pages show upctx show: the command that needs a valid base for--at base- Drift and conflicts: base snapshots and why they matter
- JSON output and exit codes: the error envelope and exit codes
