Chapter 5 · High-Level Design (HLD)

The Architecture

travsr is written in Rust and split into 15 small libraries (“crates”). The split isn’t cosmetic, there’s an ironclad rule: dependencies only ever point one direction. No cycles, ever. That keeps the system easy to reason about and impossible to tangle.

HLD vs LLD This chapter is the high-level design: crates, subsystems, and how they fit together, in plain language. For exact byte layouts, algorithm parameters, and failure modes, see the companion Low-Level Design reference.

The dependency map

Arrows mean “uses”. Read it bottom-up: the foundation (core) depends on nothing; each layer above builds on the ones below. Click any crate.

Crate dependency graph (no cycles)

Tap a crate to learn what it does

Each box is one Rust library with one job. The arrows are the real dependency rules from CLAUDE.md.

Every crate, in detail

The same 15 crates, read bottom-up in six layers. Every "depends on" line is the real set from that crate's Cargo.toml, not the idealized spine. No cycles, ever.

Layer 0 · foundation (no internal dependencies)

travsr-coreGraph primitives: Node, Edge, EdgeKind, VName (Kythe-style address), NodeId (BLAKE3 content hash), and ppr_weight(). Every other crate sits on top of it.
travsr-errorOne shared error taxonomy (StoreError, IndexError, TravsrError) so any crate can report failures without pulling in weight.
travsr-ipcThe control-plane transport between the CLI and the running daemon: a Unix socket on macOS/Linux, a named pipe on Windows.
travsr-configLayered, typed configuration (global + per-repo, validated). It backs reindex resource governance: capacity limits, cancellation, and live reconfiguration so a large reindex stays within bounded CPU and memory. No internal dependencies.
travsr-rerankThe in-process cross-encoder relevance arbiter (RFC-021): reranks graph-retrieved candidates against the natural-language query with an ONNX model (tract-onnx). Feeds its score into seed selection's PPR personalization weight rather than just reordering results after the fact (RFC-022). No internal dependencies, only external crates.
crates/travsr-core/src/lib.rs · travsr-error · travsr-ipc · travsr-config · travsr-rerank

Layer 1 · parse and store

travsr-analysisPhase A. Tree-sitter parsers for every language, plus the AST "skeleton" builder used for embedding text, snippet extraction, and data-format parsing (JSON, YAML, TOML, XML). Depends on core.
travsr-storeSQLite (WAL) persistence: the nodes / edges / files / meta tables, FTS5 full-text search, schema migrations, and RBAC columns. Depends on core, error.
travsr-plugin-protocolThe wire contract for sidecar plugins (language and embed): message structs sent as length-prefixed frames. Depends on core, error.
travsr-plugin-sdkThe small harness a sidecar binary links against to implement the protocol. Depends on plugin-protocol, core.
crates/travsr-analysis/src · travsr-store/src · travsr-plugin-protocol · travsr-plugin-sdk

Layer 2 · analyze

travsr-indexerOrchestrates indexing end to end: Phase A parsing, the Phase B LSIF/SCIP runners, the SCIP unifier that merges both passes, the sandbox, and file hashing for incremental updates. Depends on core, analysis, error.
travsr-retrievalThe algorithms: BFS, PageRank (ppr / ppr_weighted), PCST, k-core, BM25, the 0-1 knapsack budget solver, and RBAC edge filters. Depends on core, error, store.
travsr-plugin-hostOwns the trust boundary between the daemon and untrusted plugins. Runs native Phase B analyzers in-process and external ones in a sandbox, and drives the embedding sidecar (EmbedSidecar / EmbedSupervisor). Also enforces reindex governance. Depends on plugin-protocol, core, error, config, indexer, analysis.
crates/travsr-indexer/src/scip_unifier.rs · travsr-retrieval/src · travsr-plugin-host/src

Layer 3 to 5 · interface, orchestrate, binary

travsr-mcpThe Model Context Protocol server and the only external interface. Serves the tools over stdio and SSE. Depends on core, error, analysis, retrieval, rerank, store, plugin-host.
travsr-daemonThe long-running orchestrator where "always fresh" lives: git hook, file watcher, incremental reindex, the Phase B scheduler, and the query cache. Depends on core, ipc, mcp, indexer, retrieval, store, plugin-host, analysis.
travsr-cliThe travsr binary users run: init, ask, graph, mcp, lang, embed, synonym, references, pattern, config, fsck, serve, and more. Depends on daemon plus most lower crates, config, and ipc.
crates/travsr-mcp/src/server.rs · travsr-daemon/src · travsr-cli/src/main.rs

