ctx_index
Store content in the persistent knowledge base so you can search it later without re-reading.
ctx_index writes content into the persistent FTS5 knowledge base. Once stored,
the content is searchable with BM25 ranking, so you recall the relevant passage
later instead of reading the whole source back into context. Index once, then
ctx_search it as many times as you need.
Use it for text you already hold and want to keep: a spec you pasted, a long
command output you want to keep queryable, notes you want to persist past the
current step, or any reference you would otherwise re-read. You can also point it
at a local path — a single file or a whole directory — to index source from disk
without its contents ever entering context.
Parameters
Provide either content or path — not both.
| Parameter | Required | Description |
|---|---|---|
content | one of content/path | Raw text or markdown to store. |
path | one of content/path | A file or directory to read and index from disk. The contents never enter context. A directory triggers a bounded recursive walk. |
source | no | A descriptive label used to filter searches later. When omitted for a path, it defaults to the resolved path. |
The source label is how you find this content again. Make it specific —
payments-api-spec recalls cleanly, notes does not — because ctx_search
accepts source as a partial-match filter.
Directory indexing
When path resolves to a directory, ctx_index walks it and indexes each file.
The walk is bounded so it never floods the store. These controls apply only to
directory paths:
| Parameter | Default | Description |
|---|---|---|
include | all matching extensions | Glob patterns to include. |
exclude | merged with defaults | Glob patterns to exclude, added to the built-in skips (node_modules, .git, dist, build, .next, coverage, .venv, __pycache__, .DS_Store). |
maxDepth | 5 | Maximum recursion depth from the root. |
maxFiles | 200 | Hard cap on files indexed — guards against an FTS5 blow-up. |
extensions | .md .mdx .txt .json .yaml .yml .ts .tsx .js .jsx .py .rs .go .sh | Allowed file extensions. |
respectGitignore | true | Apply the nearest .gitignore. |
followSymlinks | false | Follow directory symlinks. Off by default to avoid cycles and path-escape. |
Chunking
Content is split before it is stored so that each searchable unit is coherent:
- Markdown is split by headings, with code blocks kept intact.
- JSON is split by key paths.
- Plain text is split by lines.
Each chunk is indexed on its own, which is why a query returns the one relevant section rather than the entire document.
Indexing is additive. Index the same source again to add new chunks; it does not replace what is already stored under that label.
Example
Index a short spec under a descriptive label, then search it back. The search returns only the matching chunk, not the whole text.
ctx_index(
content: "## Retry policy\nRequests retry up to 3 times with exponential backoff.\nThe 4th failure surfaces a 503 to the caller.",
source: "payments-api-spec"
)
ctx_search(
queries: ["How many times does a request retry before failing?"],
source: "payments-api-spec"
)To index source from disk instead, pass a path. A directory walks recursively
under the bounded defaults; the file contents stay out of context.
ctx_index(
path: "./src",
source: "codebase"
)