GitHub

Core Concepts

RCE Code turns a repository into one queryable index. This page is the mental model: the handful of entities the index is built from, how they relate, and the properties — content addressing, two-phase resolution, honest freshness — that make the index fast and incremental.

The entities at a glance

Index

A single SQLite database at <repo>/.rce/code/index.db holding every file, chunk, symbol, reference, and embedding.

File

One source file, content-hashed and language-detected, the unit of incremental indexing.

Chunk

A definition-aligned slice of a file — the unit of search and embedding.

Symbol

A named definition (function, class, method, …) extracted from the AST.

Reference

A call or import site, resolved to a target symbol on a lazy second pass.

Embedding

A per-chunk vector, cached by content hash and queried by cosine KNN.

The index

Everything lives in a single SQLite database, created and migrated on first use at <repo>/.rce/code/index.db. There is one serialized writer: parsing happens in pure workers that hold no database handle, and the parent process applies their results one file per transaction. Indexing is a pure pipeline — walk, parse, chunk, extract symbols and references, then resolve the call graph — and it is content-addressed, so re-indexing an unchanged tree is nearly free.

Files and content hashing

Each source file is the unit of incremental indexing. A file is content-hashed (with blake3), language-detected, and tracked by its mtime. The hash defines a cache identity: unchanged files are hash-skipped, changed files are re-parsed, and deleted files are dropped. Chunk content hashes are deliberately position-independent — they exclude line and byte offsets — so moving a function down a file does not invalidate its chunk or its embedding.

Chunks

A Chunk is a definition-aligned slice of a file and the unit of both search and embedding. The AST chunker never splits a definition mid-body; each top-level definition becomes one chunk, with comments attached. Every chunk carries its line and byte span, a kind, an optional name, the raw content, a search_terms field (the sub-token-expanded text the lexical index queries), a content_hash, a token_count, and its language. A chunk may point at a parent_chunk_id — for example a method's enclosing class.

The ChunkKind enum classifies each chunk:

ChunkKind
function class method module block doc

Symbols

A Symbol is a named definition extracted from the AST. Alongside its name, every symbol has a qualified_name — the names of its enclosing definitions joined by the language's separator (. for Python, :: for Rust, and so on), e.g. module.Class.method. Symbols carry a kind, source span (start/end line and column), an optional signature, docstring, and visibility, plus a parent_id and the chunk_id they belong to.

The SymbolKind enum is broader than ChunkKind:

SymbolKind
function method class interface type enum
variable constant field parameter module

Method reclassification

A captured function whose nearest enclosing captured definition is a class is reclassified to method. This keeps, say, Python class bodies modelled as methods, while languages without that nesting (or with receiver-based methods, like Go) are classified per their own structure.

References

A Reference is a use site — a call or an import, distinguished by the is_import flag. References are extracted by name first and resolved later: RCE Code stores the to_name immediately and fills in to_symbol_id on a lazy second pass, attaching a resolution_confidence score. Until that resolver runs — or when a name cannot be resolved — to_symbol_id stays None. Each reference also records where it came from (from_symbol_id, from_file_path) and its line/col. Resolved references are what power get_callers and get_callees.

Two-phase by design

Definitions are easy — tree-sitter pins them exactly. References are hard, so RCE Code never blocks ingestion on resolution: names are stored on write and resolved to IDs (with confidence) on a separate lazy pass.

Freshness and incremental indexing

Every indexed result carries a Freshness record so the caller can decide whether to trust it. It exposes the source file's file_mtime, the index's indexed_at time, whether the chunk is_stale(its source changed since it was indexed), and whether it has_embedding. Because the index is content-hash-cached, incremental re-indexing only touches files whose hash changed. Grep hits are the exception: they read the live filesystem and are always current, so a GrepHit carries no freshness at all.

EntityKey fields
Chunkid, file_path, start_line/end_line, kind, name, parent_chunk_id, content, search_terms, content_hash, token_count, language
Symbolid, name, qualified_name, kind, file_path, chunk_id, parent_id, signature, docstring, visibility, language
Referenceid, from_symbol_id, from_file_path, to_name, to_symbol_id, resolution_confidence, is_import, line/col, language
SearchResultchunk, score, source (SearchSource), freshness, snippet, matched_terms
Freshnessfile_mtime, indexed_at, is_stale, has_embedding
IndexStatsfiles, chunks, symbols, refs, embedding_coverage, last_full_sync_at, stale_files, skipped, fts_ok

Embeddings

Each chunk can have a single vector embedding, the basis of semantic and hybrid search. Embedding is lazy: embed() only embeds chunks that lack a current embedding, and the embedding cache is keyed by the chunk's content hash combined with the model id and version — so unchanged content is never re-embedded, even across model swaps for content that already matched. Vectors are queried by cosine KNN through a numpy backend by default, with sqlite-vec available as an option.

Incremental, not rebuilt

Re-running index() and embed() after a change re-parses and re-embeds only what actually changed — both are idempotent and content-hash-cached.

Search results and sources

Indexed queries return SearchResult objects: the matched chunk, a score, the source modality that produced it, the chunk's freshness, an optional snippet, and the matched_terms. The SearchSource enum names where a result came from:

SearchSource
lexical semantic symbol hybrid

IndexStats (returned by stats()) rolls these entities up into a health snapshot — file, chunk, symbol, and reference counts, embedding coverage, the last full sync time, and whether the FTS index is intact.

Where to go next