The Indexing Pipeline
How does raw source code become that clean graph, and stay correct? The rule (principle #2) is “always fresh”: the moment you commit, the map updates. Here’s the assembly line that makes it happen.
It starts with a git commit
When you run travsr init, it installs a git hook -
a tiny script git runs automatically after every commit. That script wakes the travsr
daemon (a background helper), which figures out what changed and re-indexes
only those files.
Think of a city that takes a mini-census every time a building changes. It doesn’t re-survey the whole city, only the block that was renovated. Fast, and always current.
# .git/hooks/post-commit (installed by travsr init)
#!/bin/sh
exec travsr hook-run --from-hook
crates/travsr-daemon/src/hook.rs
Watch the assembly line
Press play. This is the real sequence the daemon runs for each changed file.
Press play to walk through the pipeline stage by stage.
The stages, explained simply
Find what changed (git diff)
The daemon asks git which files the commit touched. Only those enter the pipeline.
Skip unchanged files (SHA-256 hash)
Each file’s contents are hashed. If the hash matches what’s stored in the files table,
the file is byte-for-byte identical and is skipped entirely. This is what makes re-indexing cheap.
Phase A: Tree-sitter (fast structural pass)
Tree-sitter parses each file into a syntax tree at high speed and pulls out the obvious structure:
functions, classes, methods, imports, and the “contains” relationships. Config and data files
(JSON, YAML, TOML, XML) are parsed here too, as nodes with
configures / external-dependency edges. No language server needed.
This is the aerial drone survey: quick, covers everything, gets the shape of the city right.
Phase B: LSIF / SCIP (precise semantic pass)
For supported languages, travsr can run real compiler-grade tools (rust-analyzer, scip-python,
scip-typescript, scip-java, scip-clang…) that resolve exactly which function a call points to,
even across files. 16 languages are in the catalog; the built-ins
(TypeScript/JavaScript, Rust, Python) run natively in-process with zero install, the rest ship as
downloadable “language plugins”, installed with travsr lang install.
This is the ground survey crew: slower, but pinpoint-accurate about which road connects to which.
Unify the two passes
The scip_unifier merges Phase B’s precise symbols onto Phase A’s nodes, so you get
both full coverage and accuracy. Edges carry a “provenance” marker recording which pass found them.
Write to graph.db + recompute importance
New nodes and edges are written to SQLite in one batch. Then travsr recomputes k-core shells (Chapter 3) so it always knows which parts of the code are structurally central.
crates/travsr-store · crates/travsr-retrieval/src/kcore.rsKeep the graph clean (GC + fsck)
When files are deleted or symbols renamed, their old nodes and edges become orphans.
A tiered garbage collector reclaims them, and travsr fsck checks and
repairs graph integrity on demand. A delete-trigger also logs removed nodes so the separate
embedding database evicts their vectors, no stale answers, ever.
Because steps 1–2 only touch changed files, indexing after a normal commit is near-instant. The graph is never stale, and the AI never reads outdated structure.