* fix(claude): skip augment hook when server owns db * chore(autofix): apply prettier + eslint fixes via /autofix command * fix(hooks): cross-platform DB lock probe for MCP owner guard Extract hook-db-lock-probe.cjs with a single hasGitNexusDbLockedByGitNexusServer entry point used by both Claude hooks: - Linux: scan /proc/<pid>/fd via dev+inode (no lsof required), optional lsof fallback; GITNEXUS_HOOK_LINUX_PROC_BUDGET_MS caps scan time - macOS and other Unix: trusted lsof + ps (absolute paths / env overrides) - Windows: Restart Manager + Win32_Process via win-rm-list-json.ps1 and GITNEXUS_HOOK_POWERSHELL_PATH Update hooks.test.ts source coverage for the probe module. Co-authored-by: Cursor <cursoragent@cursor.com> * Update gitnexus/hooks/claude/win-rm-list-json.ps1 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Apply suggestion from @github-actions[bot] Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * fix(gitnexus): repair package.json JSON after malformed engines edit Co-authored-by: Cursor <cursoragent@cursor.com> * Update Node.js engine version requirement to 22.0.0 * Update Node.js engine version to >=22.0.0 * fix(hooks): address ce-code-review findings on PR #1493 P0: - Replace malformed `RM_UNIQUE_PROCESS` block in `gitnexus/hooks/claude/win-rm-list-json.ps1` (duplicate struct decl + duplicate `ProcessStartTime` + unbalanced braces) with a single well-formed `[StructLayout(LayoutKind.Sequential, Pack = 4)]` struct, so PowerShell `Add-Type` actually compiles and the Windows DB-lock probe stops fail-open on every machine. - `gitnexus/src/cli/setup.ts` now copies `hook-db-lock-probe.cjs` and `win-rm-list-json.ps1` into the user's `~/.claude/hooks/gitnexus/` alongside `hook-lock.cjs`, preventing the `MODULE_NOT_FOUND` thrown by `gitnexus-hook.cjs:18`'s top-level require on every fresh install. `gitnexus/test/unit/setup.test.ts` extended to assert both new copy destinations. - Four fail-open hook tests (`ENOENT lsof`, `npx parent line`, `non-GitNexus ps line`, `ps ENOENT`) now seed `createHookToolDir` with a valid `[GitNexus]` stderr line so `expect(parseHookOutput).not.toBeNull()` actually holds on CI. P1: - Plugin copy of `win-rm-list-json.ps1` gains `Pack = 4` so its CLR struct matches the 12-byte native `RM_UNIQUE_PROCESS` layout (multi-blocker `RmGetList` no longer reads mangled `dwProcessId`). - `GITNEXUS_HOOK_CLI_PATH = ''` now falls through to the resolution chain in `gitnexus-hook.cjs`, matching the plugin copy and removing the twin-file divergence on empty-string envs. - Lock-warning suppression test seeds `gitnexusMarkerPath` and asserts the augment subprocess actually ran, plus `GITNEXUS_DEBUG=1` preserves the full discarded prefix. - MCP-owner skip branch in both hook copies now emits `[GitNexus] augment skipped: MCP server owns DB` on stderr, so agents can distinguish intentional skip from silent failure. P2: - `ps` loop in `hook-db-lock-probe.cjs` fails-closed on `ETIMEDOUT` to mirror the `lsof` handling (symmetric subprocess-probe contract). - `RmStartSession` return value captured in both `.ps1` copies; exits early with `[]` on non-zero so subsequent RM API calls don't operate on an invalid handle. - Windows RM-list `.ps1` encoded cache distinguishes uninitialized (`undefined`) from load-failed (`null`) with a one-shot `GITNEXUS_DEBUG` warning instead of silently caching empty string. - `createHookToolDir` helper accepts `lsofOutputLines` and `psOutputByPid`; the multi-PID test uses them instead of duplicating the fake-binary construction inline. - All five skip-path tests now assert `result.status === 0` and the new skip-signal stderr line. - `AGENTS.md` documents the seven hook configuration env vars (`GITNEXUS_HOOK_CLI_PATH`, `_LSOF_PATH`, `_PS_PATH`, `_POWERSHELL_PATH`, `_LINUX_PROC_BUDGET_MS`, `_RM_TARGET`, `GITNEXUS_DEBUG`). - `GITNEXUS_DEBUG` path in `gitnexus-hook.cjs`/`.js` writes the full discarded stderr prefix instead of a 180-char preview. - Inline comment in `hook-db-lock-probe.cjs` explains the intentional Windows ETIMEDOUT fail-closed semantics. - Removed the unnecessary `as WriteFileOptions` cast and orphaned `import type { WriteFileOptions }` in `hooks.test.ts`. P3: - `isGitNexusServerCommand` unexported from `hook-db-lock-probe.cjs` (kept as private helper). - Env-path overrides (`GITNEXUS_HOOK_CLI_PATH`, `_POWERSHELL_PATH`, `_LSOF_PATH`, `_PS_PATH`) require `fs.existsSync` before being returned, so typos / stale config fall through to the standard resolution chain. Misc: - `gitnexus/package.json` engines.node back to `>=22.0.0` (matches origin/main and the original PR reviewer's earlier request). Twin-tree parity / CI sync mechanism tracked separately at abhigyanpatwari/GitNexus#1591. Test plan: vitest run test/unit/hooks.test.ts → 113 passed, 18 Unix-only skipped; setup.test.ts → 14 passed. * chore(autofix): apply prettier + eslint fixes via /autofix command * trigger --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Cursor <cursoragent@cursor.com>
15 KiB
Last reviewed: 2026-04-23
Project: GitNexus · Environment: dev · Maintainer: repository maintainers (see GitHub)
Scope
| Boundary | Rule |
|---|---|
| Reads | gitnexus/, gitnexus-web/, eval/, plugin packages, .github/, .gitnexus/, docs. |
| Writes | Only paths required for the change; keep diffs minimal. Update lockfiles when deps change. |
| Executes | npm, npx, node under gitnexus/ and gitnexus-web/; uv run for Python under eval/; documented CI/dev workflows. |
| Off-limits | Real .env / secrets, production credentials, unrelated repos, destructive git ops without confirmation. |
Model Configuration
- Primary: Use a named model (e.g. Claude Sonnet 4.x). Avoid
Autoor unversionedlatestwhen reproducibility matters. - Notes: The GitNexus CLI indexer does not call an LLM.
Execution Sequence (complex tasks)
For multi-step work, state up front:
- Which rules in this file and GUARDRAILS.md apply (and any relevant Signs).
- Current Scope boundaries.
- Which validation commands you will run (
cd gitnexus && npm test,npx tsc --noEmit).
On long threads, "Remember: apply all AGENTS.md rules" re-weights these instructions against context dilution.
Claude Code hooks
PreToolUse hooks can block tools (e.g. git_commit) until checks pass. Adapt to this repo: cd gitnexus && npm test before commit.
Context budget
Commands and gotchas live under Repo reference below and in CONTRIBUTING.md. If always-on rules grow, split into .cursor/rules/*.mdc (globs). Cursor: project-wide rules in .cursor/index.mdc. Claude Code: load STANDARDS.md only when needed.
Reference docs
- ARCHITECTURE.md, CONTRIBUTING.md, GUARDRAILS.md
- Call-resolution DAG (legacy path): See ARCHITECTURE.md § Call-Resolution DAG. Typed 6-stage DAG inside the
parsephase; language-specific behavior behindinferImplicitReceiver/selectDispatchhooks onLanguageProvider. Shared code ingitnexus/src/core/ingestion/must not name languages. Types:gitnexus/src/core/ingestion/call-types.ts. - Scope-resolution pipeline (RFC #909 Ring 3): See ARCHITECTURE.md § Scope-Resolution Pipeline. Replaces the legacy DAG for languages in
MIGRATED_LANGUAGES(seeregistry-primary-flag.ts). A language plugs in by implementingScopeResolver(scope-resolution/contract/scope-resolver.ts) and registering it inSCOPE_RESOLVERS. CI parity gate runs BOTH paths per migrated language on every PR. - Cursor:
.cursor/index.mdc(always-on);.cursor/rules/*.mdc(glob-scoped). Legacy.cursorrulesdeprecated. - GitNexus: skills in
.claude/skills/gitnexus/; MCP rules ingitnexus:startblock below.
Changelog
| Date | Version | Change |
|---|---|---|
| 2026-04-23 | 1.7.0 | TypeScript added to MIGRATED_LANGUAGES (registry-primary call resolution by default). |
| 2026-04-20 | 1.6.0 | Added scope-resolution pipeline pointer (RFC #909 Ring 3); Python migrated to registry-primary. |
| 2026-04-19 | 1.5.0 | Cross-repo impact (#794): impact/query/context accept repo: "@<group>" + service. Removed group_query/group_contracts/group_status MCP tools; added gitnexus://group/{name}/contracts and gitnexus://group/{name}/status resources. |
| 2026-04-16 | 1.4.0 | Fixed: web UI description, pre-commit behavior, MCP tools (7->16), added gitnexus-shared, removed stale vite-plugin-wasm gotcha. |
| 2026-04-13 | 1.3.0 | Updated GitNexus index stats after DAG refactor. |
| 2026-03-24 | 1.2.0 | Fixed gitnexus:start block duplication. |
| 2026-03-23 | 1.1.0 | Updated agent instructions, references, Cursor layout. |
| 2026-03-22 | 1.0.0 | Initial structured header and changelog. |
GitNexus — Code Intelligence
Indexed as GitNexus (4325 symbols, 10556 relationships, 300 execution flows). Use MCP tools to understand code, assess impact, and navigate safely.
If any tool warns the index is stale, run
npx gitnexus analyzefirst.
Always Do
- MUST run impact analysis before editing any symbol.
gitnexus_impact({target: "symbolName", direction: "upstream"})— report blast radius to the user. - MUST run
gitnexus_detect_changes()before committing — verify only expected symbols and flows are affected. - MUST warn the user if impact returns HIGH or CRITICAL risk.
- Explore unfamiliar code with
gitnexus_query({query: "concept"})(process-grouped, ranked) instead of grepping. - Full context on a symbol:
gitnexus_context({name: "symbolName"}).
When Debugging
gitnexus_query({query: "<error or symptom>"})— find related execution flowsgitnexus_context({name: "<suspect function>"})— callers, callees, process participationREAD gitnexus://repo/GitNexus/process/{processName}— trace flow step by step- Regressions:
gitnexus_detect_changes({scope: "compare", base_ref: "main"})
When Refactoring
- Rename:
gitnexus_rename({symbol_name: "old", new_name: "new", dry_run: true})first. Graph edits are safe; text_search edits need manual review. - Extract/Split:
gitnexus_context(incoming/outgoing refs) thengitnexus_impact(upstream callers) before moving code. - After any refactor:
gitnexus_detect_changes({scope: "all"})to verify scope.
Never Do
- Edit a symbol without running
gitnexus_impactfirst. - Ignore HIGH/CRITICAL risk warnings.
- Rename with find-and-replace — use
gitnexus_rename. - Commit without
gitnexus_detect_changes(). - Add language-specific behavior to shared ingestion code (
gitnexus/src/core/ingestion/) — use aLanguageProviderhook. Seeingprovider.mroStrategy === 'xxx'or an import fromlanguages/xxx.tsin shared code means stop and add a hook.
Tools Quick Reference
| Tool | When to use | Example |
|---|---|---|
list_repos |
Discover indexed repos | gitnexus_list_repos({}) |
query |
Find code by concept | gitnexus_query({query: "auth validation"}) |
context |
360-degree view of one symbol | gitnexus_context({name: "validateUser"}) |
impact |
Blast radius before editing | gitnexus_impact({target: "X", direction: "upstream"}) |
detect_changes |
Pre-commit scope check | gitnexus_detect_changes({scope: "staged"}) |
rename |
Safe multi-file rename | gitnexus_rename({symbol_name: "old", new_name: "new", dry_run: true}) |
cypher |
Custom graph queries | gitnexus_cypher({query: "MATCH ..."}) |
api_impact |
Pre-change API route impact | gitnexus_api_impact({route: "/api/users", method: "GET"}) |
route_map |
Route → handler → consumer map | gitnexus_route_map({}) |
tool_map |
MCP/RPC tool definitions | gitnexus_tool_map({}) |
shape_check |
Response shape vs consumer access | gitnexus_shape_check({route: "/api/users"}) |
group_list |
List repo groups | gitnexus_group_list({}) |
group_sync |
Rebuild group Contract Registry | gitnexus_group_sync({name: "myGroup"}) |
query (group mode) |
Cross-repo search in a group (RRF-merged) | gitnexus_query({repo: "@myGroup", query: "auth"}) |
context (group mode) |
360° view across all member repos | gitnexus_context({repo: "@myGroup", name: "validateUser"}) |
impact (group mode) |
Cross-repo blast radius via Contract Bridge | gitnexus_impact({repo: "@myGroup", target: "X", direction: "upstream"}) |
Group mode: pass
repo: "@<groupName>"to fan out across all member repos, orrepo: "@<groupName>/<memberPath>"to target a single member (path keys fromgroup.yaml). Optionalservice: "<monorepo/path>"filters by service root. Group-level state (contracts, staleness) lives in the resources table below — there are nogroup_query/group_context/group_impact/group_contracts/group_statusMCP tools.For a full walkthrough of setting up a group across multiple repos that communicate over gRPC, see docs/guides/microservices-grpc.md.
Impact Risk Levels
| Depth | Meaning | Action |
|---|---|---|
| d=1 | WILL BREAK — direct callers/importers | MUST update |
| d=2 | LIKELY AFFECTED — indirect deps | Should test |
| d=3 | MAY NEED TESTING — transitive | Test if critical path |
Resources
| Resource | Use for |
|---|---|
gitnexus://repo/GitNexus/context |
Codebase overview, index freshness |
gitnexus://repo/GitNexus/clusters |
All functional areas |
gitnexus://repo/GitNexus/processes |
All execution flows |
gitnexus://repo/GitNexus/process/{name} |
Step-by-step execution trace |
gitnexus://group/{name}/contracts |
Group Contract Registry (provider/consumer rows + cross-links) |
gitnexus://group/{name}/status |
Per-member index + Contract Registry staleness report |
Self-Check Before Finishing
gitnexus_impactwas run for all modified symbols- No HIGH/CRITICAL warnings were ignored
gitnexus_detect_changes()confirms expected scope- All d=1 dependents were updated
Keeping the Index Fresh
npx gitnexus analyze # incremental by default; preserves embeddings
npx gitnexus analyze --force # full rebuild from scratch (opt out of incremental)
npx gitnexus analyze --embeddings # also generate embeddings for new/changed nodes
npx gitnexus analyze --drop-embeddings # explicit opt-in to wipe existing embeddings
analyze runs incrementally by default. The pipeline still parses every file every run (cross-file resolution requires it), but tree-sitter parsing is served from a content-addressed cache at .gitnexus/parse-cache.json for chunks whose file contents haven't changed since the last run. Only changed-file rows (and their importers) are rewritten in LadybugDB; unchanged-file rows are preserved. Output is byte-equivalent to a full rebuild. Pass --force to wipe and re-index from scratch (e.g., to recover from a corrupt index, or after upgrading GitNexus).
The parse cache key is content-addressed and version-tagged: it survives --force runs, and is automatically invalidated by a gitnexus package upgrade (so a new tree-sitter grammar doesn't silently replay stale parse output). Safe to delete .gitnexus/parse-cache.json at any time — it'll be rebuilt on the next analyze.
Check .gitnexus/meta.json stats.embeddings (0 = none). A plain analyze no longer drops existing vectors — pass --drop-embeddings to wipe.
Claude Code: PostToolUse hook detects a stale index after
git commitandgit mergeand prompts the agent to runanalyze. The hook does not invokeanalyzeitself.
CLI Skills
| Task | Skill file |
|---|---|
| Architecture / "How does X work?" | .claude/skills/gitnexus/gitnexus-exploring/SKILL.md |
| Blast radius / "What breaks?" | .claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md |
| Debugging / "Why is X failing?" | .claude/skills/gitnexus/gitnexus-debugging/SKILL.md |
| Refactoring | .claude/skills/gitnexus/gitnexus-refactoring/SKILL.md |
| Tools/resources/schema reference | .claude/skills/gitnexus/gitnexus-guide/SKILL.md |
| CLI commands (index, status, clean, wiki) | .claude/skills/gitnexus/gitnexus-cli/SKILL.md |
Hook env knobs
The Claude Code hook (gitnexus/hooks/claude/gitnexus-hook.cjs and the mirrored plugin copy under gitnexus-claude-plugin/hooks/) honours these env vars. Defaults work for normal installations; set them only to override resolution. All path overrides ignore values that do not exist on disk and fall through to the standard resolution chain.
| Env var | Type | Default | Purpose |
|---|---|---|---|
GITNEXUS_HOOK_CLI_PATH |
path | resolved via package layout / require.resolve |
Override path to the gitnexus CLI entry the hook spawns for augment. |
GITNEXUS_HOOK_LSOF_PATH |
path | lsof on PATH (with /usr/bin/lsof, /usr/sbin/lsof, /sbin/lsof fallbacks) |
Override POSIX lsof location for the DB-lock probe. |
GITNEXUS_HOOK_PS_PATH |
path | ps on PATH (with /bin/ps, /usr/bin/ps fallbacks) |
Override POSIX ps location. |
GITNEXUS_HOOK_POWERSHELL_PATH |
path | %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe (then SysWOW64, then powershell.exe on PATH) |
Override Windows PowerShell location used by the Restart-Manager probe. |
GITNEXUS_HOOK_LINUX_PROC_BUDGET_MS |
integer ms | 1200 |
Max wall-clock for the Linux /proc fd scan before bailing out to the lsof fallback. |
GITNEXUS_HOOK_RM_TARGET |
path | derived | Restart-Manager target file (the LadybugDB path under .gitnexus/). Set internally by the hook; rarely overridden manually. |
GITNEXUS_DEBUG |
boolean (1/true) |
unset | Verbose stderr from the hook: prints discarded augment-stderr prefixes and one-shot .ps1 load-failure warnings. |
Repo reference
Packages
| Package | Path | Purpose |
|---|---|---|
| CLI/Core | gitnexus/ |
TypeScript CLI, indexing pipeline, MCP server. Published to npm. |
| Web UI | gitnexus-web/ |
React/Vite thin client. All queries via gitnexus serve HTTP API. |
| Shared | gitnexus-shared/ |
Shared TypeScript types and constants. |
| Claude Plugin | gitnexus-claude-plugin/ |
Static config for Claude marketplace. |
| Cursor Integration | gitnexus-cursor-integration/ |
Static config for Cursor editor. |
| Eval | eval/ |
Python evaluation harness (Docker + LLM API keys). |
Running services
cd gitnexus && npm run dev # CLI: tsx watch mode
cd gitnexus-web && npm run dev # Web UI: Vite on port 5173
npx gitnexus serve # HTTP API on port 4747 (from any indexed repo)
Testing
CLI / Core (gitnexus/)
npm test— full vitest suite (~2000 tests)npm run test:unit— unit tests onlynpm run test:integration— integration (~1850 tests). LadybugDB file-locking tests may fail in containers (known env issue).npx tsc --noEmit— typecheck
Web UI (gitnexus-web/)
npm test— vitest (~200 tests)npm run test:e2e— Playwright (7 spec files; requiresgitnexus serve+npm run dev)npx tsc -b --noEmit— typecheck
Pre-commit hook (.husky/pre-commit): formatting (prettier via lint-staged) + typecheck for staged packages. Tests do not run in pre-commit — CI only.
Gotchas
npm installingitnexus/triggersprepare(builds viatsc) andpostinstall(patches tree-sitter-swift, builds tree-sitter-proto). Native bindings needpython3,make,g++.tree-sitter-kotlinandtree-sitter-swiftare optional — install warnings expected.- ESLint configured via
eslint.config.mjs(TS, React Hooks, unused-imports). Nonpm run lintscript; usenpx eslint .. Prettier runs via lint-staged. CI checks both inci-quality.yml.