ctx invite
ctx invite manages the ctxi_… keys a teammate redeems with
ctx join to get access to the current repo.
When you’d reach for it
Section titled “When you’d reach for it”You’ve pushed a knowledge base and someone else needs to pull it. Mint a key,
send it to them, and they’re a member — there is no “add by email” path, so an
invite key is the only way a second person gets in. Two things people get
wrong: a key is reusable until it expires or you revoke it (anyone holding
it can join, not just the person you sent it to), and ctx invite revoke wants
the key id from ctx invite list, not the ctxi_ token you shared.
All three subcommands are owner-only — including list, so a regular member
can’t audit outstanding keys from the CLI.
Synopsis
Section titled “Synopsis”ctx invite mint [--label <text>]ctx invite listctx invite revoke <keyId>Every subcommand also takes the global flag:
| Flag | Type | Default | Description |
|---|---|---|---|
--root | string | project root directory (default: current directory) |
ctx invite mint
Section titled “ctx invite mint”Creates a key on the current repo and prints the raw token.
ctx invite mint [--label <text>]| Flag | Type | Default | Description |
|---|---|---|---|
--label | string | Optional label to remember what the key is for |
--label is stored on the server and shown by ctx invite list. Beyond the
opaque key id and the expiry, it’s the only thing that listing tells you about a
key — the token itself is never shown again — so label anything you don’t intend
to revoke the same day.
Output is three lines: the ctxi_… token, an expires <date> UTC line (with
· label "…" appended when you passed one), and a reminder of the
ctx join <token> command to pass along.
Example
Section titled “Example”ctx invite mint --label "alice laptop"ctx invite list
Section titled “ctx invite list”Shows the keys that exist on the current repo, newest first.
ctx invite listctx invite list takes no flags.
Each row is <key id> <status> expires <date> UTC <label>, where status is
active or expired and an unlabelled key prints (no label). Expired keys
keep showing up: nothing sweeps them, and ctx invite revoke is what actually
deletes the row.
Example
Section titled “Example”ctx invite listno invite keysctx invite revoke
Section titled “ctx invite revoke”Deletes a key so it can no longer be redeemed.
ctx invite revoke <keyId>ctx invite revoke takes no flags.
<keyId> is the UUID in the first column of ctx invite list. Passing the
ctxi_… token instead fails with a 404 — the server looks keys up by id, and
scopes the delete to the current repo, so an id from another repo won’t match
either. On success it prints revoked <keyId>.
Revoking a key does not remove anyone who already joined with it. Use
ctx members remove for that.
Example
Section titled “Example”ctx invite revoke 5f1c9c2e-3f4a-4a2e-9b6d-2b1f0f7a55c1How it works
Section titled “How it works”All three subcommands read .contexo/config.json plus the stored credentials,
then talk to /v1/repos/<repo_id>/invite-keys on your configured server. They
touch no local files and make no git commits.
- mint →
POST …/invite-keyswith the label. The server checks you are an owner of the repo, generates 24 random bytes, base64url-encodes them behind thectxi_prefix, stores a hash of the token alongside the label, creator and expiry, and returns the row plus the raw token. The TTL is a fixed 7 days from minting; it is not configurable. - list →
GET …/invite-keys. Returns every key for the repo (id, label, created, expires) — never the tokens. Theactive/expiredsplit is computed locally by comparing each expiry against the current time. - revoke →
DELETE …/invite-keys/<keyId>, which deletes the row outright.
Redemption happens elsewhere: ctx join <token> posts the token to
/v1/repos/join, the server resolves it by hash and — if it hasn’t expired —
adds the caller to the repo’s member list with the member role, then writes
the repo id into the joiner’s local config. The key is not consumed, so the
same token works for the next person until its 7 days are up.
That also means the member cap is enforced at join time, not at mint time. Minting always succeeds for an owner; on the hosted service it’s the teammate whose join would exceed the plan’s member limit who gets the upgrade prompt.
Common errors
Section titled “Common errors”| Message | What happened |
|---|---|
invite: not authenticated — run 'ctx login' first |
No credentials in this project. See ctx login. |
invite: server URL not set — run 'ctx remote set <url>' first |
Config has no server. See ctx remote. |
invite: repo id not set — run 'ctx remote set-repo <id>' first |
The project isn’t pointed at a repo yet. |
sync: mint invite key failed (403): {"error":"owner role required"} |
You’re a member, not an owner. Ask an owner to mint it. |
sync: delete invite key (404): {"error":"invite key not found"} |
Wrong id, or the key belongs to another repo. |
One more 403 is worth calling out, because it looks like a permissions bug and isn’t:
Error: sync: mint invite key failed (403): {"error":"user session required to mint invite keys"}That’s a server reached with the deprecated shared --api-key. Legacy
shared-key auth has no user behind it, so there is nobody to record as the
key’s creator and the server refuses outright. Sign in properly —
ctx login with a personal access token or the browser flow —
and mint again.
See also
Section titled “See also”ctx join— the other half of the flow: redeem a keyctx members— who actually has access right nowctx activity— what those members have been doing- Teams guide — the whole onboarding flow end to end
