cartog — Code Graph Navigation Skill
When to Use
Use cartog before reaching for grep, cat, or file reads when you need to:
- Find code by name, concept, or behavior →
cartog rag search "query" - Understand the structure of a file →
cartog outline <file> - Find who references a symbol →
cartog refs <name>(or--kind callsfor just callers) - See what a function calls →
cartog callees <name> - Assess refactoring impact →
cartog impact <name> --depth 3 - Understand class hierarchies →
cartog hierarchy <class> - See file dependencies →
cartog deps <file>
Why cartog Over grep/glob
cartog pre-computes a code graph (symbols + edges) with tree-sitter and stores it in SQLite. Compared to grep/glob:
- Fewer tool calls: 1 command vs 3-6 grep/read cycles
- Transitive analysis:
impact --depth 3traces callers-of-callers — grep can't do this - Structured results: symbols with types, signatures, and line ranges — not raw text matches
Workflow Rules
-
Before you grep or read a file to understand structure, query cartog first.
-
Search routing — pick the right strategy based on the query:
A. Semantic search (
cartog rag search "<query>") — default for all searches. Handles keyword matching (FTS5), vector similarity, and cross-encoder reranking in a single call. Works for both natural language and keyword-style queries. Always use ONE call with the full query — never split a query into multiple rag search calls.cartog rag search "authentication token validation" cartog rag search "contract management and timesheet signing" cartog rag search "config"B. Structural search (
cartog search <name>) — use only when you need a symbol name to feed intorefs,callees,impact, orhierarchy. These commands require exact symbol names, not search results.cartog search validate_token cartog search AuthService --kind classRouting rules:
- Need to find code? → A (rag search) — always
- Need a symbol name for
refs/callees/impact? → B (search) first, then the structural command
-
When using
cartog searchto locate a symbol beforerefs/callees/impact:- Exactly one result → use that symbol name and file, proceed.
- Multiple results, same name, different files → add
--file <path>to disambiguate. - Multiple results, different names → add
--kind <kind>to filter, then re-evaluate. - Never pass an ambiguous name to
refs/callees/impact— the result will be wrong.
-
Use
cartog outline <file>instead ofcat <file>when you need structure, not content. -
Before refactoring, run
cartog impact <symbol>to see the blast radius. -
Only fall back to grep/read when cartog doesn't have what you need (e.g., reading actual implementation logic, string literals, config values).
-
After making code changes, run
cartog index .to update the graph.
Do / Don't
DO:
- Use
cartog rag searchas your default search — it combines FTS5 keyword + vector + reranking in one call - Use
cartog searchonly to get a symbol name for structural commands (refs,callees,impact,hierarchy) - Trust that
rag searchdegrades gracefully — FTS5 works even without vector embeddings
DON'T:
- Run
cartog searchandcartog rag searchin parallel for the same query — this wastes a tool call.rag searchalready includes FTS5 keyword matching internally - Split one query into multiple
rag searchcalls with rephrased variants — one call is enough. The hybrid search (FTS5 + vector + reranker) handles synonyms and related terms internally - Block on RAG embedding at setup — background indexing is fine,
rag searchworks immediately with FTS5 + reranker - Assume
rag searchrequiresrag index— it works (at reduced quality) with justcartog index . - Chain multiple
cartogCLI commands with&&or|— each invocation opens a fresh SQLite connection with full initialization overhead (PRAGMAs, schema checks, cold cache). Run them as separate tool calls instead - Pipe
cartogoutput throughgrep— cartog already returns focused, structured results. Filtering with grep discards context (line numbers, kinds, file paths) and can break&&chains when grep finds no match (exit code 1) - Combine unrelated cartog queries in one bash command — this creates false dependencies and hides failures. See
references/query_cookbook.md→ "Anti-patterns to avoid" for examples
Setup
Before first use, ensure cartog is installed and indexed:
# Install if missing
command -v cartog || bash scripts/install.sh
# Run the setup script (handles all 3 phases)
bash scripts/ensure_indexed.sh
Search quality tiers
cartog rag search works at three quality levels depending on setup state:
| Tier | After | FTS5 | Reranker | Vector | Quality |
|---|---|---|---|---|---|
| 1 | cartog index . | Yes | No | No | Keyword matching only |
| 2 | + cartog rag setup | Yes | Yes | No | Keyword + neural reranking |
| 3 | + cartog rag index . | Yes | Yes | Yes | Full hybrid (best) |
The setup script runs tier 1+2 blocking, then tier 3 in the background.
cartog rag search is usable immediately after tier 2 — vector search becomes available
transparently once background embedding completes.
First run: tier 2 downloads ~1.2GB of ONNX models (cached in
~/.cache/cartog/models/). This may take a few minutes — do not abort. Subsequent runs are instant.
Commands Reference
Index (build/rebuild)
cartog index . # Index current directory
cartog index src/ # Index specific directory
cartog index . --force # Re-index all files (ignore cache)
Search (find symbols by partial name)
cartog search parse # prefix + substring match
cartog search parse --kind function # filter by symbol kind
cartog search config --file src/db.rs # filter to one file
cartog search parse --limit 10 # cap results
Returns symbols ranked: exact match → prefix → substring. Case-insensitive. Max 100 results.
Valid --kind values: function, class, method, variable, import.
RAG Search (hybrid keyword + semantic)
cartog rag search "authentication token validation"
cartog rag search "error handling" --kind function
cartog rag search "database schema setup" --limit 20
Uses hybrid retrieval: FTS5 keyword matching + vector KNN, merged via Reciprocal Rank Fusion. When the cross-encoder model is available, results are re-ranked for better precision.
Outline (file structure)
cartog outline src/auth/tokens.py
Output shows symbols with types, signatures, and line ranges — no need to read the file.
Refs (who references this?)
cartog refs validate_token # all reference types
cartog refs validate_token --kind calls # only call sites
Available --kind values: calls, imports, inherits, references, raises.
Callees (what does this call?)
cartog callees authenticate
Impact (transitive blast radius)
cartog impact SessionManager --depth 3
Shows everything that transitively depends on a symbol up to N hops.
Hierarchy (inheritance tree)
cartog hierarchy BaseService
Deps (file imports)
cartog deps src/routes/auth.py
Stats (index summary)
cartog stats
Watch (auto re-index on file changes)
cartog watch . # watch current directory
cartog watch . --rag # also re-embed symbols (deferred)
cartog watch . --debounce 3 --rag-delay 30 # custom timings
Serve (MCP server)
cartog serve # MCP server over stdio
cartog serve --watch # with background file watcher
cartog serve --watch --rag # watcher + deferred RAG embedding
JSON Output
All commands support --json for structured output:
cartog --json refs validate_token
cartog --json outline src/auth/tokens.py
cartog --json rag search "authentication"
Refactoring Workflow
Before changing any symbol (rename, extract, move, delete):
- Identify —
cartog search <name>to confirm the exact symbol name and file - Map references —
cartog refs <name>to find every usage - Assess blast radius —
cartog impact <name> --depth 3for transitive dependents - Check hierarchy —
cartog hierarchy <name>if it's a class (subclasses need updating too) - Plan change order — update leaf dependents first, work inward toward the source
- Apply changes — modify files
- Re-index —
cartog index .to update the graph - Verify — re-run
cartog refs <name>to confirm no stale references remain
Decision Heuristics
| I need to... | Use |
|---|---|
| Find code by name, concept, or behavior | cartog rag search "query" |
| Get a symbol name for structural commands | cartog search <name> |
| Know what's in a file | cartog outline <file> |
| Find usages of a function | cartog refs <name> (--kind calls for just callers) |
| See what a function calls | cartog callees <name> |
| Check if a change is safe | cartog impact <name> --depth 3 |
| Understand class hierarchy | cartog hierarchy <class> |
| See file dependencies | cartog deps <file> |
| Read actual implementation logic | cat <file> (cartog indexes structure, not content) |
| Search for string literals / config | grep (cartog doesn't index these) |
| Nothing from search or rag | Fall back to grep |
Limitations
- Structural/heuristic resolution, not full semantic. ~90% accuracy for cross-file references.
- Currently supports: Python, TypeScript/JavaScript, Rust, Go, Ruby, Java.
- Does not index string literals, comments (except docstrings), or config values.
- Method resolution is name-based —
foo.bar()resolvesbar, notFoo.barspecifically.
RAG search limitations
- No substring matching:
"valid"does NOT matchvalidate_token. FTS5 is token-based. Ifrag searchreturns no results for a known symbol name, fall back tocartog searchwhich supports substring matching. - Graceful degradation:
rag searchworks withoutrag setuporrag index(FTS5-only). Quality improves with each setup tier (see Search quality tiers above). - Scores are relative:
rrf_scoreandrerank_scorevalues are only meaningful for ranking within a single query — don't compare scores across different queries. - Re-ranking latency: cross-encoder scores all candidates in a single batch ONNX call (up to 50 candidates). Expect ~150-500ms total overhead depending on candidate count.