NCI
Architecture · Local index vs. RAG

Why a local index, not a vector store

RAG is a great default for prose. It is a poor default for code. Every NCI design decision falls out of choosing structure over similarity for the part of an agent’s context that is type-aware.

Side-by-side

ConcernRAG over node_modulesNCI’s local index
GranularityChunksSymbols
Retrieval shapetop-k similarityExact match by (package, version, name) + FTS5 fallback
LatencyNetwork + vector searchLocal SQLite open
DeterminismDepends on embedding modelByte-stable
PrivacyEmbeddings leave the machineNothing leaves the disk
VersioningTied to embedderTied to your lockfile
Update costRe-embedIncremental re-index — only changed packages

When RAG still helps

NCI is not a replacement for everything an agent needs. RAG is still the right tool for:

  • The user’s own documentation, READMEs, design docs.
  • Long-form code (think handlers, business logic) that has no public API.
  • Search across history (PRs, issues) where similarity is the goal.

The right shape is “NCI for type-aware questions about libraries, RAG for prose-aware questions about your project”. They sit side-by-side in the agent’s tool catalog, not in competition.

What this buys the agent

  • The agent never re-asks the same question.
  • It never paraphrases a signature wrong.
  • It never invents a method that does not exist.
  • It can answer “is useState part of the public API of the version of React I have?” with one tool call.

Where the size argument breaks

The same symbols compress dramatically when stored as structured rows: one signature text + one js_doc text per declaration, indexed by FTS5 for free-text fallback. There is no separate vector store — the FTS index lives in the same SQLite file as symbols and ships at no additional cost.