Skip to content

codemap Integration

vecgrep and codemap share intelligence bidirectionally over CLI --json — each tool is an optional accelerator that degrades to its own local capability, never a hard dependency.

Ownership boundary

ConcernOwnerThe other side must NOT
Resolved call/type/test/import graph, blast radius, hotspotscodemapre-derive it from import-regex when codemap answers
Durable, reindex-proof annotations pinned to a symbol/pathcodemapkeep its own; vecgrep writes into it (source='vecgrep')
Semantic recall over chunks (hybrid vector + BM25)vecgrepstand up a second siloed embed index
Cross-project agent memory (importance/tags/TTL, near-duplicate refusal, related-memory links, usage lift)vecgrepstore memories; codemap only recalls

When using both tools, configure Codemap's semantic.backend: vecgrep to avoid embedding the same repository twice. Codemap keeps its structural graph and Vecgrep keeps semantic chunks in Veclite. Structural exports reconcile through the durable join key (project_key, relative_path, start_line, fqn, kind) — never by merging stores or joining on bare symbol names (which collide).

What's wired

  • Structural rerankingvecgrep_search results are re-ranked by blending semantic similarity with codemap's structural component (final = semantic × (1−w) + structural × w, default weight 0.15). The structural component is hub-dominant: codemap's fan-in in_degree (down-weighted when shared_name > 1 marks a name-inflated hub) plus a minority learning-from-use term — codemap's query_frequency (how many past searches surfaced the symbol) takes a configurable share of the structural component (codemap.query_frequency_weight, env VECGREP_CODEMAP_QUERY_FREQUENCY_WEIGHT, default 0.2), so an equally-hubbed symbol agents actually query outranks one they ignore. When the hotspot feed carries no usage data at all (older codemap builds, or a never-queried project) the share collapses to zero and the hub score keeps its full weight. Reranked results show their structural score so agents can see why a hit ranked where it did.
  • Structural indexing — when codemap is enabled, vecgrep index consumes the paginated codemap export-symbols --json v1 contract. Each symbol's available docstring, signature, and source are embedded together, while search previews keep only clean source. Long symbols are split from the full validated file, and uncovered imports, globals, template/style blocks, and other gaps remain searchable as generic chunks. Stale, omitted, or invalid files fall back individually to vecgrep's built-in chunker; fresh files in the same export stay structural. Re-embedding is already selective: the incremental hash filter skips files whose content is unchanged, so a drifted working tree costs embeddings only for what actually moved.
  • Search-hit annotation — top search hits are resolved to their enclosing symbol via codemap symbol-at and annotated, so vecgrep relevance signals survive codemap reindexes.
  • Blast-radius-scoped searchvecgrep_investigate (and symbol: on vecgrep_search) calls codemap impact to compute a changed symbol's blast radius, then scopes the semantic search to that file allow-list.
  • Peer statusvecgrep_status / vecgrep_index cross-read codemap's index freshness and hint when a reindex is needed.
  • Ingestion receipt — every configured indexer writes a small project-scoped receipt.v1.json under vecgrep's data directory. vecgrep status --format json exposes it as ingestion_receipt, including requested/effective mode, the codemap contract fingerprint when available, actual structural/gap/local counts, bounded fallback reasons, a unique attempt_id, scope_complete, and separate ingestion/postflight success. A new attempt invalidates the previous proof before index mutation; path-scoped runs intentionally remain incomplete until a full-project pass can certify the whole index. The receipt never shells out to codemap when read and never stores arbitrary provider or command error text.
  • Bounded freshness proof — status surfaces compare the working tree with vecgrep's persisted raw-source hashes, verify the receipt's last_success, and, when structural chunks were consumed, call only codemap structural-manifest --json. The manifest is timeout/output bounded and must match schema v1, export schema v1, project key, fingerprint, completeness, and freshness. When the working tree has drifted, the manifest's additive per-file delta (changed_files/new_files/ deleted_files) is surfaced verbatim inside the freshness report, so an agent sees which files moved instead of only how many. Status never downloads export-symbols; legacy, corrupt, unavailable, or mismatched evidence reports freshness.state: unknown until a successful vecgrep index --full rebuilds the proof. A durable project tombstone also forces unknown if a multi-collection delete/reset is interrupted, so retained hashes can never certify missing or ghost chunks.
  • Certified delta re-ingestion — when an index run starts and the codemap manifest attests a reindex_delta whose from_fingerprint is exactly the fingerprint vecgrep's last complete receipt certified and whose to_fingerprint is the manifest's current fingerprint, the run inverts the old trade-off: instead of re-reading the whole export, it ingests only the delta files through the codemap.structural-export.v2 filtered export (--files-from, filter fingerprint verified on every page), drops the delta-deleted files' chunks, and writes a scope-complete receipt carrying the attested to_fingerprint. Records for every other file are identical between the two exports, so unchanged files keep their certified chunks. Any doubt — no receipt, no attestation, incomplete or erroring previous run, producer unavailable, fingerprint off by one byte — falls back to the full export path. The attestation is codemap's own claim about its last run; vecgrep never derives it.
  • Vector-free health checksvecgrep status --lightweight reads the project-isolated health/<project-key>/manifest.v1.json sidecar and scans source hashes without opening VecLite. It is the preferred polling path for editors and agents; the full status command remains available for detailed vector/provider diagnostics.
  • Reverse direction — codemap shells vecgrep search --format json as its semantic-search fallback and recalls vecgrep memories into its context reports.

Invariants

  • CLI-only, one hop: integration happens by shelling the peer binary with --json; neither tool links the other's packages or reads the other's store.
  • Best-effort: if the peer binary is missing, stale, or errors, the caller falls back to its local capability and says so in a status note. Set codemap.structural_chunks: required (or pass --structural-chunks required) when CI should fail instead.
  • Structural export pages must agree on schema, project key, and index fingerprint. Record paths are project-relative and slash-canonical on every OS, and each record carries a contiguous one-based ordinal so pagination remains verifiable even when long signature/docstring sort fields are truncated for transport. vecgrep validates the public contract and current source; it never reads codemap's SQLite database.
  • Contract drift between the tools is guarded by golden tests (internal/mcp/codemap_golden_test.go).

Preserve a hit's symbol identity

Structural search hits include optional selector and source_hash fields. The selector is {file,start_line,fqn,kind} for the original declaration; start_line on the hit itself describes the preview chunk and can differ for split symbols. Generic chunks have no selector. source_hash is the raw file's SHA-256, independent of the embedding or chunk hash. Existing indexes gain these fields when indexed again; the structural chunk profile change triggers rebuilds.

Pass selector unchanged to codemap impact --selector '<json>' --json or to MCP operations accepting selector. Do not substitute the chunk ID or merge same-named symbols across files. Check index freshness and per-result graph confidence before using a hit to justify a change.

A local integration test verifies the real Codemap export, Vecgrep ingestion, Veclite persistence, search projection and the exact impact round trip:

sh
VECGREP_TEST_CODEMAP_BIN=/absolute/path/to/codemap go test ./internal/app -run TestCodemapProducerThroughStoredSearch

It uses temporary data and a deterministic embedding stub; no model service is called. This checks the contract, not semantic ranking quality.

Local-first semantic code search.