Runtime subsystems

Four moving parts do the real work at runtime.

The daemon keeps the graph fresh

A post-commit git hook fires the daemon; a file watcher catches uncommitted edits; a Phase B scheduler catches up on semantic edges in the background; a query cache keeps repeat lookups fast. Only changed files are re-parsed.

crates/travsr-daemon/src/{hook,watcher,phase_b_sched,query_cache}.rs

The plugin host isolates untrusted tools

The catalog has 16 languages. The built-ins (TypeScript/JavaScript, Rust, Python) run in-process, zero-install. External tools run in a sandbox at one of three tiers: a Standard sandbox for tools that need no network (Go, Ruby, PHP, Swift, Objective-C), a special POSIX-IPC tier (ulimit caps only, no network) for C, C++, and Dart, and an Elevated sandbox with an approved host allowlist for build tools that fetch dependencies (Java, Kotlin, C#, Scala).

crates/travsr-plugin-host/src/{trust,sandbox,transport}.rs · phase_b/catalog.rs

Storage: SQLite next to your code

The graph lives in .travsr/graph.db (SQLite + WAL) with FTS5 search and versioned migrations. Embeddings sit beside it in a separate embed.db with an HNSW index, so the graph write path never waits on the slow model writes. No server, no cloud, nothing to run.

crates/travsr-store/src/{lib,migration}.rs

MCP: two tool surfaces

Single-repo stdio exposes all 23 tools, including the synonym_* and repos_* management tools. Global mode and the SSE cloud transport expose 14 read-only tools shared by every client, no synonym or repo-registry writes. (A separate search_query_rewrite prompt helps clients turn a natural-language question into a search term.)

crates/travsr-mcp/src/server.rs (tools_list · tools_list_global) · sse.rs

The sidecar packages

Not everything is a Rust crate. Four helper packages live under packages/.

travsr-npmThe @travsr.com/travsr wrapper published to npm; downloads the right prebuilt binary on install.
travsr-vscodeThe VS Code extension: status bar, code lens, hover, and the Cytoscape graph panel.
travsr-lsif-tsThe built-in TypeScript/JavaScript LSIF emitter used for Phase B.
travsr-lsif-pyThe Python LSIF emitter.
packages/travsr-npm · travsr-vscode · travsr-lsif-ts · travsr-lsif-py

The one interface: MCP

Principle #4: MCP is the only way in. No REST API, no GraphQL. MCP (Model Context Protocol) is the open standard AI tools like Claude use to call external tools. travsr exposes its graph as a set of MCP “tools”.

Analogy

MCP is a universal power socket for AI. Any MCP-compatible assistant can plug into travsr and immediately use its tools, no custom wiring per assistant.

The tools an AI can call

search_symbolfind a symbol (or NL query)
get_dependencieswhat this depends on
get_callerswho calls this (with call-site path:line)
get_blast_radiuswhat a change could break
get_execution_pathpath A → B (PCST)
get_contextfull pipeline → token budget
get_snippetssource snippets for a symbol (4-tier disambiguation)
find_referencesevery use of a symbol, all languages
find_patternmatch a structural pattern across the graph
get_repo_map · repo_languagesstructure & detected languages
get_graph_stats · get_lang_status · get_graph_jsonstats & raw graph
crates/travsr-mcp/src/server.rs

Two ways to connect

stdio, local mode. Claude Desktop launches travsr mcp --stdio and talks over standard input/output. Your code never leaves your machine.

SSE, server mode for the optional cloud tier.

The --global flag serves every repo you’ve travsr init’d (tracked in ~/.travsr/registry.json) and labels each answer with its repo name.

{
  "mcpServers": {
    "travsr": {
      "command": "travsr",
      "args": ["mcp","--stdio","--global"]
    }
  }
}

The full request, end to end

Putting all five chapters together, here’s what happens when you ask Claude a question about your code:

You commit code

Git hook → daemon re-indexes changed files → graph stays fresh (Ch. 2).

You ask Claude a question

“Who handles payment retries?” Claude calls travsr’s get_context tool over MCP.

travsr finds seeds

BM25 keywords + (optional) semantic meaning pick starting nodes (Ch. 3 & 4).

Graph algorithms run

Weighted PageRank + k-core boost + knapsack budget select the most relevant code (Ch. 3).

Claude answers

It receives exact file:line context, real structure, far fewer tokens, no invented links.

The whole point, in one line

travsr replaces “guess from text” with “traverse a fresh, exact graph” - and uses decades-old, well-understood algorithms to do it, keeping the AI’s role small and reliable.

↺ Back to the overview