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.
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-core | Graph primitives: Node, Edge,
EdgeKind, VName (Kythe-style address), NodeId (BLAKE3
content hash), and ppr_weight(). Every other crate sits on top of it. |
travsr-error | One shared error taxonomy (StoreError,
IndexError, TravsrError) so any crate can report failures without
pulling in weight. |
travsr-ipc | The control-plane transport between the CLI and the running daemon: a Unix socket on macOS/Linux, a named pipe on Windows. |
travsr-config | Layered, 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-rerank | The 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. |
Layer 1 · parse and store
travsr-analysis | Phase 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-store | SQLite (WAL) persistence: the nodes / edges / files /
meta tables, FTS5 full-text search, schema migrations, and RBAC columns. Depends on
core, error. |
travsr-plugin-protocol | The wire contract for sidecar plugins
(language and embed): message structs sent as length-prefixed frames. Depends on
core, error. |
travsr-plugin-sdk | The small harness a sidecar binary links against
to implement the protocol. Depends on plugin-protocol, core. |
Layer 2 · analyze
travsr-indexer | Orchestrates 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-retrieval | The 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-host | Owns 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. |
Layer 3 to 5 · interface, orchestrate, binary
travsr-mcp | The 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-daemon | The 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-cli | The 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. |
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}.rsThe 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.rsStorage: 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.
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.)
The sidecar packages
Not everything is a Rust crate. Four helper packages live under
packages/.
travsr-npm | The @travsr.com/travsr wrapper published to
npm; downloads the right prebuilt binary on install. |
travsr-vscode | The VS Code extension: status bar, code lens, hover, and the Cytoscape graph panel. |
travsr-lsif-ts | The built-in TypeScript/JavaScript LSIF emitter used for Phase B. |
travsr-lsif-py | The Python LSIF emitter. |
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”.
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_symbol | find a symbol (or NL query) |
get_dependencies | what this depends on |
get_callers | who calls this (with call-site path:line) |
get_blast_radius | what a change could break |
get_execution_path | path A → B (PCST) |
get_context | full pipeline → token budget |
get_snippets | source snippets for a symbol (4-tier disambiguation) |
find_references | every use of a symbol, all languages |
find_pattern | match a structural pattern across the graph |
get_repo_map · repo_languages | structure & detected languages |
get_graph_stats · get_lang_status · get_graph_json | stats & raw graph |
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.
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.