ctx resolve
ctx resolve settles one page that changed both on your machine and on the server. --ours keeps your working file and makes the next push publish it over your teammate’s version. --theirs replaces your working file with the server’s version, after saving a backup of yours.
When you’d reach for it
Section titled “When you’d reach for it”When ctx push reports a conflict, when ctx status lists a page under CONFLICTS, or when ctx pull skips a page with “conflicts with the server version”. Push and pull never pick a side for you; this command is how you pick one.
Neither option merges. If you want both sets of changes, merge by hand: look at the server version with ctx show <path> --at server, edit your working file until it holds what you want, then run ctx resolve <path> --ours and push. --ours means “my file, as it is now, is the new version”.
--theirs has a second use: it brings back a page you deleted locally. ctx status suggests it under DELETED LOCALLY.
Synopsis
Section titled “Synopsis”ctx resolve <relpath> --oursctx resolve <relpath> --theirsctx resolve <relpath> --ours --if-server-sha <sha>ctx resolve <relpath> --theirs --json| Flag | Type | Default | Description |
|---|---|---|---|
--if-server-sha | string | fail with stale unless the server is still at this sha | |
--json | bool | false | emit a JSON document |
--ours | bool | false | keep the local content, re-based onto the server version |
--theirs | bool | false | replace the local file with the server version |
Pass exactly one of --ours and --theirs. Neither, or both, is a usage error: with --json it is the usage envelope and exit 3; without --json it is a plain error message and exit 1, like every other failure in human mode.
--if-server-sha <sha> makes the command refuse unless the server’s current version of the page is still that commit. Use it when you looked at the server version (with ctx show --at server, or the remote.sha in ctx status --json) and want to be sure your decision still applies: if your teammate pushed again in the meantime, resolve fails with stale (exit 6) and changes nothing. The sha must be 7 to 64 hex characters and is compared in full, ignoring case. An abbreviated sha that merely prefixes the server’s sha counts as stale.
--json prints a ctx.resolve.v1 document instead of the one-line summary. This one comes from the real binary (paths and shas are test placeholders):
{ "schema": "ctx.resolve.v1", "path": "wiki/concepts/retry-policy.md", "strategy": "theirs", "previous_state": "conflict", "state": "unchanged", "base_sha": "0000000000000000000000000000000000000001", "file_written": true, "backup_file": ".sync/backup/wiki/concepts/retry-policy.md.20000101T000000Z", "warnings": []}base_sha is the server version the page is now based on. backup_file appears only when a backup was taken, and is relative to .contexo/. file_written is false for --ours, which never touches the working file.
| Flag | Type | Default | Description |
|---|---|---|---|
--root | string | project root directory (default: current directory) |
What each side does
Section titled “What each side does”--ours: keep your file
Section titled “--ours: keep your file”Your working file stays exactly as it is. ctx records the server’s current version as the page’s base and clears the recorded conflict. The page now shows as modified (or unchanged, if your file happens to equal the server version), and the next ctx push sends your content with the server’s version as its parent, so it lands on top of your teammate’s edit instead of being refused.
--ours is allowed only from a conflict (either kind) or from an unverified page with a valid working file. From any other state it refuses with not_resolvable (exit 9) and writes nothing. For example, --ours on a page that is only incoming (you never changed it) would silently revert your teammate’s change, so ctx will not do it.
--theirs: take the server’s version
Section titled “--theirs: take the server’s version”The working file is replaced with the server’s version, and that version becomes the base, so the page ends unchanged. If your file differs from the server’s bytes, it is first copied to:
.contexo/.sync/backup/<relpath>.<YYYYMMDDTHHMMSSZ>The timestamp is UTC. The file is read right before it is overwritten, so the backup holds whatever you last saved. A missing working file (a page you deleted locally, or one that exists only on the server) is created with its directories. A file that already equals the server version is not rewritten. When the file is written, index.md and tags.md are regenerated.
--theirs works from any local state, as long as the server has the page. On a page that is already unchanged it is a no-op that only drops a leftover conflict record, so running it twice never takes a second backup.
In both cases the page must exist on the server: if it does not, the result is page_not_found (exit 8).
Examples
Section titled “Examples”Take the server version of the worker page. Your previous file is kept as a backup, and the summary prints its full path:
ctx resolve wiki/entities/billing-worker.md --theirs✔ Took the server version of wiki/entities/billing-worker.md (3b8e1a0); your previous file is saved at ~/projects/acme-api/.contexo/.sync/backup/wiki/entities/billing-worker.md.20260728T091407ZKeep your version of the subscription page, on top of the server’s commit f0c47d2:
ctx resolve wiki/concepts/stripe-subscription.md --ours✔ Kept your version of wiki/concepts/stripe-subscription.md on top of server f0c47d2; now run ctx pushThen publish it. The push is now an ordinary edit of the server’s latest version, so it goes through:
ctx push --yesAbout to push 1 page(s) to acme-api:
[EDIT] wiki/concepts/stripe-subscription.md (~ Concepts)
Pushed 1 page(s); HEAD=a4b2c1d3The command’s own help text:
ctx resolve --helpResolve a conflicted page.
--ours keeps your working file and re-bases it onto the current server version;
run ctx push afterwards to publish it over the teammate's edit.
--theirs replaces your working file with the server version. A file that differs
is first saved under .contexo/.sync/backup/.
--if-server-sha refuses (stale) unless the server is still at that sha.
Usage:
ctx resolve <relpath> (--ours|--theirs) [flags]
Flags:
-h, --help help for resolve
--if-server-sha string fail with stale unless the server is still at this sha
--json emit a JSON document
--ours keep the local content, re-based onto the server version
--theirs replace the local file with the server version
Global Flags:
--root string project root directory (default: current directory)How it works
Section titled “How it works”- Checks the arguments with no I/O: the path rules (the same as
ctx show), exactly one strategy, and the form of--if-server-sha. A bad argument isinvalid_pathorusage(exit 3) in any project, logged in or not. - Checks that
.contexo/exists, then resolves the server, token and repo id the same way push and pull do. - Takes
.contexo/.sync/lock, waiting up toCONTEXO_LOCK_TIMEOUT(default 10 seconds) if another ctx process, often an agent’s push or pull, holds it. After that it fails withbusy(exit 12). - Reads the page from the server once, taking both its content and its sha.
- Applies
--if-server-sha, then classifies the page against that fresh server sha, taking any recorded conflict into account. - Writes, in this order: the backup and the working file (
--theirsonly), the base, then the indexes under.contexo/.sync/. The page’s conflict record is cleared.
resolve makes exactly one server read. It never lists the repo, never reads history, never repairs other pages’ bases, and never pushes: after --ours, publishing your version is a separate ctx push.
Common errors
Section titled “Common errors”With --json, every failure is a one-line envelope on stderr; without it, a message and exit 1. The exit codes with --json are 0, 3, 4, 5, 6, 7, 8, 9 and 12 (and 1 for an internal error).
not_resolvable (exit 9): the strategy does not apply to the page’s current state. details names the path, the state and the strategy. From the real binary:
{"schema":"ctx.error.v1","exit_code":9,"error":{"code":"not_resolvable","message":"resolve wiki/concepts/idempotency-keys.md --ours: the page is incoming, not a conflict","advice":[],"retryable":false,"details":{"path":"wiki/concepts/idempotency-keys.md","state":"incoming","strategy":"ours"}}}Run ctx status to see the real state. For an incoming page, ctx pull is what you want.
stale (exit 6): --if-server-sha did not match. details carries path, expected_sha and server_sha. Look at the new server version and decide again.
page_not_found (exit 8): the server does not have the page. There is nothing to resolve against; push it instead.
usage (exit 3, or exit 1 without --json): resolve: pass exactly one of --ours or --theirs, or a malformed --if-server-sha.
busy (exit 12): another ctx process held the lock for longer than CONTEXO_LOCK_TIMEOUT. details names its pid, host, command and start time. Retry once it finishes.
not_authenticated (exit 4), server_unresolved or repo_not_configured (exit 5): resolve always talks to the server. See ctx login and ctx remote.
See also
Section titled “See also”ctx show: look at the base and the server version before you choosectx push: publish your version after--oursctx status: which pages are in conflict- Drift and conflicts: how conflicts arise and the full by-hand flow
- JSON output and exit codes: the
ctx.resolve.v1document and the error envelope
