Skip to content

ctx remote

ctx remote reads and edits the two fields in .contexo/config.json that decide where this project syncs: server_url and repo_id.

Mostly you don’t — ctx login writes both fields for you, and ctx join writes the repo. You reach for ctx remote when the defaults are wrong or have changed: moving a project from the hosted server to a self-hosted one, pointing a second checkout at a repo you already belong to, or just asking “which repo is this directory actually pushing to?” before a big push.

The trap is treating ctx remote set as a full re-target. It writes config.json only, and most sync commands prefer the server URL saved in .contexo/credentials.json — see How it works. To genuinely move a project to another server, log in against it.

Terminal window
ctx remote get # show what is configured
ctx remote set <url> # set the server URL
ctx remote set-repo <repo_id> # set the repo
ctx remote set-repo # …or pick from a list

ctx remote is a container command; the work is in the three subcommands, and none of them adds flags of its own.

FlagTypeDefaultDescription
--rootstringproject root directory (default: current directory)

--root is worth remembering here: ctx remote get --root ../other-project answers the “where does that checkout point?” question without leaving your current directory.

Terminal window
ctx remote set <url>

Writes server_url into .contexo/config.json and echoes it back as Server: <url>. The argument is mandatory and taken verbatim — no probing, no validation, no trailing-slash cleanup — so a typo is only discovered on the next command that talks to the network.

ctx remote set takes no flags.

Terminal window
ctx remote set https://contexo.internal
Terminal window
ctx remote set-repo [repo_id]

Writes repo_id into .contexo/config.json. With an argument it is a pure local write — no network, no membership check. What the server does with a bad id depends on whether it exists: an id belonging to a repo you are not a member of is refused on the next push with not a member of this repo, but an id that matches no repo at all is auto-created by that push, with you as its owner. A typo does not necessarily fail loudly — it can quietly give you an empty repo.

ctx remote set-repo takes no flags.

Terminal window
ctx remote set-repo acme-api
ctx remote set-repo acme-api
Repo: acme-api
Terminal window
ctx remote set-repo

Omit the argument on a terminal and the CLI calls GET /v1/repos, then shows a picker of every repo you are a member of, each line reading <repo_id> (role) with the ids padded into a column. Arrow keys to move, Enter to choose, Ctrl-C to abort with cancelled and no change on disk.

The picker needs credentials and a server URL to fetch that list. It resolves the server the same way ctx push does — credentials.json first, then config.json — so it can find your repos even in the mismatched state described above.

Terminal window
ctx remote get

Prints the two values from .contexo/config.json, substituting a hint for whichever one is missing.

ctx remote get takes no flags.

ctx remote get
Server: https://contexo.example.com
No repo configured (run 'ctx remote set-repo <id>')

This is a config dump, not a health check: it does not contact the server, does not verify the repo exists, and does not read credentials.json. For the wider picture — auth state, page counts, server drift — use ctx status.

set and set-repo do the same thing: load .contexo/config.json, change one field, write the whole file back with 0644 permissions. The file is created on demand, so ctx remote set works in a directory that has never seen ctx init — you get a .contexo/config.json and nothing else.

The part worth internalising is that the server URL is stored twice:

File Field Written by Read by
.contexo/config.json server_url ctx remote set, ctx login (with or without --server) ctx join, ctx invite, ctx members, ctx activity, ctx status, ctx remote get, and as the fallback everywhere else
.contexo/credentials.json server_url ctx login ctx push, ctx pull, ctx log, ctx history, ctx diff, ctx evolution, and the set-repo picker — in preference to config.json

That precedence exists so a token always travels with the host it was minted for. The side effect is that ctx remote set on a logged-in project produces a split brain: ctx remote get and ctx status report the new URL while pushes keep going to the old one. Logging in against the new server resolves it.

There is one more setting in config.json that ctx remote cannot touch: dashboard_url, used by the browser login flow. Set it with ctx login --dashboard <url>.

set-repo requires a <repo_id> when stdin is not a terminal — the picker would have nothing to read from, so rather than hang, it stops. Pass the id explicitly in scripts and CI.

set-repo: no credentials yet — run 'ctx login --token <ctxp_...>' first, or pass a <repo_id> directly — the picker cannot list repos anonymously.

set-repo: no server URL configured — run 'ctx remote set <url>' first, or pass a <repo_id> directly — neither file has a server_url, so there is nowhere to send GET /v1/repos.

You're not a member of any repos yet. followed by no repos available — the call succeeded and returned nothing. Get an invite key and run ctx join, or create a repo from the dashboard.

accepts 1 arg(s), received 0 — cobra’s own message for ctx remote set with no URL. Unlike set-repo, it has no interactive fallback.

  • ctx login — the command that normally writes both fields
  • ctx join — set repo_id by redeeming an invite key
  • ctx status — config plus auth, page counts and drift
  • Self-hosting — pointing projects at your own server