gitcortex-indexer
Incremental AST indexer for Git repositories. Reads only the files that changed since the last indexed commit, parses them with tree-sitter, resolves cross-file edges, and produces a GraphDiff ready to be written to any GraphStore backend.
Add to your project
[]
= "0.2"
= "0.2"
Quick start
use IncrementalIndexer;
use Path;
// Open an indexer rooted at the repo
let indexer = new?;
// Full index on first run — pass None for last_sha
let = indexer.run?;
println!;
// Incremental update — pass the last indexed SHA
let = indexer.run?;
// diff2 is empty if nothing changed
How it works
- Opens the repository with
git2to compute which files changed betweenlast_shaandHEAD. - Filters to supported extensions and respects
.gitcortex/ignorepatterns. - Parses each changed file in parallel (via
rayon) using the appropriate tree-sitter parser. - Resolves cross-file call edges, uses edges, implements edges, and more within the changed set.
- Unresolved edges (where the target lives in an unchanged file) are returned as deferred lists — the store resolves them against its full existing data.
- Synthesises
FileandFolderstructural nodes from the parsed file paths. - Returns the combined
GraphDiffand the new HEAD SHA to persist.
Supported languages
| Language | Extensions | What is extracted |
|---|---|---|
| Rust | .rs |
structs, traits, impl blocks, functions, methods, macros, calls, implements, uses, imports |
| Python | .py |
classes, functions, methods, decorators, properties, generators, calls, inherits, implements (Protocol), imports |
| TypeScript | .ts, .tsx |
classes, interfaces, functions, arrow functions, methods, calls, implements, inherits, imports, type annotations |
| JavaScript | .js, .jsx, .mjs, .cjs |
same as TypeScript (without type annotations) |
| Go | .go |
packages, structs, interfaces, methods, functions, calls, implements, imports |
| Java | .java |
classes, interfaces, enums, annotations, methods, calls, implements, inherits, throws, imports |
Ignore patterns
Create .gitcortex/ignore in your repo root (.gitignore syntax) to exclude files from indexing:
target/
dist/
node_modules/
**/*.generated.ts
**/*.pb.rs
The ignore crate evaluates these patterns — the same engine that backs ripgrep.
File size limit
Files larger than 512 KB are skipped silently. Override the limit by building a custom indexer wrapper.
Using a parser directly
Each language parser implements the LanguageParser trait and can be used standalone:
use ;
use Path;
let source = r#"
fn greet(name: &str) -> String {
format!("Hello, {name}!")
}
"#;
let parser = parser_for_path.unwrap;
let result = parser.parse?;
println!;
for node in &result.nodes
ParseResult contains:
nodes— all named entities found in the fileedges— intra-file edges (calls, contains, implements resolved within the same file)deferred_calls/deferred_uses/deferred_implements/ ... — cross-file references as(src_id, target_name)pairs
Integrating with a store
The GraphDiff returned by IncrementalIndexer::run is passed directly to any GraphStore::apply_diff:
use IncrementalIndexer;
use KuzuGraphStore;
use GraphStore;
use Path;
let repo_root = new;
let indexer = new?;
let mut store = open?;
let branch = "main";
let last_sha = store.last_indexed_sha?;
let = indexer.run?;
if !diff.is_empty
Differ
Differ wraps git2::Repository and can be used independently if you only need file-level change detection:
use Differ;
use Path;
let differ = open?;
let head = differ.head_sha?;
let changes = differ.changed_files?;
for change in changes
FileChange is an enum with three variants: Added, Modified, Deleted, each carrying the repo-relative path.
Dependencies
| Crate | Purpose |
|---|---|
gitcortex-core |
Shared graph types and GraphStore trait |
tree-sitter |
Parser runtime |
tree-sitter-{rust,python,typescript,javascript,go,java} |
Language grammars |
git2 |
Git diff and SHA resolution |
rayon |
Parallel file parsing |
ignore |
.gitcortex/ignore pattern matching |
License
MIT — free for commercial and open-source use.