Reuse happens per file and per chunk
Embedding a chunk takes model compute, so an incremental indexer avoids it at 2 levels: the file and the chunk. cocoindex-code is built on the CocoIndex engine, and its per-file function is memoized with @coco.fn(memo=True) (indexer.py). The engine handles each kind of change this way (Index your codebase for AI agents with CocoIndex V1):
| Change | Work done |
|---|---|
| A file did not change | The file is skipped. |
| A file is added | Only that file is chunked and embedded. |
| A file is edited | The file is re-chunked. Chunks whose text is the same keep their embedding. New chunks are embedded. Chunks that no longer exist are deleted. |
| A file is deleted | Its rows are removed from the index. |
Chunk boundaries decide how much an edit invalidates. cocoindex-code tries to split files at function and class boundaries with Tree-sitter. When you edit one function, chunks whose text did not change keep their embeddings, so the model runs only for the chunks that contain the edit. A neighboring chunk can change too, because chunks overlap by up to 150 characters.
What triggers a refresh in cocoindex-code
- The MCP
searchtool. Itsrefresh_indexparameter defaults to true, so the index is refreshed before the query runs. - The skill. It instructs the agent to run
ccc indexorccc search --refreshwhen the index may be stale, for example at the start of a session or after significant code changes. A plainccc searchdoes not refresh. - The CLI.
ccc indexupdates the index.ccc search --refresh <query>updates it and then searches. - Plugin hooks. In an initialized project, the Grok plugin (installed with
--trust) and the Oh My Pi plugin run an incrementalccc indexat session start and after each edit.
Install and connect
pipx install 'cocoindex-code[full]'
# or with uv:
uv tool install --upgrade 'cocoindex-code[full]'
cd your-repo
ccc index
# Claude Code: skill (recommended in the README)
npx skills add cocoindex-io/cocoindex-code
# Claude Code: MCP
claude mcp add cocoindex-code -- ccc mcp
# OpenAI Codex CLI
codex mcp add cocoindex-code -- ccc mcp
Cursor and other MCP clients that launch a stdio server take the generic entry. The client must start ccc mcp with the project as its working directory:
{
"mcpServers": {
"cocoindex-code": {
"command": "ccc",
"args": ["mcp"]
}
}
}
Changes that repeat more work
- New embedding model. A different model produces different vectors, so everything is embedded again. In
cocoindex-code, runccc reset && ccc indexafter you switch models. - Language overrides and custom chunkers. A change to
language_overridesor to a chunker re-chunks all files. Chunks whose text did not change keep their cached embeddings, so the model runs only for the chunks that differ. After a chunker change, runccc daemon restartbeforeccc index. - File patterns. A change to
include_patterns,exclude_patternsormax_file_sizeneeds no rebuild. The nextccc indexupdates the existing index.
Build your own incremental index
In your own pipeline, the CocoIndex framework does the same work. @coco.fn(memo=True) skips a file when its content and the function’s code are both unchanged:
@coco.fn(memo=True)
async def process_file(
file: FileLike,
table: postgres.TableTarget[CodeEmbedding],
) -> None:
text = await file.read_text()
language = detect_code_language(filename=str(file.file_path.path.name))
chunks = _splitter.split(
text,
chunk_size=1000,
min_chunk_size=300,
chunk_overlap=300,
language=language,
)
id_gen = IdGenerator()
await coco.map(process_chunk, chunks, file.file_path.path, id_gen, table)
cocoindex update main catches up once and exits. cocoindex update -L main keeps watching and applies each change as you save. The full walkthrough has the rest of the pipeline.
Limits, and when another tool fits better
- Refresh per query. By default, the refresh runs before each MCP query. Pass
refresh_index=falseto skip it when the index is already current. - Other change detection. Claude Context finds changed files with Merkle trees and also re-indexes only those files.
- Hosted indexes. The GitHub MCP Server searches code that is on GitHub. It does not see edits you have not pushed.
- Branches.
cocoindex-codeindexes the working tree of one project. CocoIndex Code Plus (ccx), a separate self-hosted product, indexes a repository at several long-lived branches and processes each file once for all branches that contain it.
Sources and further reading
- cocoindex-code README: MCP tool reference, project settings and re-index rules.
- Index your codebase for AI agents with CocoIndex V1: the incremental update rules, with diagrams.
- Incremental processing with CocoIndex: how the engine tracks changes.
- Functions and memoization keys in the CocoIndex docs.