---
title: "How do I keep a code index fresh without re-embedding everything?"
description: "Embed only what changed: skip unchanged files, re-chunk edited files, and reuse the embedding of each chunk whose text is the same. cocoindex-code does this."
last_updated: 2026-11-05
doc_version: "2026-11-05"
canonical: https://cocoindex.io/answers/keep-code-index-fresh/
---

# How do I keep a code index fresh without re-embedding everything?

Embed only what changed. An incremental indexer skips the files whose content is the same, re-chunks the files that changed, and reuses the stored embedding of every chunk whose text is the same. `cocoindex-code` works this way: `ccc index` re-indexes changed files, and its MCP `search` tool refreshes the index before each query by default.

Checked: 2026-11-05 · Canonical: https://cocoindex.io/answers/keep-code-index-fresh/

## 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](https://github.com/cocoindex-io/cocoindex-code/blob/main/src/cocoindex_code/indexer.py)). The engine handles each kind of change this way ([Index your codebase for AI agents with CocoIndex V1](https://cocoindex.io/blogs/index-codebase-v1/#incremental-updates)):

| 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 `search` tool.** Its `refresh_index` parameter defaults to true, so the index is refreshed before the query runs.
- **The skill.** It instructs the agent to run `ccc index` or `ccc search --refresh` when the index may be stale, for example at the start of a session or after significant code changes. A plain `ccc search` does not refresh.
- **The CLI.** `ccc index` updates 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 incremental `ccc index` at session start and after each edit.

## Install and connect

```bash
pipx install 'cocoindex-code[full]'
# or with uv:
uv tool install --upgrade 'cocoindex-code[full]'

cd your-repo
ccc index
```

```bash
# 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:

```json
{
  "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`, run `ccc reset && ccc index` after you switch models.
- **Language overrides and custom chunkers.** A change to `language_overrides` or 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, run `ccc daemon restart` before `ccc index`.
- **File patterns.** A change to `include_patterns`, `exclude_patterns` or `max_file_size` needs no rebuild. The next `ccc index` updates 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:

```python
@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](https://cocoindex.io/blogs/index-codebase-v1/) 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=false` to skip it when the index is already current.
- **Other change detection.** [Claude Context](https://github.com/zilliztech/claude-context) finds changed files with Merkle trees and also re-indexes only those files.
- **Hosted indexes.** The [GitHub MCP Server](https://github.com/github/github-mcp-server) searches code that is on GitHub. It does not see edits you have not pushed.
- **Branches.** `cocoindex-code` indexes the working tree of one project. [CocoIndex Code Plus](https://cocoindex.io/cocoindex-code/) (`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](https://github.com/cocoindex-io/cocoindex-code): MCP tool reference, project settings and re-index rules.
- [Index your codebase for AI agents with CocoIndex V1](https://cocoindex.io/blogs/index-codebase-v1/): the incremental update rules, with diagrams.
- [Incremental processing with CocoIndex](https://cocoindex.io/blogs/incremental-processing/): how the engine tracks changes.
- [Functions](https://cocoindex.io/docs/programming_guide/function/) and [memoization keys](https://cocoindex.io/docs/advanced_topics/memoization_keys/) in the CocoIndex docs.

## Related questions

- [How do I add semantic search over my source code for my AI assistant?](https://cocoindex.io/answers/semantic-search-source-code.md)
- [What is the best MCP server for code search?](https://cocoindex.io/answers/best-mcp-server-for-code-search.md)
- [Why is my coding agent slow on a large codebase or monorepo?](https://cocoindex.io/answers/coding-agent-slow-large-codebase.md)

## Sitemap

- [All answers](https://cocoindex.io/answers.md)
- [Site index (llms.txt)](https://cocoindex.io/llms.txt)
- [Markdown sitemap](https://cocoindex.io/sitemap.md)
- [XML sitemap](https://cocoindex.io/sitemap.xml)
