The code graph that lives next to git.
Source code is a deterministic graph, not unstructured text. Travsr builds that graph on every commit and exposes it via MCP so AI agents traverse real edges instead of guessing from vector chunks.
# 1. Install (either one)
curl -fsSL https://travsr.com/install.sh | sh # shell installer, no Node needed
npm install -g @travsr.com/travsr # npm
# 2. Initialize your repo (requires git)
cd your-project
git init # skip if already a git repo
travsr init # indexes every tracked file → .travsr/graph.db
# auto-registers in ~/.travsr/registry.json
# 3. Connect to Claude Desktop (set once, works for all repos)The shell installer supports --version <tag> to install a specific release
instead of latest stable (e.g. sh -s -- --version v1.0.0), --system
(installs to /usr/local/bin, e.g.
curl -fsSL https://travsr.com/install.sh | sh -s -- --system, since a piped
script can only take flags via sh -s --), and TRAVSR_INSTALL_DIR to
override the default ~/.local/bin. If travsr.com is unreachable, use the
GitHub fallback URL:
https://github.com/Travsr-com/travsr/releases/latest/download/install.sh.
See SECURITY.md for what the script verifies before installing.
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"travsr": {
"command": "travsr",
"args": ["mcp", "--stdio", "--global"]
}
}
}Restart Claude Desktop. Ask: "Who calls PaymentService.charge?"
No
cwdneeded.--globalreads~/.travsr/registry.jsonwhichtravsr initpopulates automatically. Every repo you init becomes immediately available, no config changes required.
Every release ships to three npm dist-tags. ^-range installs never resolve to
a pre-release, so latest is always what you get unless you opt in explicitly:
npm i -g @travsr.com/travsr@latest # stable (default if you omit the tag)
npm i -g @travsr.com/travsr@rc # release candidate, final gates in flight
npm i -g @travsr.com/travsr@beta # earliest builds, opt-in testing onlyA beta and its later-promoted rc/latest releases are byte-identical
binaries: promotion re-publishes the same signed artifact under a new tag
rather than rebuilding, so what you tested on beta is exactly what ships to
latest. Every tarball is cosign-signed and SLSA-attested regardless of
channel; see SECURITY.md for verification steps.
The channels move independently, so beta can be newer than rc in content
while sorting below it under semver. v1.0.0-beta.2 was a fresh build cut
after v1.0.0-rc.1 rather than a promotion of it, and v1.0.0 was promoted
from that beta rather than from rc.1, so the stable bits are the ones the beta
channel tested. travsr --version reports the tag base plus the commit it was
built from, which is what tells two builds apart.
Travsr maintains a global registry at ~/.travsr/registry.json. Every
travsr init call registers that repo automatically.
# Init each repo once
cd ~/projects/repo-a && travsr init
cd ~/projects/repo-b && travsr init
cd ~/projects/task-manager && travsr init
# See all registered repos
travsr repos| Name | DB Path | Exists |
| repo-a | /Users/you/projects/repo-a/.travsr/graph.db | yes |
| repo-b | /Users/you/projects/repo-b/.travsr/graph.db | yes |
| task-manager | /Users/you/projects/task-manager/.travsr/graph.db | yes |
The single --global MCP server serves all of them. When you ask about a
symbol, it searches all registered repos and prefixes results with
[repo-name] so you always know which codebase the answer came from.
Travsr speaks MCP, the open standard for connecting AI agents to tools.
{
"mcpServers": {
"travsr": {
"command": "travsr",
"args": ["mcp", "--stdio", "--global"]
}
}
}Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project):
{
"mcpServers": {
"travsr": {
"command": "travsr",
"args": ["mcp", "--stdio", "--global"]
}
}
}Requires VS Code 1.99+. Add to .vscode/mcp.json in your project:
{
"servers": {
"travsr": {
"type": "stdio",
"command": "travsr",
"args": ["mcp", "--stdio", "--global"]
}
}
}In the Cline extension settings → MCP Servers → Add server:
{
"travsr": {
"command": "travsr",
"args": ["mcp", "--stdio", "--global"],
"disabled": false
}
}Add to ~/.continue/config.json under mcpServers:
{
"mcpServers": [
{
"name": "travsr",
"command": "travsr",
"args": ["mcp", "--stdio", "--global"]
}
]
}If you prefer to point at one specific repo, use --db:
travsr mcp --stdio --db /path/to/repo/.travsr/graph.dbOr omit both flags and run from inside the repo; travsr discovers the db from the current git root.
All tool responses are wrapped in a <travsr-data> envelope and sanitized
before being returned, so returned content is safe to pass directly into LLM
context (control characters stripped, prompt-injection vectors neutralised).
In global mode, tools that accept a file or symbol argument also accept
an optional repo parameter to target a specific registered repo. Omitting
repo searches all registered repos, with one exception: the observability
tools (get_index_status, get_daemon_logs, get_graph_health) never
aggregate across repos. Supply repo when more than one repo is registered,
or the call returns an ambiguity error naming repos_list.
Query tools (available in both single-repo and global mode):
| Tool | Description |
|---|---|
get_dependencies(file) |
All imports/dependencies of a file |
get_callers(symbol) |
All nodes with an incoming edge to a symbol |
find_references(symbol, path?) |
Every use site of a symbol as path:line, across every indexed language; path scopes an overloaded name to a file, directory, or path fragment |
find_pattern(pattern, scope?, fixed?) |
Graph-scoped textual/regex search (git grep-style), optionally confined to a path prefix or to files importing a symbol |
get_blast_radius(file) |
Files transitively affected if the given file changes |
search_symbol(name) |
Symbol definitions matching a name across the graph |
get_repo_map |
Structural overview of the indexed repository |
get_execution_path(source, sink) |
Lowest-cost execution path between two symbols, plus nearby context |
get_context(query, token_budget) |
PPR traversal ranked by relevance, budget-capped by knapsack |
get_graph_stats |
Node/edge counts, schema version, last-indexed SHA |
get_graph_json(query, direction, depth) |
Subgraph as structured JSON for graph renderers |
get_snippets(symbol) |
Source snippets for a symbol with file and line context |
get_lang_status |
Phase B indexer status for each language in the repo |
repo_languages |
Languages detected in the indexed repository |
get_index_status |
Index freshness/completeness: staleness, Phase A/B state, semantic readiness |
get_daemon_logs(tail, level) |
Recent daemon log entries, parsed and sanitized (read-only) |
get_graph_health |
Read-only graph integrity report: ghost paths, orphan edges, lexical parity |
Repo management tools (global mode):
| Tool | Description |
|---|---|
repos_list |
List all globally registered repos |
repos_remove(repo) |
Remove a repo from the global registry |
repos_prune |
Remove registry entries whose db path no longer exists |
Synonym tools (query expansion):
| Tool | Description |
|---|---|
synonym_add(term, alias) |
Add a single term/alias pair |
synonym_set(term, aliases) |
Replace all aliases for a term atomically |
synonym_remove(term, alias) |
Remove one term/alias pair |
synonym_remove_term(term) |
Remove all aliases for a term |
synonym_list |
List all configured synonyms |
synonym_reset |
Clear all synonyms |
In global mode, tools that accept a file or symbol argument also accept an optional repo parameter to target a specific registered repo. Omitting repo searches all registered repos.
travsr init Index the repo, install git hook, register globally
travsr init --no-connect Index the repo without wiring detected AI tools to Travsr
travsr connect Detect installed AI coding tools and wire each to the Travsr MCP server
travsr connect --print Show what connect would write, without touching the filesystem
travsr connect --remove Undo a previous connect run
travsr daemon start/stop/status Start, stop, or check the background daemon
travsr daemon logs Print daemon log entries (--follow, --level, --since, --json)
travsr daemon lsp Show the last diagnostics overlay the editor extension reported
travsr repos List all globally registered repos
travsr status Show node/edge counts, schema version, last-indexed SHA
travsr fsck Report ghost nodes and orphan edges (add --fix to repair)
travsr config get/set <key> Inspect or set a layered config key (global, or --repo for this repo)
travsr ask <query> Graph-grounded answer for a question, or a bare symbol name
travsr ask --examples What you can ask, with runnable examples from your own index
travsr ask --cmds Every command travsr supports, grouped by what it is for
travsr references <symbol> Every use site of a symbol as path:line (add --format json)
travsr pattern <regex> Graph-scoped text search for what the graph does not model
travsr index Index without installing hooks or registering the repo
travsr graph <query> Show dependency graph for a symbol or file
travsr graph --all Show graph for the entire indexed repository
travsr mcp --stdio Start the MCP stdio server (single-repo, cwd-based)
travsr mcp --stdio --global Start the MCP stdio server (all registered repos)
travsr mcp --stdio --db <path> Start the MCP stdio server (explicit db path)
travsr lang list Per-language analysis status, prerequisites, and this repo's state
travsr lang status Alias of `lang list`
travsr lang install <language> Set up full cross-file analysis for a language, and enable this repo
travsr lang detect Scan the repo and install what it finds (--yes to skip prompts)
travsr lang remove <language> Unregister a language analyzer
travsr lang allow-unsandboxed <lang> Windows only: permit a language whose build tooling cannot run
inside isolation (Java, Scala) to run with your own privileges
travsr synonym add <term> <alias> Add a query synonym
travsr synonym list List all configured synonyms
travsr synonym remove <term> Remove a synonym term
travsr embed list List available embedding models
travsr embed init Initialize the embedding index for this repo
travsr embed status Show embedding index status
travsr embed reindex Fill in missing embeddings (--rebuild to re-embed everything)
travsr embed switch <model> Switch to a different embedding model
travsr embed reconfigure Change the reindex worker budget/priority and apply it immediately
travsr embed gc Reclaim disk space held by inactive embedding models (dry-run; add --apply)
travsr embed calibrate Re-measure semantic floors on the existing index without re-embedding
travsr rerank install Download the cross-encoder reranker model
travsr rerank status Show whether the reranker model is installed
AI tool auto-wiring. travsr init (unless run with --no-connect) and
travsr connect detect installed AI coding tools, Claude Code, Cursor, VS Code
Copilot, Gemini CLI, Antigravity, Codex, Windsurf, and Zed, and for each one
register the travsr mcp --stdio server. Pass --rules to also write an
always-on rules file telling the agent to query Travsr before grep or a raw
file read; it is opt-in because an agent re-reads it on every turn of every
conversation, while MCP already hands the model every tool name, description
and schema before the conversation starts. Generated files are
local and git-ignored by default (a committed MCP server definition is a
clone-and-run-arbitrary-command vector), written only into files a strict-JSON
check confirms Travsr already owns or that don't exist yet, so an existing
hand-authored config is skipped rather than clobbered. Pass --commit to
opt into committing the generated files instead, --tool <id> to wire a
single tool, --print to preview without writing, or --remove to undo a
previous run.
GPU acceleration (optional). travsr embed init installs a CPU-only sidecar
by default, which works everywhere with nothing to set up. Set
TRAVSR_EMBED_ACCEL to install a hardware-accelerated build instead:
| Value | Effect |
|---|---|
off (default) |
CPU build |
auto |
picks an accelerated build only where it needs no host setup (currently DirectML on Windows x86_64) |
directml |
Windows x86_64. Any DX12 GPU: Intel, AMD or NVIDIA |
cuda |
Linux x86_64 + NVIDIA. Requires a host CUDA runtime, cuDNN and glibc 2.38+ |
TRAVSR_EMBED_ACCEL=auto travsr embed initThis works whether or not a sidecar is already installed: if the installed one
has no accelerator, it is reinstalled rather than reported as ready. No
--reinstall needed, and re-running the same command afterwards is a no-op.
auto never selects CUDA, because that build needs a host CUDA runtime the
installer cannot verify. Accelerated builds also install the ONNX Runtime
libraries they load; if the GPU turns out to be unusable at run time the sidecar
logs why and falls back to its CPU engine, so a wrong guess costs speed, not
function. macOS needs none of this, its default build already uses CoreML, and
Linux aarch64 has no accelerated build at all.
Visualise the dependency graph from any symbol or file as an ASCII tree, Graphviz DOT, or structured JSON.
# ASCII tree (default): what does extension.ts import and define?
travsr graph extension.ts
# Who calls PaymentService.charge?
travsr graph PaymentService.charge --direction callers
# Both directions, depth 2
travsr graph service.ts --direction both --depth 2
# Render as SVG (requires graphviz: brew install graphviz)
travsr graph extension.ts --format dot | dot -Tsvg -o graph.svg && open graph.svg
# Machine-readable JSON for AI tools
travsr graph extension.ts --format json
# Whole-repository graph
travsr graph --all --format dot | dot -Tsvg -o repo.svg && open repo.svg
travsr graph --all --format jsonFlags:
| Flag | Default | Description |
|---|---|---|
--direction |
deps |
deps · callers · both |
--depth |
3 |
Maximum traversal depth |
--format |
tree |
tree · dot · json |
--all |
(none) | Dump the entire indexed graph (mutually exclusive with <query>) |
JSON output schema (--format json):
{
"schema_version": 1,
"summary": {
"mode": "query",
"root": "file",
"root_path": "src/index.ts",
"total_nodes": 6,
"total_edges": 5,
"kinds": { "file": 1, "function": 2, "import": 2, "variable": 1 }
},
"nodes": [
{ "id": "...", "signature": "fn:activate", "label": "activate", "kind": "function",
"path": "src/index.ts", "language": "typescript", "depth_from_seed": 1 }
],
"edges": [
{ "from_id": "...", "to_id": "...", "from": "file", "to": "activate", "kind": "defines/binding" }
]
}Install the Travsr extension from the VS Code Marketplace (travsr.travsr-vscode).
The extension connects to your local Travsr daemon over MCP and adds:
- Status bar: daemon connection state and indexed node count
- Code lens: inline "N callers" annotations on function definitions, escalating to a warning before you edit a high-blast file
- Hover: dependency list on import statements
- Graph panel: interactive dependency graph rendered with Cytoscape.js; kind filtering, two-hop traversal, node search, and an overlay of the diagnostics your language extensions report; open via the Travsr sidebar or the command palette (
Travsr: Show Graph) - Context Explorer: graph-ranked context for a natural-language query, grouped by how each result matched
- Languages panel: which languages have full cross-file analysis here and in this repository, what each one still needs, and a one-click install
- Stats panel: index and daemon health, plus a searchable daemon log with severity filters, a per-day file picker, and optional auto-refresh
- Repository picker: choose which of several open repos an action targets, shown in the status bar
The extension uses your installed travsr binary, resolved from travsr.binaryPath, then ~/.travsr/bin, then PATH, and offers to download a verified release build if none of those resolve. Set travsr.binaryPath in VS Code settings to pin it. The Languages panel needs the language-status fields a v1.0.0 or later binary reports; an older one is detected and named rather than rendered as a table of gaps.
| Backend | Flag | Notes | Status |
|---|---|---|---|
| SQLite + WAL | (default) | Zero setup, works everywhere | Available |
SQLite + WAL is the storage backend and requires no additional dependencies.
Kùzu was previously offered as an optional backend but was dropped
(see docs/adrs/ADR-018-drop-kuzu-backend.md). RocksDB remains a possible future
hyperscale backend.
git init && travsr init
└─▶ walks .ts / .tsx files (respects .gitignore)
└─▶ Tree-sitter parses each file
└─▶ Nodes + edges → .travsr/graph.db (SQLite WAL)
└─▶ post-commit hook installed
└─▶ repo registered in ~/.travsr/registry.json
git commit
└─▶ post-commit hook fires
└─▶ travsr hook-run <changed files>
└─▶ SHA-256 delta: only re-indexes changed files
└─▶ graph.db updated, last_commit SHA recorded
Graph stays current via the post-commit hook. Every committed change is
re-indexed automatically. The graph is also fully queryable immediately after
travsr init, before any commit.
Language support: TypeScript / TSX, Rust, Python, Go (builtin, zero configuration). Additional languages (Java, Kotlin, C#, Scala, PHP, Ruby, Swift) are available as Phase B indexers via travsr lang install.
| Algorithm | When used | Status |
|---|---|---|
| BFS depth-3 | get_dependencies / get_callers queries |
Available |
| Personalized PageRank (PPR) | get_context and deep traversal |
Available |
| PPR weighted | Score-aware PPR variant | Available |
| 0-1 Knapsack | Token budget cap on get_context results |
Available |
| Shortest path + λ-corridor | get_execution_path: lowest-cost path between two symbols, padded with nodes within λ=0.5 of that cost |
Available |
| k-core decomposition | Buried-middle recovery | Available |
| BM25 | Full-text ranked retrieval | Available |
| RBAC | Role-based access filtering on graph queries | Available |
get_context and ask also search your Markdown documentation (ADRs, RFCs,
design docs) alongside code by default, so a query can surface the
rationale behind code, not just the code itself. Turn it off with
travsr config set docs.enabled false.
| Kind | Meaning |
|---|---|
depends |
File imports another module |
defines/binding |
File or class defines a symbol (function, method, variable) |
ref/call |
Call-site reference |
ref/field |
Field read (x.foo), a use site that is not a call, so it stays out of the call graph get_callers and get_blast_radius traverse |
exports |
Symbol exported from a module |
All MCP tool outputs are passed through a sanitization pipeline before being returned to the client:
- Truncated to a safe maximum length
- C0/C1 control characters stripped
<and>escaped to prevent XML/HTML injection in tool descriptions- Wrapped in a
<travsr-data>structural envelope
Path traversal and argument injection are rejected at the tool dispatch layer
(../, ..\\, absolute paths, null bytes, %-encoded traversal sequences).
Release artifact signing: Every release tarball is signed with cosign keyless signing using the GitHub Actions OIDC token. SLSA v1.0 provenance is attached to every release via GitHub attestations. See SECURITY.md for verification instructions.
Supply chain auditing: All Rust dependencies are audited on every CI run
with cargo-deny (CVE advisories,
license policy, banned crates). A nightly OSV scan checks for new CVEs against
Cargo.lock and package-lock.json.
git clone https://github.com/Travsr-com/travsr
cd travsr
# Build (SQLite backend)
cargo build --release # requires Rust 1.88+
# Override the npm-installed binary with a local build
cp target/release/travsr $(which travsr)
# or
export TRAVSR_BINARY=/path/to/travsr/target/release/travsrPlatform support: macOS (x86_64 + arm64), Linux (x86_64 + aarch64), Windows (x86_64). Pre-built binaries are available on the Releases page.
MSRV: Rust 1.88 (verified in CI on every commit).
-
not inside a git repositoryRungit initbeforetravsr init. -
not initialized: run travsr initRuntravsr initin the repo root before usinggraph,ask,status, ormcp. -
MCP server returns empty results in
--globalmode Runtravsr reposto verify the repo is registered andExistsshowsyes. If missing, re-runtravsr initin that repo. -
Stale entries in
travsr repos(Exists = no) Safe to ignore; they are skipped automatically. They appear when a repo was deleted or moved after being indexed. -
Binary not found after npm install? Set
TRAVSR_BINARY=/path/to/travsrto use a local build instead. -
Corporate proxy blocks the postinstall download? Same: set
TRAVSR_BINARYto skip the remote fetch.
See CHANGELOG.md for the full release history.
See CONTRIBUTING.md. Issues and PRs welcome. Licensed under Apache 2.0.