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.8CORTEX_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:
| Path | reason |
|---|---|
/ | 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 it | data_directory |
outside CORTEX_CODE_REPO_ROOTS when it is set, including a symlink inside a root that points out of it | outside_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
.gitignoredoesn'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 holdingsrc/add.c,.env,.env.exampleandserver.pemindexes onlysrc/add.c. To index more,git initit 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.pyis 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 repository | Result |
|---|---|
GET /v1/code/repos | the 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:a | 403 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::closeandfile::closeresolve 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.scipThe 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.