GitNexus/gitnexus
Gergo Magyar 2d2ef8c47f refactor(group): apply simplify-pass findings
Four cleanup agents over the last five commits. Efficiency was clean and traced
why: the containment helper is failure-path only, the reason ternary sits after
the fan-out loop, and the tri-state readers run once per artifact read.

The strongest finding was one the diff itself proved. `refreshPreservedBridgeMeta`
enforced the never-persisted rule for `repoListsUnreadable` and
`pairedWithDatabase` with two deletes in its own body, under a comment noting it
was the only code that read metadata and wrote it back. That held exactly as
long as there was one such caller. `markBridgeProvenanceUnknown` made it two,
and inherited nothing. The strip now lives in `writeBridgeMeta`, so every writer
gets it and no future one can forget; `pairedWithDatabase` is the dangerous one,
because persisted it tells every later reader the pair was verified when nothing
verified it.

`group impact` still printed "fan-out stopped early" whenever `truncatedRepos`
was non-empty — but the bridge's incomplete repos are unioned into that list
even when zero crossings were attempted, so a structural gap was reported as a
runtime one, with the only working remedy omitted. That is the same false-cause
shape the contract listing was re-gated for one commit ago, left live one
command over because the new reason was bolted in front of the old branch rather
than replacing the thing it branched on. Now keyed on the reason.

The `?? 'incomplete-sync'` arm in cross-impact was unreachable: reaching it
needs `truncated` true with all three of its inputs false, which
`truncated = runtimeTruncated || bridge.truncated` forbids. Flattened.

Also: a `recordedMatchStages` insert had split `crossRepoCompleteness` from its
own JSDoc; one new test was a strict subset of another; and the bridge-failure
warning interleaved concatenation with a mid-chain ternary.

The new invariant assertion was caught being VACUOUS by mutation before it
shipped — seeded with a valid repo list, `readBridgeMeta` never sets the
reader-only field, so it passed with or without the strip. The fixture now seeds
an unreadable list, and both it and the pre-existing assertion go red when the
strip is removed.

Deliberately skipped, with reasons: a shared `firstTruncated` fold over
`TruncationFields` (the right altitude, but it changes cross-trace's return
assembly and that surface separately documents a 'timeout' rung it cannot emit —
a behavior change, not a cleanup); a reason-keyed `explainFloor` helper across
all four CLI renderers (real, but a four-site refactor); narrowing the persisted
stage vocabulary to a `SuppressibleStage` alias (would be undone by the very
extension the field was modelled as a list to allow); moving `verbose` to
`logger.debug` and deleting `SyncOptions.verbose` (the maintainer explicitly
directed keeping both); and merging the two tri-state readers behind a predicate
(they are adjacent in one file now, so a tightening applies to both by
inspection — the duplication the comment warned about was cross-FILE).

