ctx pull
ctx pull downloads pages that changed on the server since your last pull, writes them into .contexo/, and regenerates the local index.
When you’d reach for it
Section titled “When you’d reach for it”Pull at the start of a session, before you or your agent start editing pages — that’s what keeps a push from turning into a conflict later. Pull again when ctx status reports drifted pages, or when a push comes back with a 409.
The thing to internalise: pull is a fetch-and-overwrite, not a merge. It writes the server’s bytes over your local file with no three-way merge, no prompt and no backup. If a page has both local edits you haven’t pushed and server edits you haven’t pulled, pulling loses your side. Push first (or copy the local version aside), then pull.
Synopsis
Section titled “Synopsis”ctx pullctx pull --full| Flag | Type | Default | Description |
|---|---|---|---|
--full | bool | false | ignore last_pull_sha and fetch everything |
--full ignores the last_pull_sha recorded in .contexo/.sync/state.json and asks for everything tracked at the server’s HEAD, rewriting every page rather than only the changed ones. Reach for it when the local .contexo/ has been edited by hand, partially deleted, or restored from somewhere else and you want a known-good copy of the whole knowledge base.
ctx pull also accepts the global flag:
| Flag | Type | Default | Description |
|---|---|---|---|
--root | string | project root directory (default: current directory) |
Examples
Section titled “Examples”The normal incremental case — everything committed on the server since your recorded sha:
ctx pullPulled 1 page(s); HEAD=a4b2c1d3Re-fetch the entire knowledge base regardless of what the local sync state says:
ctx pull --fullPulled 1 page(s); HEAD=a4b2c1d3When the server’s HEAD already matches your recorded sha, pull prints Already up to date and writes nothing — but it still advances last_pull_sha if the server’s HEAD moved for reasons that produced no file changes.
How it works
Section titled “How it works”- Reads
repo_idand the server URL from.contexo/config.json, the bearer token from.contexo/credentials.json. Aserver_urlin credentials takes precedence over the one in config. GET /v1/repos/<repo>/sync/pull?since=<last_pull_sha>, with the headerX-Contexo-Client: ctx-cliso the server can attribute the read. With--fullthesinceparameter is omitted.- Server side,
sinceresolves togit diff --name-only <since> HEADfor the incremental case, or the fullHEADtree whensinceis empty. Each path is read at HEAD and returned with the sha of the last commit that touched it. Apullevent is recorded in the repo’s activity feed only if at least one file came back. - Each returned file is written to
.contexo/<path>, creating directories as needed, and its sha is recorded in.contexo/.sync/state.jsonunderpage_shas. That recorded sha is theparent_shayour next push will send for that page, and the baseline the drift check compares against. last_pull_shais set to the server’s HEAD..contexo/index.mdand.contexo/tags.mdare regenerated from everything now on disk, so the always-loaded index reflects the pages you just received. A failure here printswarning: reindex: …on stderr but does not fail the command.
Common errors
Section titled “Common errors”pull: no credentials, run 'ctx auth login' first — no .contexo/credentials.json. Run ctx login.
pull: no server URL configured (run 'ctx remote add') — the message names a subcommand that doesn’t exist; the real one is ctx remote set <url>. See ctx remote.
pull: no repo_id configured in .contexo/config.json — run ctx remote set-repo <id>.
pull: open hub: … (did you run 'ctx init'?) — no .contexo/ in this directory. Check your location or pass --root.
sync: pull failed (403): {"error":"not a member of this repo"} — your token authenticates, but you aren’t a member of that repo. Membership is checked before the repo is looked up, so a typo’d repo_id lands here too, not on a 404. Ask an owner for an invite key and run ctx join, or fix the id with ctx remote set-repo.
sync: pull failed (404): {"error":"repo not found"} — you passed the membership check but the server has no git repo under that id. Repos are created by their first push.
See also
Section titled “See also”ctx push— the other half of the loop; pull is the fix for its 409ctx status— tells you whether a pull is neededctx_pull— the MCP tool your agent calls- Drift and conflicts — when to pull, and what to do about a divergent page
