ctx detach
Undoes ctx init: removes the Contexo wiring from your agent configs and, unless you
say otherwise, deletes the .contexo/ directory.
When you’d reach for it
Section titled “When you’d reach for it”Two quite different jobs share this command. The common one is “I evaluated Contexo, get it off my
project” — that is the default, and it is destructive on purpose. The other is “keep the knowledge,
stop the agents touching it”, which is --keep-knowledge and is the flag you want when you are
handing a repo over, debugging a hook, or moving a project between machines.
The mistake to avoid is trusting the unpushed-pages warning as a safety net. It counts pages the
local sync state has never seen — pages you edited after pushing them are not counted, and are
destroyed silently. If the knowledge matters, run ctx push first and read its
output, rather than relying on detach to notice.
Also worth knowing before you run it in a hurry: Codex’s MCP entry is global, so detaching one project removes Contexo from Codex everywhere.
Synopsis
Section titled “Synopsis”ctx detachctx detach --keep-knowledgectx detach --yesctx detach --root path/to/project --keep-knowledge --yes| Flag | Type | Default | Description |
|---|---|---|---|
--keep-knowledge | bool | false | keep the .contexo/ directory; only remove the wiring (MCP entries, .gitignore line, Stop hook) |
--yes, -y | bool | false | skip the confirmation prompt |
| Flag | Type | Default | Description |
|---|---|---|---|
--root | string | project root directory (default: current directory) |
--keep-knowledge preserves the entire .contexo/ directory as-is — every page, plus
config.json (server URL and repo id), credentials.json (your token), and .sync/state.json
(the per-page SHAs push uses for conflict detection). Re-running ctx init later reconnects the
agents and everything picks up where it left off, with no re-login and no re-ctx remote set-repo.
Without it, all four are gone.
--yes skips the prompt. You need it in any non-interactive context: the prompt reads stdin and
treats EOF — a pipe, a CI step, < /dev/null — as “no”, so an unattended ctx detach does nothing
and exits 0.
Examples
Section titled “Examples”Check for unpushed work first
Section titled “Check for unpushed work first”ctx statusInitialized: yes
Server: https://contexo.example.com
Repo: acme-api
Authenticated: yes (legacy API key)
User: dev <dev@example.com>
Local pages: 1
Last pull: (never)
Pages never pushed: 0
Pages drifted on server: 0Pages never pushed: 0 is the number detach’s warning is derived from. It is the never pushed
count, not a dirty-working-tree count.
Disconnect the agents, keep the knowledge
Section titled “Disconnect the agents, keep the knowledge”ctx detach --keep-knowledgeThis will:
- delete .mcp.json (only contained the contexo entry)
- delete .cursor/mcp.json (only contained the contexo entry)
- remove the .contexo/ line from .gitignore
- remove the Contexo Stop hook from .claude/settings.json
- remove the Contexo capture hooks from .cursor/hooks.json
- (keeping .contexo/ as requested)
Proceed? [y/N] Aborted.Detach always prints the full plan before it touches anything. This run had stdin closed, so the
[y/N] prompt read EOF and aborted — nothing was removed. Note that .mcp.json and
.cursor/mcp.json are listed for deletion rather than editing: each contained only the contexo
entry, so detach would remove the whole file.
Purge everything, no prompt
Section titled “Purge everything, no prompt”ctx detach --yesWithout --keep-knowledge this deletes .contexo/ outright — pages, config, credentials and sync
state — in addition to the wiring. The plan is still printed, but it is a receipt, not a
checkpoint.
How it works
Section titled “How it works”Detach runs in three phases: build a plan by inspecting the filesystem (and, if codex is on
PATH, by asking it), print the plan, then execute it. Which files get touched is decided before
the prompt, so nothing you do while it waits for an answer changes the list.
What each item does:
| Target | Action |
|---|---|
.mcp.json |
drops mcpServers.contexo; deletes the file when that entry was the only server and mcpServers was the only top-level key |
.cursor/mcp.json |
same rule |
~/.codex/config.toml |
runs codex mcp remove contexo — global, only when codex is on PATH and codex mcp get contexo succeeds |
.gitignore |
removes the .contexo/ (or .contexo) line plus the Contexo comment header directly above it, then trims the trailing blank line that leaves behind; every other line is preserved verbatim |
.claude/settings.json |
removes only the Stop hook entry tagged _contexo: contexo-capture-turn, then drops the group, the Stop key and the hooks key as each is emptied. The file itself is never deleted |
.codex/hooks.json |
removes the ctx capture turn --agent codex entries; deletes the file if nothing else remains |
.cursor/hooks.json |
removes the ctx capture turn --agent cursor entries; deletes the file if only the version key would be left |
.contexo/ |
recursive delete — omitted with --keep-knowledge |
Nothing on the server changes. Pages you pushed stay in the server’s git repo, the repo keeps
existing, and members, invites and activity are untouched. Detach makes no Contexo API call; the
only process it launches is codex. To come back, run ctx init, ctx login and
ctx remote set-repo, then ctx pull your knowledge back down.
Only the Claude hook is removed by marker. Its entry carries _contexo: contexo-capture-turn,
so a Stop hook you wrote by hand that happens to run ctx capture turn is left in place. The Codex
and Cursor hooks carry no marker — they are matched on the exact command string
(ctx capture turn --agent codex / --agent cursor), so a hand-written hook running precisely that
command is removed along with Contexo’s.
Partial failures do not stop the run. Each step that fails prints warning: <step>: <error> on
stderr and the rest continue; detach then exits non-zero with the first error and suppresses the
final Detach complete. line. Re-running is safe — the plan is rebuilt from what is actually on
disk.
Common errors
Section titled “Common errors”Aborted. when you did not answer anything — stdin was not a terminal. Pass --yes.
The plan omits .mcp.json even though it has a contexo entry — the file is not valid JSON.
Detach parses it to decide, and an unparseable config is treated as “no entry here”: no warning, no
edit, nothing removed. Fix the JSON and re-run, or delete the entry by hand.
warning: codex mcp remove: agentwire: codex mcp remove: exit status 1 — detach confirmed the
entry exists (via codex mcp get contexo) but the codex CLI refused to remove it, typically
because its global config is not writable. Check with ctx mcp status, then retry with
ctx mcp uninstall --tool=codex.
warning: remove .contexo/: … — a file under .contexo/ could not be deleted. On Windows this
is almost always an open handle from an agent session still running ctx mcp. Close it and re-run
ctx detach --yes; everything else in the plan has already been applied.
