* Initial plan * feat: add Rust scope-resolution hooks (RFC #909 Ring 3) Implement the scope-based resolution pipeline for Rust, following the established pattern from Go and other migrated languages. New files in gitnexus/src/core/ingestion/languages/rust/: - query.ts: tree-sitter scope query covering scopes, declarations, imports, type bindings, and references - cache-stats.ts: parse cache hit/miss counters - import-decomposer.ts: decomposes use declarations into individual import captures (handles grouped, wildcard, renamed, re-exported) - receiver-binding.ts: synthesizes self type bindings for impl methods - interpret.ts: interprets captures into ParsedImport/ParsedTypeBinding - arity.ts: arity compatibility checker (no overloading in Rust) - merge-bindings.ts: local-shadows-import binding merge strategy - simple-hooks.ts: binding scope, import owning scope, receiver binding - import-target.ts: resolves Rust module paths (crate/super/self) - method-owners.ts: bridges impl block methods to struct defs - captures.ts: main emit function with import decomposition and self-binding synthesis - scope-resolver.ts: ScopeResolver implementation - index.ts: barrel re-exports Wiring changes: - rust.ts: add scope hook imports and properties to defineLanguage - registry.ts: register rustScopeResolver in SCOPE_RESOLVERS - registry-primary-flag.ts: add Rust to MIGRATED_LANGUAGES Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> * feat(LANG-rust): add scope-resolution hooks and register Rust ScopeResolver Implements RFC #909 Ring 3 deliverables: - query.ts: tree-sitter scope query for Rust - captures.ts: emitRustScopeCaptures with method reclassification - import-decomposer.ts: use statement decomposition (groups, renames, globs) - interpret.ts: interpretRustImport + interpretRustTypeBinding - import-target.ts: crate/module/super/self path resolution - receiver-binding.ts: self/&self/&mut self receiver synthesis - method-owners.ts: impl block → struct ownership bridging - arity.ts: no-overloading arity check - merge-bindings.ts: local > import > wildcard binding precedence - simple-hooks.ts: binding/import scope, receiver binding - scope-resolver.ts: ScopeResolver contract implementation - Wired into rustProvider (rust.ts) with scope hooks - Registered in SCOPE_RESOLVERS (pipeline/registry.ts) - NOT yet added to MIGRATED_LANGUAGES (29 advanced pattern tests pending) Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/8f14b730-79d4-4356-9505-325750d71f84 Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> * Add Rust scope-resolution integration tests (RFC #909 Ring 3) Tests cover the core deliverables for the Rust scope-resolution pipeline: - impl blocks and trait implementations - Module resolution (crate::, super::, self::) - Struct fields and type bindings - Self/&self/&mut self receiver binding - Generic functions (V1 ignores generic args) - Grouped imports (use foo::{A, B}) - Renamed imports (use foo::Bar as Baz) - Arity checking (no overloading) - Struct literal constructor inference - Return type inference - Scoped/qualified calls (Foo::new()) - Enum declarations - Multiple impl blocks - Free function calls - Typed let bindings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> * test(LANG-rust): add 28 scope-resolution integration tests Covers 15 test suites validating: impl blocks, trait impls, grouped imports, renamed imports, module resolution, receiver binding, arity filtering, struct literal inference, return type inference, qualified calls, struct fields, enums, multiple impl blocks, free calls, and typed let bindings. Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/8f14b730-79d4-4356-9505-325750d71f84 Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> * feat(LANG-rust): add implicit crate path fallback, 35 scope tests - Import resolver now falls back to crate-relative for unqualified module paths (Rust 2015 edition compat) - Added 7 more test cases: re-exports, shadowing, closures, default trait methods (35 total, exceeding ≥30 requirement) Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/8f14b730-79d4-4356-9505-325750d71f84 Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> * feat(rust): add Rust to MIGRATED_LANGUAGES with 100% scope-resolution parity 35/35 integration tests pass under both REGISTRY_PRIMARY_RUST=0 (legacy) and =1 (scope-resolution). Rust scope-resolution is now the default production call-resolution path. * test(rust): add pipeline benchmark matching PHP benchmark pattern Generates synthetic Rust codebases at 100/250/500 files with structs, impl blocks, traits, cross-module use declarations, and method calls. Measures wall-clock time, peak heap, and scaling ratios. Results: sub-linear scaling (0.79x ratio), 500 files in 3.8s with workers, 110MB peak heap. Gated by GITNEXUS_BENCH=1. * chore(autofix): apply prettier + eslint fixes via /autofix command * perf(rust): optimize captures, type normalization, and method-owner linking - Cache findEnclosingImpl result to avoid duplicate tree walk per function - Avoid double namedChild accessor call in struct field arity counting - Extract regex constants (REF_PREFIX_RE, PTR_PREFIX_RE) from hot normalization loops - Replace O(s) suffix-match scan with O(1) Map lookup in method-owner linking Benchmark: 500 files 3806ms → 2970ms (-22%), 250 files 2432ms → 1752ms (-28%) * fix(rust): resolve CodeQL alerts — file-system race and dead code - Remove existsSync+appendFileSync/writeFileSync TOCTOU in benchmark fixture generator; appendFileSync creates if missing - Remove always-true guard on computeRustCallArity return; narrow return type from number|undefined to number - Remove no-op .filter() in fixture generator * feat(rust): hoist impl return-type bindings to struct scope for chain resolution Synthesize a module-level duplicate of @type-binding.return captures for methods inside impl blocks. The scope-extractor's auto-hoist places these on the struct's Class scope, making them visible to the compound receiver chain resolver via classScopeByDefId. Without this, method return types are only on the impl block scope (which has no class-like def and is not indexed by classScopeByDefId), so chains like svc.get_user().save() cannot follow the intermediate return type. This is the structural prerequisite for chain resolution, pattern binding, and for-loop element-type parity (28 remaining tests). The cross-file return-type propagation step still needs wiring for full parity. * fix(rust): use implNode anchor for return-type hoisting — fixes chain resolution Use the enclosing impl_item node (not tree.rootNode) as the synthetic capture anchor. The scope-extractor's auto-hoist places bindings whose anchor matches the innermost scope on the parent scope. With implNode, the binding lands on the Module scope (parent of impl's Class scope), giving declaredAtScope the correct context for findClassBindingInScope to resolve the return type across the scope chain. Unlocks: chain calls (svc.get_user().save()), return-type inference, assignment chains, cross-file binding propagation, call-result binding, deep field chains — 28→27 failing tests. * feat(rust): add populateRangeBindings hook + .await query capture Implement populateRustRangeBindings (Phase 2 hook, same pattern as Go's populateGoRangeBindings) to populate type bindings that need runtime type lookup — for-loop element types, if-let/while-let captured patterns, match arm patterns, and struct destructuring field types. Also add tree-sitter query capture for let x = fn().await — unwraps await_expression to find the inner call_expression. 28→19 failing tests: fixes for-loop Tier 1c, .iter()/.into_iter(), async .await, if-let captured_pattern. * fix(rust): fix tuple_struct_pattern variable extraction + Result<T,E> raw type lookup - Skip wrapper type identifier when finding bound variable in tuple_struct_pattern (Some(user) was binding 'Some' not 'user') - Add lookupRawParameterType to read unstripped generic type from AST for Ok/Err pattern resolution (normalizeRustTypeName strips generics) 28→15 failing tests: fixes if-let Some, if-let Ok/Err, match arm patterns. * fix(rust): fix match_arm parent traversal + raw return type for for-loop calls - Walk up from match_arm through match_block to find match_expression for source variable extraction - Add lookupRawFunctionReturnType to find unstripped return type from AST for same-file for-loop call expression iterables 28→14 failing tests. * feat(rust): inject field type bindings on struct scopes for chain resolution Walk struct_item AST nodes and inject field types (e.g., address -> Address) as typeBindings on the struct's Class scope. The compound receiver chain resolver uses these to follow field chains like user.address.save(). Also fixes: match_arm parent traversal to match_expression, lookupFieldType to check typeBindings first. 28→11 failing tests: fixes field type chains, deep chains, struct destructuring. * feat(rust): cross-file return type lookup for for-loop call iterables Build allReturnTypes map across all parsedFiles in Phase 2 first pass, then use it to resolve for-loop iterables like `for x in get_fn()` when get_fn is defined in another file. 28→9 failing tests. * feat(rust): cross-file field type map for struct destructuring Build allFieldTypes map across parsedFiles in Phase 2 first pass. Used by processStructDestructuring to resolve `let Point { x, y } = p` when Point is defined in another file. 28→7 failing tests. * fix(rust): compound assignment write capture + pending assignment fixpoint - Add compound_assignment_expr query for +=, -=, etc. field writes - Add processPendingAssignments with 3-pass fixpoint for field access and method call result variable bindings (let addr = user.address, let city = addr.get_city()) 28→5 failing tests. * fix(rust): identity method return-type bindings for unwrap/expect chains Inject unwrap/expect/clone/as_ref/as_mut as return-type bindings on struct scopes that return the struct's own type. Since normalizeRustTypeName already unwraps Option<T> → T, calling .unwrap() on a value typed as T is semantically an identity — the return type equals the receiver type. 28→3 failing tests: fixes user.unwrap().save() and repo.unwrap().save() chains. * fix(rust): skip enum variant call-return bindings + cross-file pending assignments + identity alias - Skip Some/None/Ok/Err in @type-binding.call-return — these are enum variant constructors, not type names; let the annotation capture win - Add identifier alias handler in processPendingAssignments for `let alias = opt` chains - Cross-file field type and method return type lookup in pending assignment fixpoint via findFieldTypeAcrossFiles/findMethodReturnTypeAcrossFiles - Identity method bindings (unwrap/expect/clone) on struct scopes 155/156 tests pass (99.4%). Remaining: trait default method dispatch via MRO (repo.count() where count has default impl on Repository trait). * feat(rust): 100% scope-resolution parity — MRO with same-file IMPLEMENTS + trait default method reclassification - Add buildRustMro that includes same-file IMPLEMENTS edges in the MRO chain, so trait default methods (e.g., repo.count()) resolve through the struct → trait ancestry walk - Only add IMPLEMENTS to MRO when struct and trait are in the same file; cross-file trait calls require the trait to be imported (Rust semantics) - Reclassify function_item inside trait_item as @declaration.method so default trait methods register in the model's methods lookup 156/156 legacy parity tests pass. 35/35 scope tests pass. 0 regressions. * fix(rust): address code review findings — null guard, name collision, scope order - Fix Array.find() null guard: check === undefined not === null in processCapturedPattern (find() never returns null) - Fix allReturnTypes/allFieldTypes name collision: delete entry on second occurrence so colliding names (new, default, Config) produce no result rather than a wrong result - Fix lookupTypeInScopes: search function scope then module scope only, skip unrelated Class scopes that could shadow names from other functions --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Test <test@example.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|---|---|---|
| .. | ||
| .claude | ||
| bench | ||
| hooks/claude | ||
| scripts | ||
| shadow-parity-dashboard | ||
| skills | ||
| src | ||
| test | ||
| vendor | ||
| .env.example | ||
| .npmignore | ||
| CHANGELOG.md | ||
| Dockerfile.test | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| tsconfig.test.json | ||
| vitest.config.ts | ||
GitNexus
Graph-powered code intelligence for AI agents. Index any codebase into a knowledge graph, then query it via MCP or CLI.
Works with Cursor, Claude Code, Codex, Windsurf, Cline, OpenCode, and any MCP-compatible tool.
Why?
AI coding tools don't understand your codebase structure. They edit a function without knowing 47 other functions depend on it. GitNexus fixes this by precomputing every dependency, call chain, and relationship into a queryable graph.
Three commands to give your AI agent full codebase awareness.
Quick Start
# Index your repo (run from repo root)
npx gitnexus analyze
That's it. This indexes the codebase, installs agent skills, registers Claude Code hooks, and creates AGENTS.md / CLAUDE.md context files — all in one command.
To configure MCP for your editor, run npx gitnexus setup once — or set it up manually below.
gitnexus setup auto-detects your editors and writes the correct global MCP config. You only need to run it once.
Editor Support
| Editor | MCP | Skills | Hooks (auto-augment) | Support |
|---|---|---|---|---|
| Claude Code | Yes | Yes | Yes (PreToolUse) | Full |
| Cursor | Yes | Yes | Yes (postToolUse, manual install) | Full |
| Codex | Yes | Yes | — | MCP + Skills |
| Windsurf | Yes | — | — | MCP |
| OpenCode | Yes | Yes | — | MCP + Skills |
Claude Code gets the deepest integration: MCP tools + agent skills + PreToolUse hooks that automatically enrich grep/glob/bash calls with knowledge graph context.
Community Integrations
| Agent | Install | Source |
|---|---|---|
| pi | pi install npm:pi-gitnexus |
pi-gitnexus |
MCP Setup (manual)
If you prefer to configure manually instead of using gitnexus setup:
Claude Code (full support — MCP + skills + hooks)
# macOS / Linux
claude mcp add gitnexus -- npx -y gitnexus@latest mcp
# Windows
claude mcp add gitnexus -- cmd /c npx -y gitnexus@latest mcp
Codex (full support — MCP + skills)
codex mcp add gitnexus -- npx -y gitnexus@latest mcp
Cursor / Windsurf
Add to ~/.cursor/mcp.json (global — works for all projects):
{
"mcpServers": {
"gitnexus": {
"command": "npx",
"args": ["-y", "gitnexus@latest", "mcp"]
}
}
}
OpenCode
Add to ~/.config/opencode/config.json:
{
"mcp": {
"gitnexus": {
"command": "npx",
"args": ["-y", "gitnexus@latest", "mcp"]
}
}
}
How It Works
GitNexus builds a complete knowledge graph of your codebase through a multi-phase indexing pipeline:
- Structure — Walks the file tree and maps folder/file relationships
- Parsing — Extracts functions, classes, methods, and interfaces using Tree-sitter ASTs
- Resolution — Resolves imports and function calls across files with language-aware logic
- Field & Property Type Resolution — Tracks field types across classes and interfaces for deep chain resolution (e.g.,
user.address.city.getName()) - Return-Type-Aware Variable Binding — Infers variable types from function return types, enabling accurate call-result binding
- Field & Property Type Resolution — Tracks field types across classes and interfaces for deep chain resolution (e.g.,
- Clustering — Groups related symbols into functional communities
- Processes — Traces execution flows from entry points through call chains
- Search — Builds hybrid search indexes for fast retrieval
The result is a LadybugDB graph database stored locally in .gitnexus/ with full-text search and semantic embeddings.
MCP Tools
Your AI agent gets these tools automatically:
| Tool | What It Does | repo Param |
|---|---|---|
list_repos |
Discover all indexed repositories | — |
query |
Process-grouped hybrid search (BM25 + semantic + RRF) | Optional |
context |
360-degree symbol view — categorized refs, process participation | Optional |
impact |
Blast radius analysis with depth grouping and confidence | Optional |
detect_changes |
Git-diff impact — maps changed lines to affected processes | Optional |
rename |
Multi-file coordinated rename with graph + text search | Optional |
cypher |
Raw Cypher graph queries | Optional |
With one indexed repo, the
repoparam is optional. With multiple, specify which:query({query: "auth", repo: "my-app"}).
MCP Resources
| Resource | Purpose |
|---|---|
gitnexus://repos |
List all indexed repositories (read first) |
gitnexus://repo/{name}/context |
Codebase stats, staleness check, and available tools |
gitnexus://repo/{name}/clusters |
All functional clusters with cohesion scores |
gitnexus://repo/{name}/cluster/{name} |
Cluster members and details |
gitnexus://repo/{name}/processes |
All execution flows |
gitnexus://repo/{name}/process/{name} |
Full process trace with steps |
gitnexus://repo/{name}/schema |
Graph schema for Cypher queries |
MCP Prompts
| Prompt | What It Does |
|---|---|
detect_impact |
Pre-commit change analysis — scope, affected processes, risk level |
generate_map |
Architecture documentation from the knowledge graph with mermaid diagrams |
CLI Commands
gitnexus setup # Configure MCP for your editors (one-time)
gitnexus analyze [path] # Index a repository (or update stale index)
gitnexus analyze --repair-fts # Fast path: rebuild/verify only FTS indexes on existing index data
gitnexus analyze --force # Full rebuild: re-parse + graph rebuild + FTS rebuild
gitnexus analyze --embeddings # Enable embedding generation (slower, better search)
gitnexus analyze --skip-agents-md # Preserve custom AGENTS.md/CLAUDE.md gitnexus section edits
gitnexus analyze --verbose # Log skipped files when parsers are unavailable
gitnexus analyze --max-file-size 1024 # Skip files larger than N KB (default: 512, cap: 32768)
gitnexus analyze --worker-timeout 60 # Increase worker idle timeout for slow parses
gitnexus analyze --wal-checkpoint-threshold 67108864 # 64 MiB. Control LadybugDB WAL auto-checkpoint threshold (default: 67108864 = 64 MiB; -1 keeps Ladybug stock ~16 MiB)
gitnexus mcp # Start MCP server (stdio) — serves all indexed repos
gitnexus serve # Start local HTTP server (multi-repo) for web UI
gitnexus index # Register an existing .gitnexus/ folder into the global registry
gitnexus list # List all indexed repositories
gitnexus status # Show index status for current repo
gitnexus clean # Delete index for current repo
gitnexus clean --all --force # Delete all indexes
gitnexus wiki [path] # Generate LLM-powered docs from knowledge graph
gitnexus wiki --model <model> # Wiki with custom LLM model (default: gpt-4o-mini)
# Repository groups (multi-repo / monorepo service tracking)
gitnexus group create <name> # Create a repository group
gitnexus group add <group> <groupPath> <registryName> # Add a repo to a group. <groupPath> is a hierarchy path (e.g. hr/hiring/backend); <registryName> is the repo's name from the registry (see `gitnexus list`)
gitnexus group remove <group> <groupPath> # Remove a repo from a group by its hierarchy path
gitnexus group list [name] # List groups, or show one group's config
gitnexus group sync <name> # Extract contracts and match across repos/services
gitnexus group contracts <name> # Inspect extracted contracts and cross-links
gitnexus group query <name> <q> # Search execution flows across all repos in a group
gitnexus group status <name> # Check staleness of repos in a group
Remote Embeddings
Set these env vars to use a remote OpenAI-compatible /v1/embeddings endpoint instead of the local model:
export GITNEXUS_EMBEDDING_URL=http://your-server:8080/v1
export GITNEXUS_EMBEDDING_MODEL=BAAI/bge-large-en-v1.5
export GITNEXUS_EMBEDDING_DIMS=1024 # optional, default 384
export GITNEXUS_EMBEDDING_API_KEY=your-key # optional, default: "unused"
gitnexus analyze . --embeddings
Works with Infinity, vLLM, TEI, llama.cpp, Ollama, LM Studio, or OpenAI. When unset, local embeddings are used unchanged.
Multi-Repo Support
GitNexus supports indexing multiple repositories. Each gitnexus analyze registers the repo in a global registry (~/.gitnexus/registry.json). The MCP server serves all indexed repos automatically.
Supported Languages
TypeScript, JavaScript, Python, Java, C, C++, C#, Go, Rust, PHP, Kotlin, Swift, Ruby
Language Feature Matrix
| Language | Imports | Named Bindings | Exports | Heritage | Type Annotations | Constructor Inference | Config | Frameworks | Entry Points |
|---|---|---|---|---|---|---|---|---|---|
| TypeScript | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| JavaScript | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ | ✓ | ✓ |
| Python | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Java | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ |
| Kotlin | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ |
| C# | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Go | ✓ | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rust | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ |
| PHP | ✓ | ✓ | ✓ | — | ✓ | ✓ | ✓ | ✓ | ✓ |
| Ruby | ✓ | — | ✓ | ✓ | — | ✓ | — | ✓ | ✓ |
| Swift | — | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| C | — | — | ✓ | — | ✓ | ✓ | — | ✓ | ✓ |
| C++ | — | — | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ |
Imports — cross-file import resolution · Named Bindings — import { X as Y } / re-export tracking · Exports — public/exported symbol detection · Heritage — class inheritance, interfaces, mixins · Type Annotations — explicit type extraction for receiver resolution · Constructor Inference — infer receiver type from constructor calls (self/this resolution included for all languages) · Config — language toolchain config parsing (tsconfig, go.mod, etc.) · Frameworks — AST-based framework pattern detection · Entry Points — entry point scoring heuristics
Agent Skills
GitNexus ships with skill files that teach AI agents how to use the tools effectively:
- Exploring — Navigate unfamiliar code using the knowledge graph
- Debugging — Trace bugs through call chains
- Impact Analysis — Analyze blast radius before changes
- Refactoring — Plan safe refactors using dependency mapping
Installed automatically by both gitnexus analyze (per-repo) and gitnexus setup (global).
Requirements
- Node.js >= 18
- Git repository (uses git for commit tracking)
Release candidates
Stable releases publish to the default latest dist-tag. When a pull request
with non-documentation changes merges into main, an automated workflow also
publishes a prerelease build under the rc dist-tag, so early adopters can
try in-flight fixes without waiting for the next stable cut. (Docs-only
merges are skipped.)
# Try the latest release candidate (pre-stable — may change at any time)
npm install -g gitnexus@rc
# — or —
npx gitnexus@rc analyze
Release-candidate versions follow the standard semver prerelease format
X.Y.Z-rc.N, where X.Y.Z is the next stable target (bumped from the
current latest by patch by default; minor or major when kicking off a
bigger cycle) and N increments per published rc. Example sequence:
1.6.2-rc.1, 1.6.2-rc.2, …, then once 1.6.2 ships stable,
1.6.3-rc.1. See the Releases page
for the full list; stable latest is unaffected.
Troubleshooting
Cannot destructure property 'package' of 'node.target' as it is null
This crash was caused by a dependency URL format that is incompatible with certain npm/arborist versions (npm/cli#8126). It is fixed in gitnexus v1.6.2+. Upgrade to the latest version:
npx gitnexus@latest analyze # always uses the newest release
# — or —
npm install -g gitnexus@latest # upgrade a global install
If you still hit npm install issues after upgrading, these generic workarounds may help:
npm install -g npm@latest # update npm itself
npm cache clean --force # clear a possibly corrupt cache
Installation fails with native module errors
Some optional language grammars (Dart, Kotlin, Swift) require native compilation. If they fail, GitNexus still works — those languages will be skipped.
If npm install -g gitnexus fails on native modules:
# Ensure build tools are available (Linux/macOS)
# Ubuntu/Debian: sudo apt install python3 make g++
# macOS: xcode-select --install
# Retry installation
npm install -g gitnexus
Analyze warns about unavailable FTS or VECTOR extensions
GitNexus uses optional DuckDB extensions for BM25 and vector search. The gitnexus serve and MCP read paths only ever try to LOAD the extensions — they never block on a network install. The analyze command, by default, attempts one bounded out-of-process INSTALL if LOAD fails and proceeds even when that install times out, so the index is always written to disk; BM25/vector search degrade gracefully until the extensions become available.
Configure the behavior with two environment variables:
| Variable | Values | Default | Effect |
|---|---|---|---|
GITNEXUS_LBUG_EXTENSION_INSTALL |
auto, load-only, never |
auto |
auto runs one bounded INSTALL if LOAD fails. load-only only uses already-installed extensions (recommended for offline / firewalled environments). never skips optional extensions entirely. |
GITNEXUS_LBUG_EXTENSION_INSTALL_TIMEOUT_MS |
positive integer | 15000 |
Wall-clock budget for the out-of-process INSTALL child before it is killed. |
GITNEXUS_WAL_CHECKPOINT_THRESHOLD |
integer >= -1 |
67108864 (64 MiB) |
LadybugDB WAL auto-checkpoint threshold during analyze (bytes). Auto-checkpoint remains enabled; -1 keeps Ladybug's stock ~16 MiB. Larger thresholds reduce checkpoint frequency but increase the WAL size at rotation time — choose a smaller value on disk-constrained environments. |
# Offline/airgapped: never reach the network for extensions
GITNEXUS_LBUG_EXTENSION_INSTALL=load-only npx gitnexus analyze
# Slow network: give extension downloads more time
GITNEXUS_LBUG_EXTENSION_INSTALL_TIMEOUT_MS=30000 npx gitnexus analyze
Analysis runs out of memory
For very large repositories:
# Increase Node.js heap size
NODE_OPTIONS="--max-old-space-size=16384" npx gitnexus analyze
# Exclude large directories
echo "vendor/" >> .gitnexusignore
echo "dist/" >> .gitnexusignore
Large files are being skipped
By default the walker skips files larger than 512 KB (see log line Skipped N large files (>512KB)). Raise the threshold via either the CLI flag or the environment variable — both accept a value in KB:
# CLI flag (takes precedence over the env var)
npx gitnexus analyze --max-file-size 2048 # skip only files > 2 MB
# Environment variable (persists across commands)
export GITNEXUS_MAX_FILE_SIZE=2048
npx gitnexus analyze
Values above 32768 KB (32 MB) are clamped to the tree-sitter parser ceiling; invalid values fall back to the 512 KB default with a one-time warning. When an override is active, analyze prints the effective threshold in its startup banner (e.g. GITNEXUS_MAX_FILE_SIZE: effective threshold 2048KB (default 512KB)).
Analyze reports a worker timeout
Worker parse timeouts are recoverable. GitNexus retries stalled worker jobs with backoff, splits large jobs to isolate slow files, and falls back to the sequential parser when needed. If a large repository needs more time per worker job, use either:
# CLI flag, in seconds
npx gitnexus analyze --worker-timeout 60
# Environment variable, in milliseconds
export GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=60000
npx gitnexus analyze
For repositories with very large source files, GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES controls the worker job byte budget. The default is 8388608 bytes (8 MB).
Worker pool resilience tuning
Three env vars expose the pool's resilience layers (respawn budget, cumulative-timeout cap, circuit breaker). Defaults are tuned for typical repos; bump them when an analyze legitimately needs more retries, or lower them to fail-fast on a known-bad shape.
| Variable | Default | Effect |
|---|---|---|
GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT |
3 |
Max replacement spawns per slot before the slot is dropped from the active rotation. |
GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS |
5 × subBatchTimeoutMs |
Total retry wall-time budget per job before quarantining. Bounds exponentially-growing retry waits. |
GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD |
max(3, poolSize) |
Per-slot consecutive deaths before the pool's circuit breaker trips. After tripping, dispatches require a fresh pool. |
Privacy
- All processing happens locally on your machine
- No code is sent to any server
- Index stored in
.gitnexus/inside your repo (gitignored) - Global registry at
~/.gitnexus/stores only paths and metadata
Web UI
GitNexus also has a browser-based UI at gitnexus.vercel.app — 100% client-side, your code never leaves the browser.
Local Backend Mode: Run gitnexus serve and open the web UI locally — it auto-detects the server and shows all your indexed repos, with full AI chat support. No need to re-upload or re-index. The agent's tools (Cypher queries, search, code navigation) route through the backend HTTP API automatically.
License
Free for non-commercial use. Contact for commercial licensing.