CortexDB Docs
Docs for CortexDB 0.12.8, the version running on CortexDB Cloud (api.cortexdb.ai).
Features

Code Intelligence Plane

Index a repository into CortexDB and retrieve task-scoped, cited code context.

The Code Intelligence Plane indexes a code repository into CortexDB and answers "what code is relevant to this task?" with cited snippets — each pinned to repo:path@<snippet-hash>#Lx-Ly. It's a separate surface from the memory layers, gated behind a flag and its own /v1/code/* routes.

Off by default; enable with CORTEX_CODE_PLANE=1

The code plane is disabled unless CORTEX_CODE_PLANE=1 is set (or Code memory is switched on in the Admin Console Features page, which takes effect on restart). With the flag off, every /v1/code/* route returns 503 CODE_PLANE_DISABLED. Most /v1/code/* routes are not in /v1/openapi.json — they're a separate surface; the spec does list POST/GET /v1/code/repos, GET/DELETE /v1/code/repos/{name} (delete de-registers and frees the bytes), POST /v1/code/certify (a certified answer over compiler-tier SCIP evidence only), POST /v1/code/import/scip and POST /v1/code/import/coverage (lcov). The full route reference ships inside the server image as /opt/cortexdb/docs/CODE_PLANE.md. The CLI mirrors the main routes as cortexdb code add/status/remove/import-scip/import-coverage. (There is no /v1/code/health route — a 404 there means "no such route", not "disabled".)

Enable and mount a repository

The server can only index paths it can read, so mount the repo into the container, and tell the server which directories repositories may be registered from:

docker run -d --name cortexdb \
  -p 127.0.0.1:3141:3141 \
  -v cortexdb-data:/data \
  -v /host/path/to/myrepo:/repos/myrepo:ro \
  -e CORTEX_CODE_PLANE=1 \
  -e CORTEX_CODE_REPO_ROOTS=/repos \
  -e OPENAI_API_KEY=$OPENAI_API_KEY \
  -e CORTEX_LICENSE \
  cortexdb/cortexdb:v0.12.8

CORTEX_CODE_REPO_ROOTS is recommended rather than required: without it the server logs a startup warning that any readable directory may be registered. See Where repositories may live.

Register a repository

curl -X POST http://localhost:3141/v1/code/repos \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "X-Cortex-Actor: $CORTEX_ACTOR" \
  -H "Content-Type: application/json" \
  -d '{ "name": "myrepo", "path": "/repos/myrepo", "scope": "org:acme/team:eng" }'

Returns 201 with parse statistics (files parsed, symbols extracted) and the bound scope. The path is the in-container path you mounted, not a host path. scope names the parent the repository is bound under; the server appends repo:<name>-<12 hex>, where the leaf comes from the repository name (so two names registered from one checkout bind to two different scopes). Omit scope to bind under the tenant root.

Retrieve task-scoped context

curl -X POST http://localhost:3141/v1/code/context \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "X-Cortex-Actor: $CORTEX_ACTOR" \
  -H "Content-Type: application/json" \
  -d '{
    "repo": "myrepo",
    "task": "where is the recall pack assembled?",
    "token_budget": 4000
  }'

The response is a set of cited snippets with a reason code explaining why each was selected, plus snapshot and generation. Feed that context straight into a coding agent's prompt.

What a citation hash is (and isn't)

A citation looks like hiredis:net.c@f0a1c85552da9fe4#L458-L485. The hash after @ is a hash of the snippet it cites, so you can verify a citation against its text. It is not a git commit, blob or tree id — git show won't find it. The commit the index was built from is the response's separate snapshot field (the checkout's HEAD when it was last indexed, the same value as git rev-parse HEAD). The index follows the working tree, uncommitted edits included, so a snippet can come from a file edited since that commit.

Where repositories may live

The requested path is resolved first (.. segments and symlinked directories become their real target) and then checked. Refusals are 422 REPO_PATH_NOT_ALLOWED with a details.reason:

Pathreason
/filesystem_root
/proc, /proc/self, /sys, /etc (also /dev, /run, /boot)system_path
the server's data directory or anything inside it — directly, via /tmp/../data, or via a symlink to itdata_directory
outside CORTEX_CODE_REPO_ROOTS when it is set, including a symlink inside a root that points out of itoutside_allowed_roots

A relative path is refused (422 REGISTRATION_FAILED without the roots variable). With CORTEX_CODE_REPO_ROOTS set (a :-separated list on Linux), the resolved path must lie inside one of the roots; set but naming no existing directory refuses every registration (per the server reference). Registration never follows the server into its own storage.

What gets indexed

  • A git checkout indexes every file .gitignore doesn't exclude, minus built-in vendor and generated skips (node_modules/, target/, dist/, …).
  • Any other directory indexes only files with a recognised source extension and skips hidden files and directories (a leading .): a plain folder holding src/add.c, .env, .env.example and server.pem indexes only src/add.c. To index more, git init it and describe it with a .gitignore.
  • Credential files are never read, in either mode (the full list is in the server's CODE_PLANE.md): dotenv files (.env, .env.*, *.env, except the templates .env.example / .env.sample / .env.template, which are indexed in a git checkout), private keys and key stores (*.pem, *.key, *.p12, id_rsa, …), credential files (.netrc, .npmrc, .git-credentials, credentials*.json, …), Terraform state, and everything under .ssh/, .aws/, .kube/ and similar.
  • A secret embedded in a source file is not detected — an API key hard-coded in config.py is indexed like the rest of the file. Keep secrets out of source.
  • Symbolic links inside the checkout are not followed. The server reference adds that files over 4 MiB and binary files are skipped.

Who can read a repository

A repository is bound to a scope and every read or change is authorized against it: the caller needs the capability, a seat on that scope's roster, and (if the token carries scopes) confinement that reaches it. For example, with two agent tokens minted by the operator (on dev_local or on_prem_enterprise): team A registered the repository under org:dev/team:a, which made it the owner of that scope (the first registrant claims an unregistered team scope); team B has no seat there:

Team B's call on team A's repositoryResult
GET /v1/code/reposthe repository is omitted from the listing
POST /v1/code/context, POST /v1/code/graph/query, GET /v1/code/repos/{name}404 REPO_NOT_FOUND
DELETE /v1/code/repos/{name}404 REPO_NOT_FOUND (team A's repository survives)
POST /v1/code/repos with scope: org:dev/team:a403 POLICY_DENIED

The 404 never confirms that a name exists. Another tenant's repository is equally invisible. The static operator key (and no-auth mode) skips per-scope rosters and sees every repository in its tenant.

The call graph and SCIP

POST /v1/code/graph/query walks calls edges from exact indexed roots (direction: outgoing, incoming or both). Out of the box the edges come from parsing (tier: Syntax, status: Unresolved, matched by name). On C and C++ code:

  • C functions returning pointers carry their outgoing calls, and callers are attributed to the calling function, not to the file.
  • C++ members can be named by their qualified name: buffered_file::close and file::close resolve separately. A bare name (close) returns every identity carrying it — ambiguity is returned, never collapsed.
  • Calls inside gtest TEST(...) bodies are attributed to the test, so impact analysis sees tests that call a function.

For exact cross-references, import a compiler-tier index. For C/C++ that means running scip-clang over a compile_commands.json, then:

curl -X POST "http://localhost:3141/v1/code/import/scip?repo=myrepo" \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @index.scip

The response reports accepted, rejected and derived_calls; afterwards the graph carries tier: Compiler, status: Exact edges beside the syntax ones. POST /v1/code/certify answers count-call-sites or list-implementations only from compiler-tier evidence. It covers every code file in the symbol's language family, so if parts of the repository were not compiled (examples, optional adapters), narrow it with paths (repo-relative prefixes):

{ "repo": "hiredis", "question": "count-call-sites",
  "symbol": "cxx . . $ redisConnectWithOptions(45dbf3ccfa7760d5).",
  "paths": ["hiredis.c", "async.c", "test.c"] }

The answer is exact for the code as compiled: calls inside a disabled #ifdef don't exist for the compiler and aren't counted. Without full coverage the response is incomplete and lists the files that lack compiler-tier evidence; docs, config and scripts in other languages never block it.

The CLI

The cortexdb CLI wraps the plane under cortexdb code:

cortexdb code add <path>           # register + index a repo
cortexdb code status               # list repos and index state
cortexdb code remove <name>

Run cortexdb code --help for the full set (add, remove, status, import-scip, import-coverage, export-index, import-index, pin, gc, matrix, watch).

What the plane stores

Registering a repo parses it into symbols and indexes them alongside CortexDB's other indexes in the same data directory — so a cold backup covers the code plane too. Snippets are kept by content hash, and each context response names the commit it was built from (snapshot). Deleting a repository frees its directory; while a repository is registered, content of files removed from it may stay on disk until garbage collection but is never served.

On this page