ctx init
Creates the .contexo/ knowledge tree for a project and connects the AI coding agents on your
machine to it.
When you’d reach for it
Section titled “When you’d reach for it”Once per project, from the repository root, before anything else. It needs no login and never
contacts a Contexo server — every step is a local file write — so it is safe to run while you are
still deciding whether you want Contexo at all (ctx detach reverses it).
Two things trip people up. First, ctx init does not log you in or attach a remote repo;
straight after it you have a local knowledge base and nothing else, which is exactly what
ctx status reports below. Second, everything is written relative to the current directory (or
--root), so running it from a subdirectory quietly gives you a second, useless .contexo/. Run
it where your .git is.
Re-running is safe. It is idempotent by design: existing config, seed files, MCP entries and hooks
are left alone, so ctx init is a reasonable way to pick up an agent you installed after the fact
(though ctx mcp install and ctx hooks install are the targeted
tools for that).
Synopsis
Section titled “Synopsis”ctx initctx init --root path/to/projectctx init --no-gitignorectx init --no-mcp --no-hooks| Flag | Type | Default | Description |
|---|---|---|---|
--no-cursor | bool | false | skip auto-wiring Cursor (.cursor/mcp.json) even when Cursor is detected |
--no-gitignore | bool | false | skip adding .contexo/ to .gitignore |
--no-hooks | bool | false | skip registering the Claude Code Stop hook for per-turn capture |
--no-mcp | bool | false | skip wiring the MCP server into agent configs (.mcp.json, .cursor/mcp.json) |
| Flag | Type | Default | Description |
|---|---|---|---|
--root | string | project root directory (default: current directory) |
A few of these do less — or more — than their one-liners suggest:
--no-cursoronly skips Cursor’s MCP entry. Cursor’s capture hooks are governed by--no-hooks, not by--no-cursor, soctx init --no-cursoron a machine with Cursor installed still writes.cursor/hooks.json. Use--no-hooksas well if you want no.cursor/directory at all.--no-hooksskips all three capture integrations, not just Claude Code’s: no Stop hook in.claude/settings.json, no.codex/hooks.json, no.cursor/hooks.json.--no-mcpimplies no Cursor MCP entry, and also suppresses the “Codex detected” hint. It does not affect hooks.--rootis a global flag and is resolved before anything is created; every path on this page is relative to it.
Examples
Section titled “Examples”Initialize a project
Section titled “Initialize a project”ctx init Wired Claude Code (.mcp.json) — restart your agent to load the contexo server
Cursor detected — wired .cursor/mcp.json
Created .gitignore with .contexo/
Installed Contexo capture Stop-hook in .claude/settings.json
Restart Claude Code (or open a new session) so the hook is picked up.
Installed Cursor capture hooks (.cursor/hooks.json: beforeSubmitPrompt + afterAgentResponse)
Initialized .contexo in ~/projects/acme-api
Agent integrations for this project:
AGENT MCP SERVER CAPTURE (STOP HOOK)
Claude Code wired (.mcp.json) installed
Cursor wired (.cursor/mcp.json) installed
Codex not installed not installed
Add Contexo to another agent or harness
---------------------------------------
Contexo's MCP server is a standard stdio server: command "ctx", args ["mcp"].
Add that to the agent's own MCP config — same server everywhere; only the
file and format differ:
AGENT CONFIG FORMAT / HOW
Claude Code ./.mcp.json JSON mcpServers — ctx mcp install --tool=claude
Cursor ./.cursor/mcp.json JSON mcpServers — ctx mcp install --tool=cursor
Codex ~/.codex/config.toml TOML [mcp_servers.contexo] — ctx mcp install --tool=codex
Windsurf ~/.codeium/windsurf/mcp_config.json JSON mcpServers
OpenCode ./opencode.json JSON mcp: { contexo: { type: "local", command: ["ctx","mcp"] } }
Hermes config.yaml YAML mcp_servers: { contexo: { command: ctx, args: [mcp] } }
OpenClaw (CLI-managed) run the `openclaw mcp` command
JSON mcpServers entry: "contexo": { "command": "ctx", "args": ["mcp"] }
Any other MCP client: add the same server; see its docs for the exact path.
Capture (the Stop hook): Claude Code, Codex, and Cursor are supported —
ctx hooks install --tool=claude|codex|cursor|all
Claude parses its transcript; Codex and Cursor pair their prompt + response
hooks inline. Other MCP-capable harnesses get the tools now; capture as they
expose a stop/turn-end hook.The per-file lines come first, then the summary: where .contexo/ landed, an integration table for
this project, and the guide for agents Contexo does not wire itself. This run was in a fresh git
repo with Cursor installed and no Codex on PATH.
See what you actually have afterwards
Section titled “See what you actually have afterwards”ctx statusInitialized: yes
Server: (none — run 'ctx remote set <url>')
Repo: (none — run 'ctx remote set-repo <id>')
Authenticated: no
Local pages: 0
Last pull: (never)
Pages never pushed: 0No server, no repo, not authenticated. ctx init is local-only; wiring up the remote is
ctx login followed by ctx remote set-repo.
Re-check the wiring later
Section titled “Re-check the wiring later”ctx mcp statusAgent integrations for this project:
AGENT MCP SERVER CAPTURE (STOP HOOK)
Claude Code wired (.mcp.json) installed
Cursor wired (.cursor/mcp.json) installed
Codex not installed not installed
Add another agent (Windsurf, OpenCode, Hermes, ...)? Run `ctx mcp guide`.This is the same table ctx init prints at the end, on demand. Useful after you install a new
agent, or when an agent claims it cannot see the contexo server.
How it works
Section titled “How it works”Everything below is a local file write. ctx init contacts no Contexo server and makes no git
commit. The only network traffic it can produce is the update nudge every ctx command runs after
it succeeds — an at-most-once-per-24h GitHub releases lookup, skipped when stdout is not a TTY or
when CONTEXO_NO_UPDATE_CHECK or CI is set.
| Path | What ctx init does |
Skipped by |
|---|---|---|
.contexo/, .contexo/wiki/concepts/, .contexo/wiki/entities/, .contexo/wiki/analyses/, .contexo/raw/sessions/ |
created (mkdir -p, mode 0755) |
never |
.contexo/config.json |
written as {"version": 1} — only if absent |
never |
.contexo/index.md, .contexo/tags.md |
seeded with empty-section placeholders — only if absent | never |
.mcp.json |
merges mcpServers.contexo = {"command": "ctx", "args": ["mcp"]} |
--no-mcp |
.cursor/mcp.json |
same entry, only when Cursor is detected | --no-mcp, --no-cursor |
.gitignore |
created (or appended to) with a comment header plus .contexo/, only when <root>/.git exists |
--no-gitignore |
.claude/settings.json |
appends a Stop hook group running ctx capture turn, tagged _contexo: contexo-capture-turn |
--no-hooks |
.codex/hooks.json |
Stop + UserPromptSubmit hooks running ctx capture turn --agent codex, only when Codex is detected |
--no-hooks |
.cursor/hooks.json |
beforeSubmitPrompt + afterAgentResponse hooks running ctx capture turn --agent cursor (adds "version": 1), only when Cursor is detected |
--no-hooks |
Merging, not overwriting. The JSON writers load whatever is already there and add only the
contexo key, so other MCP servers and other hooks survive. If the contexo MCP entry is present
and identical, nothing is written at all and init says so. The .gitignore edit is skipped
entirely when a line already reads .contexo/ or .contexo.
Detection is deliberately asymmetric. Cursor counts as installed if ~/.cursor exists or
cursor is on PATH — wiring it only writes harmless project-local files. Codex must have its
binary on PATH; a bare ~/.codex directory is not enough, because other tools create that
directory and wiring Codex means shelling out to codex mcp add.
Codex’s MCP server is never wired by init. It lives in Codex’s global ~/.codex/config.toml,
so init only prints a one-line hint and leaves the decision to you:
ctx mcp install --tool=codexHook failures are non-fatal. If the Stop hook cannot be installed, init prints
Warning: could not install Claude Stop hook: … (run 'ctx hooks install' later) and carries on;
the knowledge directory is the load-bearing part. The Codex and Cursor capture hooks warn the same
way (Warning: could not install Codex capture hooks: …).
Why the seed files matter. .contexo/index.md and .contexo/tags.md are what the ctx://index
and ctx://tags MCP resources read; the index is advertised to agents with priority 1.0. Seeding
them means the very first session gets a valid (if empty) index instead of a read error. They are
rebuilt from your pages whenever an agent writes a page (ctx_write_page) and on every
ctx pull.
Common errors
Section titled “Common errors”init: write .mcp.json: agentwire: parse …: invalid character … — an existing .mcp.json (or
.cursor/mcp.json) is not valid JSON. Init refuses to guess and aborts. The .contexo/ tree was
created first and survives; the .gitignore line and the hooks come after MCP wiring and never
ran. Fix the file, or run ctx init --no-mcp and wire the agent afterwards with ctx mcp install.
init: create …: permission denied — the project root is not writable. Directory creation is
the very first step, so nothing else has been touched.
No .gitignore line and no message about one — the directory has no .git, so the step is
skipped silently. Run git init first, then ctx init again (it is idempotent), or add
.contexo/ yourself.
Agent shows contexo with zero tools — the agent is running ctx mcp outside a Contexo
project. Outside a .contexo/ directory the MCP server starts in dormant mode with no tools rather
than failing. Check that the agent’s working directory is the project root you ran ctx init in.
See also
Section titled “See also”ctx detach— reverse everything on this pagectx mcp— wire, unwire, and inspect agent MCP configs on their ownctx hooks— install or remove the capture hooks on their ownctx login— the next step: authenticate and attach a remote repo