tsc clean; eslint 0 errors; 1164/1164.
2026-08-27 16:41:52 +00:00
..
.claude feat(cpp): sfinae filter (#1623) 2026-05-16 20:23:13 +01:00
bench fix(group)!: remove max_candidates_per_step and shared_libs (U6) 2026-08-27 14:43:09 +00:00
hooks fix(cli): stop churning the committed agent guides, and nudge --index-only (#2907) (#2927) 2026-08-11 13:30:14 +01:00
scripts fix(group): stop reporting what could not be measured as a measurement of zero (#3012) 2026-08-26 09:37:16 +01:00
skills docs(claude-skills): bind repository and worktree identity in multi repo skills (#2981) 2026-08-18 14:09:09 +00:00
src refactor(group): apply simplify-pass findings 2026-08-27 16:41:52 +00:00
test refactor(group): apply simplify-pass findings 2026-08-27 16:41:52 +00:00
vendor perf(communities): fix the O(communities x N) copy in vendored Leiden, wire Icebug to its real API (#2337) (#2692) 2026-07-25 13:23:17 +01:00
.env.example feat(serve): validate and port-scope the origin/proxy configuration surface (#2820) 2026-08-05 06:52:39 +01:00
.npmignore feat(install): toolchain-free tree-sitter via vendored prebuilds (#2113) 2026-06-09 18:16:24 +01:00
CHANGELOG.md chore: release v1.6.9 (#2367) 2026-07-04 07:53:06 +01:00
Dockerfile.test fix(security): Pin Docker Node base images, remove runtime package-manager CVE surface, verify Trivy on PRs, and harden Dependabot policy (#1455) 2026-05-09 16:55:31 +01:00
package-lock.json feat(group+ingestion): resolve Java constant-based route paths (@PostMapping(ApiPathConstants.X)) (#2980) 2026-08-25 09:41:57 +01:00
package.json fix(deps): override sharp >=0.35.0 to remediate libvips vulnerabilities (#2993) 2026-08-19 07:21:32 -07:00
README.md feat: make MAX_CALLABLE_VALUE_TARGETS configurable via env (#2725) 2026-08-01 12:42:36 +01:00
tsconfig.json perf(cfg): SSA-sparse reaching-defs to replace the dense-set worklist (#2201) (#2212) 2026-06-15 19:16:53 +01:00
tsconfig.test.json test: add test suite with vitest (unit + integration + fixtures) 2026-03-01 20:07:02 +05:30
vitest.config.ts fix(mcp): stop scaling the detect_changes query with the diff's hunk count (#2915) (#2930) 2026-08-12 14:51:17 +01:00

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, Antigravity (Google), Codex, Windsurf, Cline, OpenCode, CodeBuddy (Tencent), Qoder (Alibaba), and any MCP-compatible tool.

npm version License: PolyForm Noncommercial


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.

On npm 11.x? npx can crash during install (Cannot destructure property 'package' of 'node.target'). Use the pnpm form instead:

pnpm --allow-build=@ladybugdb/core --allow-build=gitnexus --allow-build=tree-sitter dlx gitnexus@latest analyze

See Troubleshooting → npx gitnexus crashes with node.target is null (npm 11) for the full matrix (global install, npm downgrade).

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. To configure only selected integrations, pass --coding-agent/-c with a comma-separated list or repeat the option, for example gitnexus setup -c cursor,codex.

Editor Support

Editor MCP Skills Hooks (auto-augment) Support
Claude Code Yes Yes Yes (PreToolUse + PostToolUse) Full
Cursor Yes Yes Yes (postToolUse, manual install) Full
Antigravity (Google) Yes Yes Yes (AfterTool, Gemini CLI hooks schema) Full
Codex Yes Yes Yes (PreToolUse + PostToolUse, Codex hooks) Full
OpenCode Yes Yes MCP + Skills
CodeBuddy (Tencent) Yes Yes MCP + Skills
Qoder (Alibaba) Yes Yes MCP + Skills
Windsurf Yes MCP

Claude Code and Codex get the deepest integration: MCP tools + agent skills + PreToolUse hooks that automatically enrich grep/glob/bash calls with knowledge graph context + PostToolUse hooks that detect a stale index after commits and prompt the agent to reindex.

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 + hooks)

codex mcp add gitnexus -- npx -y gitnexus@latest mcp

Codex hooks (PreToolUse graph enrichment + PostToolUse stale-index detection in ~/.codex/hooks.json, same schema as Claude Code) need the bundled adapter script, so they are installed by gitnexus setup -c codex rather than manually.

Alternatively, install everything as a Codex plugin (MCP + skills + hooks in one step):

codex plugin marketplace add abhigyanpatwari/GitNexus
# then inside Codex: /plugins → install "GitNexus"

Codex notes: SessionStart is intentionally not registered — Codex reads AGENTS.md natively, which already carries the GitNexus context block. Newly installed hooks need a one-time approval in Codex via /hooks before they run. Pick one install route (gitnexus setup -c codex or the plugin): plugin hooks load alongside ~/.codex/hooks.json, so installing both can fire duplicate hooks per tool call.

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"]
    }
  }
}

CodeBuddy

CodeBuddy reads only the first existing file in its config priority chain: ~/.codebuddy/.mcp.json (recommended) → ~/.codebuddy/mcp.json (deprecated) → ~/.codebuddy.json (legacy). Edit the first non-empty file that exists — creating a higher-priority file would hide the servers in the ones below it. If none exist, create ~/.codebuddy/.mcp.json:

{
  "mcpServers": {
    "gitnexus": {
      "command": "npx",
      "args": ["-y", "gitnexus@latest", "mcp"]
    }
  }
}

Qoder

Add to ~/.qoder.json:

{
  "mcpServers": {
    "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:

  1. Structure — Walks the file tree and maps folder/file relationships
  2. Parsing — Extracts functions, classes, methods, and interfaces using Tree-sitter ASTs
  3. 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
  4. Clustering — Groups related symbols into functional communities
  5. Processes — Traces execution flows from entry points through call chains
  6. 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.

Experimental community detection engine

Experimental — not supported for production indexes. The Icebug engine is a research path for #2337. It carries no stability guarantee, may change or be removed without a major version, and partitions differently from the default, so switching engines changes community IDs and any generated context keyed on them. Reindex with graphology before relying on the output.

Community detection uses the bundled Graphology Leiden implementation by default. To try the #2337 Icebug path without changing default analyze behavior, install the optional native package alongside GitNexus and set the engine:

npm i @ladybugmem/icebug
GITNEXUS_COMMUNITY_ENGINE=icebug npx gitnexus analyze

Supported values are graphology, icebug, and auto. Today auto is behaviorally identical to icebug: both try Icebug and fall back to Graphology, while graphology skips Icebug entirely.

Icebug is not a declared dependency — its prebuilds link against system Arrow 24 (libarrow.so.2400), OpenMP, and glibc ≥ 2.38, none of which GitNexus can assume. Analyze falls back to Graphology and reports the reason in progress output when the module is missing, fails to load, or predates the setNumberOfThreads / setSeed controls that reproducible community IDs require (present at icebug-nodejs HEAD, absent from the published 12.8.0 tarball — so the fallback is what you will see today). The engine is pinned to threads: 1, randomize: false for determinism.

Note that the bundled Graphology path is no longer the slow option it once was: #2337 removed an accidental O(communities × N) copy in the vendored Leiden. On a synthetic 200k-node / 800k-edge benchmark graph it went from exceeding the 60s timeout to finishing in ~15s. Real projections vary with their degree distribution, so treat that as a direction, not a guarantee.

MCP Tools

Your AI agent gets 17 tools (15 per-repo + 2 group) automatically:

Tool What It Does
list_repos Discover all indexed repositories (paginated — limit/offset)
query Process-grouped hybrid search (BM25 + semantic + RRF)
context 360-degree symbol view — categorized refs, process participation
impact Blast radius analysis with depth grouping and confidence
trace Shortest directed path between two symbols (call + class-member edges)
detect_changes Git-diff impact — maps changed lines to affected processes
check Read-only structural checks against the indexed graph
rename Multi-file coordinated rename with graph + text search
cypher Raw Cypher graph queries
route_map API route map — which components fetch which endpoints, and handlers
tool_map MCP/RPC tool definitions — where they're defined and handled
shape_check Validate API response shapes against consumers' property accesses
api_impact Pre-change impact report for an API route handler
explain Explain persisted taint findings (source→sink flows, --pdg indexes)
pdg_query Query control/data dependence at statement level (--pdg indexes)
group_list List configured repository groups
group_sync Rebuild a group's Contract Registry and cross-repo links

With one indexed repo, the repo param is optional. With multiple, specify which: query({search_query: "auth", repo: "my-app"}). Per-repo tools also take an optional branch for indexes pinned with gitnexus analyze --branch; omitting it queries the workspace index, which follows your checked-out working tree. explain and pdg_query need an index built with gitnexus analyze --pdg.

MCP Resources

Resource Purpose
gitnexus://repos List all indexed repositories (read first)
gitnexus://setup Setup and usage guidance for agents
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
gitnexus://group/{name}/contracts A group's extracted contracts and cross-links
gitnexus://group/{name}/status Staleness of repos in a group

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 detected editors (one-time; use -c to select)
gitnexus uninstall               # Preview removal of GitNexus MCP/skills/hooks (add --force to apply)
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 embeddings install      # Fetch the optional local embedding stack on demand (--cuda, --force)
gitnexus analyze --skills        # Generate repo-specific skill files from detected communities
gitnexus analyze --skip-agents-md  # Preserve custom AGENTS.md/CLAUDE.md gitnexus section edits
gitnexus analyze --skip-skills   # Skip installing standard .claude/skills/gitnexus-* skill files
gitnexus analyze --skip-git      # Index folders that are not Git repositories
gitnexus analyze --workers <n>   # Parse worker pool size (>=1; default: cores-1, capped at 16)
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: minimax/minimax-m2.5)
gitnexus wiki --base-url http://llama-box.local:8080/v1 --allow-insecure-connection llama-box.local
                                  # Allow an exact LAN/self-hosted HTTP LLM host; env: GITNEXUS_ALLOW_INSECURE_CONNECTION
gitnexus doctor                  # Show runtime platform capabilities and embedding configuration

# Direct graph queries — the same tools the MCP server exposes, no MCP daemon needed
gitnexus query "<concept>"                                    # Process-grouped hybrid search
gitnexus context <symbol> [--uid <uid> | --file <path>]       # 360° symbol view; flags disambiguate a shared name
gitnexus impact <symbol> [--uid <uid> | --file <path> | --kind <kind>]  # Blast radius; flags disambiguate a shared name
gitnexus trace <from> <to>       # Shortest directed path between two symbols
gitnexus detect-changes          # Map the working-tree diff to affected symbols and execution flows
gitnexus check                   # Read-only structural checks against the indexed graph
gitnexus cypher "<query>"        # Run a raw Cypher query against the knowledge graph

# 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
gitnexus group impact <name> --target <symbol> --repo <groupPath>  # Cross-repo blast radius

gitnexus uninstall reverses gitnexus setup — it removes the GitNexus MCP entries, hooks, and skill directories it added to each detected editor. Skill directories are identified by bundled gitnexus skill name (e.g. gitnexus-cli/), so if you customized files inside an installed skill directory, back them up first. It is a dry-run preview by default and prints the exact paths it would remove; pass --force to apply. Per-repo indexes (gitnexus clean --all) and the global npm package (npm uninstall -g gitnexus) are left for you to remove.

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_REQUEST_DIMS=omit  # optional: omit "dimensions", or an integer to override it
export GITNEXUS_EMBEDDING_API_KEY=your-key   # optional, default: "unused"
export GITNEXUS_EMBEDDING_MAX_ATTEMPTS=3     # optional, total attempts (1-20)
export GITNEXUS_EMBEDDING_RETRY_CAP_MS=5000  # optional, maximum retry delay
export GITNEXUS_EMBEDDING_MIN_INTERVAL_MS=0  # optional, minimum request spacing
export GITNEXUS_EMBEDDING_HTTP_TIMEOUT_MS=180000 # optional, per-request timeout (max 300000)
gitnexus analyze . --embeddings

GITNEXUS_EMBEDDING_REQUEST_DIMS controls only the dimensions field sent in the request body, independently of GITNEXUS_EMBEDDING_DIMS (which still validates the returned vector's length):

  • omit (or none, off, false, 0) — do not send dimensions at all, for strict backends that return the right vector size but reject the field.
  • a positive integer — send that value instead of GITNEXUS_EMBEDDING_DIMS.
  • unset — send GITNEXUS_EMBEDDING_DIMS (the previous behavior).

Works with Infinity, vLLM, TEI, llama.cpp, Ollama, LM Studio, or OpenAI. Retry and pacing settings are provider-neutral; provider-specific limits should be supplied through configuration. When unset, local embeddings are used unchanged.

JVM Package Sibling Injection

Java and Kotlin files in the same package receive implicit sibling class bindings to resolve same-package references. By default, GitNexus injects at most 200 siblings per module scope, nearest first by path. Set GITNEXUS_MAX_INJECTED_SIBLINGS=0 to remove that per-file limit; this can substantially increase indexing work for large packages.

export GITNEXUS_MAX_INJECTED_SIBLINGS=200
gitnexus analyze .

When the limit truncates a file's sibling set, that file is marked visibility-incomplete: same-package references still resolve through the injected siblings, but wildcard-import attribution (used by the Spring bean/DI/config passes) is disabled for it rather than resolved against a partial view. Analyze logs a sibling injection truncated warning naming how many files were affected.

Packages with more than 500 files are a separate, fixed limit: they are skipped entirely (logged as skipping package with N files) and every file in them is marked visibility-incomplete. GITNEXUS_MAX_INJECTED_SIBLINGS does not lift that skip — including at 0.

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, Dart

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++
Dart

Imports — cross-file import resolution · Named Bindingsimport { 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
  • Guide — GitNexus tool/resource/schema reference for the agent
  • CLI — Run analyze/status/clean/wiki commands on request
  • PDG Query — Statement-level control/data dependence queries (--pdg index)
  • Taint Analysis — Source→sink data-flow findings (--pdg index)
  • Plan / Work / Review / LFG — The engineering family: implementation-ready plans, gated plan execution, graph-backed change review with taint + expert lenses, and the end-to-end pipeline

Installed automatically by both gitnexus analyze (per-repo) and gitnexus setup (global). Run gitnexus analyze --skills to additionally generate each detected functional area as a direct project skill under .claude/skills/gitnexus-area-<name>/.

Requirements

  • Node.js >= 22
  • Git repository (uses git for commit tracking)
  • Linux: glibc 2.34 or newer (Ubuntu 22.04+, RHEL/Rocky/Alma 9+, Debian 12+, Fedora 35+). The LadybugDB native binary ships as a prebuild against that floor, so on an older host it cannot load and reinstalling does not help — see Linux: GLIBC_2.34' not found.
  • Windows, for full-text search: the Microsoft Visual C++ 2015-2022 Redistributable (x64) and OpenSSL 3 (libssl-3-x64.dll, libcrypto-3-x64.dll) resolvable on PATH — see Windows: full-text search unavailable.

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 error comes from npm 11.x's arborist while installing gitnexus (often via npx), before gitnexus code runs. It is triggered by platform-filtered optionalDependencies in native packages such as onnxruntime-node / @huggingface/transformers (used when indexing with --embeddings). GitNexus cannot catch it at runtime — use one of these workarounds:

pnpm --allow-build=@ladybugdb/core --allow-build=gitnexus --allow-build=tree-sitter dlx gitnexus@latest analyze       # auto-selected when pnpm + npm 11+
npm install -g gitnexus@latest         # global install avoids per-run npx reify
gitnexus analyze                       # if already installed globally

On pnpm 10+, lifecycle scripts are blocked unless explicitly allowed — the resolver adds --allow-build for @ladybugdb/core, gitnexus, and tree-sitter automatically when it picks pnpm dlx.

If you must stay on npm 11.x without pnpm, downgrade npm toolchain-wide (last resort):

npm install -g npm@10.9.0

See #1939 and the original #819 thread. An older variant of this crash (tree-sitter-dart tarball URL) was fixed in gitnexus v1.6.2+ (#820); if you still see install failures after upgrading, clear cache:

npm cache clean --force
npx gitnexus@latest analyze

ERR_DLOPEN_FAILED / lbugjs.node missing (pnpm dlx, pnpx)

GitNexus depends on @ladybugdb/core, whose native database addon (lbugjs.node) is placed by a postinstall script. pnpm dlx, pnpx, and any install run with --ignore-scripts skip lifecycle scripts, so the addon is never put in place and the runtime crashes with ERR_DLOPEN_FAILED:

Error: dlopen(.../@ladybugdb/core/lbugjs.node, ...): tried: '...' (no such file)
  code: 'ERR_DLOPEN_FAILED'

Options that run install scripts:

# pnpm dlx with explicit build permission (one-off, no global install required)
pnpm --allow-build=@ladybugdb/core --allow-build=gitnexus --allow-build=tree-sitter \
  dlx gitnexus@latest serve

# npm: global install (recommended on npm 11+; bare npx may crash — see section above)
npm install -g gitnexus@latest
gitnexus serve

# npx (npm < 11, or after upgrading npm)
npx gitnexus@latest serve

# pnpm: global install with build scripts allowed (pnpm 10.2+; no approve-builds -g on pnpm 11+)
pnpm add -g --allow-build=@ladybugdb/core --allow-build=gitnexus --allow-build=tree-sitter gitnexus
gitnexus serve

Linux: GLIBC_2.34' not found

LadybugDB native binary (lbugjs.node) exists but failed to load:
  /lib64/libc.so.6: version `GLIBC_2.34' not found (required by .../lbugjs.node)

The LadybugDB addon ships as a prebuilt binary compiled against glibc 2.34. If your distribution is older (CentOS/RHEL 8 has 2.28, Ubuntu 20.04 has 2.31, Debian 11 has 2.31), the dynamic loader cannot resolve its symbols.

Reinstalling does not help — every download delivers the same prebuilt binary. The fix is a newer C library:

  • Run GitNexus on a distribution with glibc 2.34 or newer — Ubuntu 22.04+, RHEL/Rocky/Alma 9+, Debian 12+, Fedora 35+.
  • Or run it in the container image, which bundles a current glibc (see Docker).

gitnexus doctor reports the required and detected glibc versions when this happens (#2672).

Windows: full-text search unavailable

analyze completes, but keyword search is degraded and doctor shows the FTS extension failing with Windows error 126 (The specified module could not be found). The extension needs two runtime dependencies Windows does not ship by default:

  1. Microsoft Visual C++ 2015-2022 Redistributable (x64)https://aka.ms/vs/17/release/vc_redist.x64.exe
  2. OpenSSL 3libssl-3-x64.dll and libcrypto-3-x64.dll, resolvable on PATH

The redistributable alone is not sufficient. If Git for Windows is installed you already have the OpenSSL DLLs — run gitnexus from Git Bash, or prepend the directory to PATH in the shell you use:

$env:PATH = "C:\Program Files\Git\mingw64\bin;$env:PATH"
gitnexus analyze --repair-fts

Without them the index is still built, but without search tables, so query returns empty keyword results until you re-run gitnexus analyze --repair-fts from a shell where the DLLs resolve (#2669).

Installation fails with native module errors

Some optional language grammars (Dart, Proto, Swift, Kotlin) require native compilation. If they fail, GitNexus still works — those languages will be skipped. To skip them intentionally (no C++ toolchain needed), set GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 before installing.

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

Installation fails behind an HTTP proxy (onnxruntime-node postinstall)

onnxruntime-node's postinstall downloads optional CUDA GPU binaries from api.nuget.org — outside the npm registry, so registry mirrors don't cover it, and its proxy layer (global-agent) ignores the standard HTTP_PROXY/HTTPS_PROXY variables and rejects 302 redirects (#2370).

Since the packages are optional dependencies, a failed download no longer breaks npm install -g gitnexus — npm skips the embedding stack and everything else works. The stack then self-heals on demand: the first gitnexus analyze --embeddings (or an explicit gitnexus embeddings install) fetches it through your configured npm registry — mirrors and proxies apply, no NuGet download involved — into ~/.gitnexus/embedding-runtime.

# heal a proxy-degraded install manually (CPU embeddings; registry-only)
gitnexus embeddings install

# reinstall into the prefix even when the stack already resolves
gitnexus embeddings install --force

# CUDA GPU hosts: also fetch GPU binaries (NuGet; set the proxy global-agent reads)
GLOBAL_AGENT_HTTPS_PROXY=<proxy-url> gitnexus embeddings install --cuda

The prefix defaults to ~/.gitnexus/embedding-runtime; set GITNEXUS_EMBEDDING_RUNTIME_DIR to install it elsewhere (e.g. a writable path in a container).

Node requirement for the on-demand prefix: the self-heal loads the prefixed packages via module.registerHooks, available on Node ≥ 22.15 (on the 22.x line) or ≥ 23.5 (on the 23.x line). On an older Node the packages install but can't be loaded from the prefix — reinstall them into the install itself instead (works on every supported Node): ONNXRUNTIME_NODE_INSTALL=skip npm install -g gitnexus (Windows: set ONNXRUNTIME_NODE_INSTALL=skip && npm install -g gitnexus). Skipping only the CUDA download keeps full CPU embeddings (CPU embeddings don't need it). Check the result any time with gitnexus doctor (Embeddings → Support line).

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 (a plain INSTALL to download a missing extension, escalating to FORCE INSTALL only when the LOAD error shows the existing file is broken or truncated, so a permanent non-file failure does not re-download on every run) 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 these environment variables:

Variable Values Default Effect
GITNEXUS_LBUG_EXTENSION_INSTALL auto, load-only, never auto auto runs one bounded install if LOAD fails — a plain INSTALL, escalating to FORCE INSTALL only when the LOAD error shows the present extension file is broken. 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 extension-install child before it is killed.
GITNEXUS_FTS_STEMMER supported LadybugDB stemmer porter Stemmer used when rebuilding BM25/FTS indexes. Use none for CJK-heavy repositories, or a language stemmer such as german, french, or spanish when that better matches repository comments and identifiers. Re-run gitnexus analyze --repair-fts after changing it.
GITNEXUS_FTS_CJK_SEGMENTATION none, bigram none bigram inserts overlapping character-bigram boundaries into Chinese/Japanese Han-ideograph spans in content/description before FTS indexing, so LadybugDB's space-only tokenizer can see sub-phrase word boundaries. Scoped to CJK Unified Ideographs only — Japanese Hiragana/Katakana and Korean Hangul are not currently segmented. Unlike GITNEXUS_FTS_STEMMER, this rewrites stored text — enabling it on an already-indexed repo requires a full gitnexus analyze --force; neither --repair-fts nor a plain incremental analyze applies it to previously-indexed files. Set the same value wherever analyze and search-serving processes (CLI query, MCP server, web server) run.
GITNEXUS_STREAM_GRAPH_EMIT 0, 1 1 (on) On by default on a full rebuild (--force); incremental runs ignore it. Holds structural relationships (CALLS, IMPORTS, ACCESSES, CONTAINS, ...) as CSV-on-disk plus compact in-memory columns instead of as objects in three overlapping indexes, cutting peak in-memory graph heap by ~1.4x at no measurable CPU cost (measured A/B on a synthetic 400k-node / 1.08M-edge graph: 819 MB -> 584 MB, iteration at parity, scaling verified linear from 100k to 800k nodes, with every edge still visible through the graph interface; no end-to-end measurement on a real repository yet). Nothing is traded away — community detection, process extraction, PDG taint summaries and the local-symbol pruner all read a complete relationship set and behave identically. Set to 0 only to bisect a suspected streaming-related fault.
GITNEXUS_COMMUNITY_ENGINE graphology, icebug, auto graphology Community-detection engine used during analyze. graphology is the supported default. icebug and auto are experimental and currently behave identically: both try the optional @ladybugmem/icebug native Leiden over a CSR export and fall back to Graphology if it is not installed, cannot load, or lacks the deterministic thread/seed controls. Experimental engines partition differently, so community IDs are not comparable across engines.
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.
GITNEXUS_LBUG_BUFFER_POOL_SIZE integer >= 0 (bytes) min(2 GiB, 80% RAM) LadybugDB buffer-pool ceiling for every GitNexus database (analyze, MCP server, serve, group bridges). Bounded so a long-lived gitnexus mcp process or a large incremental analyze cannot grow toward LadybugDB's native 80%-of-RAM default and OOM the host (#2557). 0 restores that native unbounded default; invalid values warn and fall back to the default. During analyze the pool is right-sized to the graph and, on non-4 KiB-page hosts (Apple Silicon 16 KiB, Ascend/aarch64 64 KiB), scaled by the page-size granule ratio up to min(2 GiB × pageSize/4 KiB, 80% RAM) (#2631); this env var overrides all of that as an absolute value.
GITNEXUS_LBUG_MAX_DB_SIZE positive integer (bytes) 17179869184 (16 GiB) Upper bound for a single LadybugDB database file. This is an mmap/disk-address-space ceiling, not a memory limit — it does not constrain the buffer pool (use GITNEXUS_LBUG_BUFFER_POOL_SIZE for that). Raise it when indexing genuinely huge monorepos; invalid values silently fall back to the default.
# 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

# CJK-heavy codebase: rebuild keyword indexes without English stemming
GITNEXUS_FTS_STEMMER=none npx gitnexus analyze --repair-fts

# CJK-heavy codebase: enable sub-phrase search over Chinese/Japanese Han text.
# On an already-indexed repo, the first run after enabling this MUST be --force —
# --repair-fts and plain incremental `analyze` both leave old files un-segmented.
GITNEXUS_FTS_CJK_SEGMENTATION=bigram npx gitnexus analyze --force

Analysis runs out of memory

Memory management is automatic: analyze sizes its heap to the machine (always below physical RAM), caps each parse worker, and — rather than grinding into a GC death spiral or crash — stops early with a message telling you the one thing to do. Repeated Replacement worker did not report ready within 5000ms warnings on a large repository are part of the same picture: memory pressure starving healthy workers, not a worker bug (#2649).

If analyze says the repository doesn't fit, do what the message says:

  • The machine has more memory to give (a NODE_OPTIONS --max-old-space-size pin from your environment is holding analyze back): re-run without the pin — no flags needed.
  • The machine is the ceiling: shrink the scope (exclude generated or vendored directories, below) or use a machine with more RAM.

Escape hatches (GITNEXUS_MEMORY=off to decline the autopilot, GITNEXUS_WORKER_HEAP_MB to size workers yourself) are listed in the environment-variable table below — most users never need them.

For very large repositories:

# Increase Node.js heap size
NODE_OPTIONS="--max-old-space-size=16384" npx gitnexus analyze

# Exclude large directories (this repo only)
echo "vendor/" >> .gitnexusignore
echo "dist/" >> .gitnexusignore

# Exclude a directory across every repo you index, without touching each
# repo's own .gitnexusignore or needing push/commit access to it. GitNexus
# reads the same sources `git` itself does: core.excludesFile (all repos)
# and $GIT_DIR/info/exclude (this repo only, untracked). A repo's own
# .gitignore/.gitnexusignore can still override either with a `!pattern`
# negation. Skip both entirely with GITNEXUS_NO_GLOBAL_IGNORE=1.
git config --global core.excludesFile ~/.gitignore_global   # applies to every repo
echo "docs/" >> ~/.gitignore_global
echo "build/" >> .git/info/exclude                          # this repo only, untracked

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 quarantines a file that repeatedly crashes its worker (respawning the slot so the pool keeps going). 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

Four env vars expose the pool's resilience layers (respawn budget, cumulative-timeout cap, circuit breaker, startup handshake). 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.
GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS 30000 Max wait at pool shutdown for a retired worker still inside native code — terminated at its next JS-safe point instead of mid-native-call, which would abort the process (Napi::Error, #2432).
GITNEXUS_WORKER_READY_TIMEOUT_MS 5000 Startup budget for a parse worker to load its grammar bindings and report {type:'ready'}. Slots that miss it are treated as startup crashes. Raise it on a slow or heavily loaded host where a full pool cold-starting concurrently needs more than 5s.
GITNEXUS_MEMORY off unset (autopilot on)
GITNEXUS_WORKER_HEAP_MB clamp(512, RAM/2/poolSize, 4096) Per-worker V8 old-generation heap cap (#2649). Bounds pool RSS on large repos; a worker exceeding it dies with a real heap error handled by quarantine/respawn.
GITNEXUS_SERVER_ANALYZE_HEAP_MB min(8192, auto cap) Heap for the web/MCP server's forked analyze worker (#2649). Defaults to the historical 8192 MB bounded by the machine/container's RAM-aware auto cap; set an absolute MB value to override.
GITNEXUS_CPP_CAPTURE_BUDGET_MS 20000 Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning (#2432). 0 expires immediately.

Graph cleanup tuning

After scope resolution, analyze prunes inert block-local value symbols (a function-local const/let/var that ends up with only its structural File→DEFINES edge) to keep the graph focused on cross-symbol relationships. Module/file-scope symbols, class members, and any local with a real edge are always kept.

Variable Default Effect
GITNEXUS_KEEP_LOCAL_VALUE_SYMBOLS unset Set to 1/true to keep inert block-local value symbols instead of pruning them.

Programmatic callers can pass keepLocalValueSymbols: true in PipelineOptions instead of setting the env var.

Scope-resolution property-key dispatch cap

During scope resolution GitNexus synthesizes CALLS edges through property-key dispatch — call sites like hooks.emitScopeCaptures() where a property key is registered by multiple definitions across the codebase. To keep this fan-in bounded, each property key is capped at 32 registrations: a key registered by more than 32 distinct functions is skipped entirely (no CALLS are synthesized through it), and the dropped key names are surfaced in the analyze log for operator visibility. The cap is calibrated at 2× this repo's own provider table (16 legitimate registrations, one per language provider).

Variable Default Effect
GITNEXUS_MAX_PROPERTY_DISPATCH_FANOUT 32 Per-property-key registration cap in the property-dispatch scope-resolution pass. Set to a positive integer to raise it for repositories whose provider/hook tables exceed the default and lose CALLS coverage on a legitimate key; non-integer or < 1 values fall back to 32. Lowering it tightens the overflow budget.
# A property key registered by 40 functions overflows the default 32 and drops
# all CALLS through it — raise the cap for that repo and rebuild so scope
# resolution reruns.
export GITNEXUS_MAX_PROPERTY_DISPATCH_FANOUT=64
npx gitnexus analyze --force

Scope-resolution dispatch-target cap

During scope resolution GitNexus resolves calls that flow through callable values — function/method references bound to variables, passed as arguments, or stored in maps/tables. To keep that inclusion-based resolution finite, each callable site is capped at 32 dispatch targets. When a site gathers more candidates than the cap it is treated as overflowed and all of its call edges are dropped — a cliff, not a tail, so a repository with a legitimately wide dispatch table (a single callable site resolving to 33+ targets) loses that site's whole call chain. In that case analyze logs callable-value-flow: candidate set exceeded the cap; no partial CALLS emitted alongside a warning carrying the language, the overflowing context, the candidate count, and the cap (32).

Raise the cap for such repositories:

Variable Default Effect
GITNEXUS_MAX_CALLABLE_VALUE_TARGETS 32 Per-callable-site dispatch-target cap in the callable-value-flow scope-resolution pass. Set to a positive integer to raise it for repositories whose wide dispatch tables overflow the default and lose a whole call chain; non-integer or < 1 values fall back to 32. Lowering it tightens the overflow budget.
# A callable site resolving to 48 targets overflows the default 32 and drops
# the chain — raise the cap for that repo and rebuild so scope resolution reruns.
export GITNEXUS_MAX_CALLABLE_VALUE_TARGETS=64
npx gitnexus analyze --force

Hook augmentation and skip diagnostics

The Claude Code / Antigravity hooks keep their stderr silent on normal skip paths so strict hook runners (e.g. Codex PreToolUse) never see unexpected diagnostic output.

When a GitNexus process holds the repo DB write lock (the common case — the MCP server is running, or the DB-lock probe timed out and failed closed), the local CLI augment can't run (LadybugDB is single-writer). Rather than drop the augmentation, the hook hands the agent a short, conditional MCP-query hint on stdout (the sanctioned additionalContext channel) — "if the GitNexus MCP tools are live in this session, call query …" — so an agent that has the tools can still fetch graph-ranked context. The hint is throttled to at most once per repo per window (GITNEXUS_MCP_HINT_THROTTLE_MS, default 10 min; 0 disables), so an owner-locked session isn't nudged on every search. A stale-index reminder, or an already-current index, stays silent.

To see why a hook skipped the CLI augment, set GITNEXUS_DEBUG=1 and re-run the action — the hook writes the reason (e.g. [GitNexus] augment skipped: MCP server owns DB) and the stale-index hint to its stderr:

GITNEXUS_DEBUG=1 <your command>   # surfaces hook skip/diagnostic reasons on stderr

Only GITNEXUS_DEBUG=1 and GITNEXUS_DEBUG=true enable diagnostics; every other value (including 0 and false) is treated as off. Diagnostics go to stderr only — the hook's structured stdout (the JSON the agent consumes) is unaffected.

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

PolyForm Noncommercial 1.0.0

Free for non-commercial use. Contact for commercial licensing.