gitnexus 1.1.8 → 1.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/ai-context.js +9 -9
- package/dist/cli/analyze.js +50 -40
- package/dist/cli/augment.d.ts +13 -0
- package/dist/cli/augment.js +33 -0
- package/dist/cli/claude-hooks.d.ts +22 -0
- package/dist/cli/claude-hooks.js +97 -0
- package/dist/cli/index.js +5 -0
- package/dist/cli/setup.js +147 -5
- package/dist/core/augmentation/engine.d.ts +26 -0
- package/dist/core/augmentation/engine.js +213 -0
- package/dist/core/embeddings/embedder.js +1 -1
- package/dist/core/embeddings/embedding-pipeline.js +1 -1
- package/dist/core/ingestion/import-processor.js +1 -1
- package/dist/core/ingestion/pipeline.js +1 -1
- package/dist/core/ingestion/process-processor.js +1 -1
- package/dist/core/kuzu/kuzu-adapter.js +13 -9
- package/dist/core/search/bm25-index.js +13 -15
- package/dist/mcp/local/local-backend.d.ts +54 -1
- package/dist/mcp/local/local-backend.js +707 -169
- package/dist/mcp/resources.d.ts +1 -1
- package/dist/mcp/resources.js +111 -73
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +90 -21
- package/dist/mcp/tools.js +80 -61
- package/hooks/claude/gitnexus-hook.cjs +135 -0
- package/hooks/claude/pre-tool-use.sh +78 -0
- package/hooks/claude/session-start.sh +42 -0
- package/package.json +4 -2
- package/skills/debugging.md +24 -22
- package/skills/exploring.md +26 -24
- package/skills/impact-analysis.md +19 -13
- package/skills/refactoring.md +37 -26
package/dist/mcp/tools.js
CHANGED
|
@@ -15,7 +15,7 @@ WHEN TO USE: First step when multiple repos are indexed, or to discover availabl
|
|
|
15
15
|
AFTER THIS: READ gitnexus://repo/{name}/context for the repo you want to work with.
|
|
16
16
|
|
|
17
17
|
When multiple repos are indexed, you MUST specify the "repo" parameter
|
|
18
|
-
on other tools (
|
|
18
|
+
on other tools (query, context, impact, etc.) to target the correct one.`,
|
|
19
19
|
inputSchema: {
|
|
20
20
|
type: 'object',
|
|
21
21
|
properties: {},
|
|
@@ -23,25 +23,28 @@ on other tools (search, explore, impact, etc.) to target the correct one.`,
|
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
name: '
|
|
27
|
-
description: `
|
|
28
|
-
Returns
|
|
26
|
+
name: 'query',
|
|
27
|
+
description: `Query the code knowledge graph for execution flows related to a concept.
|
|
28
|
+
Returns processes (call chains) ranked by relevance, each with its symbols and file locations.
|
|
29
29
|
|
|
30
|
-
WHEN TO USE:
|
|
31
|
-
AFTER THIS: Use
|
|
30
|
+
WHEN TO USE: Understanding how code works together. Use this when you need execution flows and relationships, not just file matches. Complements grep/IDE search.
|
|
31
|
+
AFTER THIS: Use context() on a specific symbol for 360-degree view (callers, callees, categorized refs).
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
33
|
+
Returns results grouped by process (execution flow):
|
|
34
|
+
- processes: ranked execution flows with relevance priority
|
|
35
|
+
- process_symbols: all symbols in those flows with file locations
|
|
36
|
+
- definitions: standalone types/interfaces not in any process
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Hybrid ranking: BM25 keyword + semantic vector search, ranked by Reciprocal Rank Fusion.`,
|
|
39
39
|
inputSchema: {
|
|
40
40
|
type: 'object',
|
|
41
41
|
properties: {
|
|
42
42
|
query: { type: 'string', description: 'Natural language or keyword search query' },
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
task_context: { type: 'string', description: 'What you are working on (e.g., "adding OAuth support"). Helps ranking.' },
|
|
44
|
+
goal: { type: 'string', description: 'What you want to find (e.g., "existing auth validation logic"). Helps ranking.' },
|
|
45
|
+
limit: { type: 'number', description: 'Max processes to return (default: 5)', default: 5 },
|
|
46
|
+
max_symbols: { type: 'number', description: 'Max symbols per process (default: 10)', default: 10 },
|
|
47
|
+
include_content: { type: 'boolean', description: 'Include full symbol source code (default: false)', default: false },
|
|
45
48
|
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
46
49
|
},
|
|
47
50
|
required: ['query'],
|
|
@@ -52,26 +55,30 @@ RETURNS: Array of {name, type, filePath, cluster?, connections[]?, fusedScore, s
|
|
|
52
55
|
description: `Execute Cypher query against the code knowledge graph.
|
|
53
56
|
|
|
54
57
|
WHEN TO USE: Complex structural queries that search/explore can't answer. READ gitnexus://repo/{name}/schema first for the full schema.
|
|
55
|
-
AFTER THIS: Use
|
|
58
|
+
AFTER THIS: Use context() on result symbols for deeper context.
|
|
56
59
|
|
|
57
60
|
SCHEMA:
|
|
58
|
-
- Nodes: File, Folder, Function, Class, Interface, Method, Community, Process
|
|
59
|
-
-
|
|
61
|
+
- Nodes: File, Folder, Function, Class, Interface, Method, CodeElement, Community, Process
|
|
62
|
+
- Multi-language nodes (use backticks): \`Struct\`, \`Enum\`, \`Trait\`, \`Impl\`, etc.
|
|
63
|
+
- All edges via single CodeRelation table with 'type' property
|
|
64
|
+
- Edge types: CONTAINS, DEFINES, CALLS, IMPORTS, EXTENDS, IMPLEMENTS, MEMBER_OF, STEP_IN_PROCESS
|
|
65
|
+
- Edge properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)
|
|
60
66
|
|
|
61
67
|
EXAMPLES:
|
|
62
68
|
• Find callers of a function:
|
|
63
69
|
MATCH (a)-[:CodeRelation {type: 'CALLS'}]->(b:Function {name: "validateUser"}) RETURN a.name, a.filePath
|
|
64
70
|
|
|
65
|
-
• Find
|
|
66
|
-
MATCH (f
|
|
71
|
+
• Find community members:
|
|
72
|
+
MATCH (f)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community) WHERE c.heuristicLabel = "Auth" RETURN f.name
|
|
67
73
|
|
|
68
|
-
•
|
|
69
|
-
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process
|
|
74
|
+
• Trace a process:
|
|
75
|
+
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process) WHERE p.heuristicLabel = "UserLogin" RETURN s.name, r.step ORDER BY r.step
|
|
70
76
|
|
|
71
77
|
TIPS:
|
|
72
|
-
- All relationships use CodeRelation table with
|
|
73
|
-
- Community = functional
|
|
74
|
-
- Process = execution flow trace from entry point to terminal
|
|
78
|
+
- All relationships use single CodeRelation table — filter with {type: 'CALLS'} etc.
|
|
79
|
+
- Community = auto-detected functional area (Leiden algorithm)
|
|
80
|
+
- Process = execution flow trace from entry point to terminal
|
|
81
|
+
- Use heuristicLabel (not label) for human-readable community/process names`,
|
|
75
82
|
inputSchema: {
|
|
76
83
|
type: 'object',
|
|
77
84
|
properties: {
|
|
@@ -82,72 +89,84 @@ TIPS:
|
|
|
82
89
|
},
|
|
83
90
|
},
|
|
84
91
|
{
|
|
85
|
-
name: '
|
|
86
|
-
description: `
|
|
92
|
+
name: 'context',
|
|
93
|
+
description: `360-degree view of a single code symbol.
|
|
94
|
+
Shows categorized incoming/outgoing references (calls, imports, extends, implements), process participation, and file location.
|
|
87
95
|
|
|
88
|
-
WHEN TO USE: After
|
|
89
|
-
AFTER THIS
|
|
90
|
-
AFTER THIS (cluster): Use explore() on specific members, or READ processes resource.
|
|
91
|
-
AFTER THIS (process): Use explore() on individual steps for detail.
|
|
96
|
+
WHEN TO USE: After query() to understand a specific symbol in depth. When you need to know all callers, callees, and what execution flows a symbol participates in.
|
|
97
|
+
AFTER THIS: Use impact() if planning changes, or READ gitnexus://repo/{name}/process/{processName} for full execution trace.
|
|
92
98
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
For SYMBOL: Shows cluster membership, process participation, callers/callees
|
|
96
|
-
For CLUSTER: Shows members, cohesion score, processes touching it
|
|
97
|
-
For PROCESS: Shows step-by-step trace, clusters traversed, entry/terminal points`,
|
|
99
|
+
Handles disambiguation: if multiple symbols share the same name, returns candidates for you to pick from. Use uid param for zero-ambiguity lookup from prior results.`,
|
|
98
100
|
inputSchema: {
|
|
99
101
|
type: 'object',
|
|
100
102
|
properties: {
|
|
101
|
-
name: { type: 'string', description: '
|
|
102
|
-
|
|
103
|
+
name: { type: 'string', description: 'Symbol name (e.g., "validateUser", "AuthService")' },
|
|
104
|
+
uid: { type: 'string', description: 'Direct symbol UID from prior tool results (zero-ambiguity lookup)' },
|
|
105
|
+
file_path: { type: 'string', description: 'File path to disambiguate common names' },
|
|
106
|
+
include_content: { type: 'boolean', description: 'Include full symbol source code (default: false)', default: false },
|
|
103
107
|
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
104
108
|
},
|
|
105
|
-
required: [
|
|
109
|
+
required: [],
|
|
106
110
|
},
|
|
107
111
|
},
|
|
108
112
|
{
|
|
109
|
-
name: '
|
|
110
|
-
description: `
|
|
113
|
+
name: 'detect_changes',
|
|
114
|
+
description: `Analyze uncommitted git changes and find affected execution flows.
|
|
115
|
+
Maps git diff hunks to indexed symbols, then traces which processes are impacted.
|
|
111
116
|
|
|
112
|
-
WHEN TO USE:
|
|
113
|
-
AFTER THIS:
|
|
117
|
+
WHEN TO USE: Before committing — to understand what your changes affect. Pre-commit review, PR preparation.
|
|
118
|
+
AFTER THIS: Review affected processes. Use context() on high-risk symbols. READ gitnexus://repo/{name}/process/{name} for full traces.
|
|
114
119
|
|
|
115
|
-
Returns:
|
|
116
|
-
- All communities (clusters) with member counts and cohesion scores
|
|
117
|
-
- All processes with step counts and types (intra/cross-community)
|
|
118
|
-
- High-level architectural view`,
|
|
120
|
+
Returns: changed symbols, affected processes, and a risk summary.`,
|
|
119
121
|
inputSchema: {
|
|
120
122
|
type: 'object',
|
|
121
123
|
properties: {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
limit: { type: 'number', description: 'Max items per category', default: 20 },
|
|
124
|
+
scope: { type: 'string', description: 'What to analyze: "unstaged" (default), "staged", "all", or "compare"', enum: ['unstaged', 'staged', 'all', 'compare'], default: 'unstaged' },
|
|
125
|
+
base_ref: { type: 'string', description: 'Branch/commit for "compare" scope (e.g., "main")' },
|
|
125
126
|
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
126
127
|
},
|
|
127
128
|
required: [],
|
|
128
129
|
},
|
|
129
130
|
},
|
|
130
131
|
{
|
|
131
|
-
name: '
|
|
132
|
-
description: `
|
|
133
|
-
|
|
132
|
+
name: 'rename',
|
|
133
|
+
description: `Multi-file coordinated rename using the knowledge graph + text search.
|
|
134
|
+
Finds all references via graph (high confidence) and regex text search (lower confidence). Preview by default.
|
|
134
135
|
|
|
135
|
-
WHEN TO USE:
|
|
136
|
-
AFTER THIS:
|
|
136
|
+
WHEN TO USE: Renaming a function, class, method, or variable across the codebase. Safer than find-and-replace.
|
|
137
|
+
AFTER THIS: Run detect_changes() to verify no unexpected side effects.
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
Each edit is tagged with confidence:
|
|
140
|
+
- "graph": found via knowledge graph relationships (high confidence, safe to accept)
|
|
141
|
+
- "text_search": found via regex text search (lower confidence, review carefully)`,
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: 'object',
|
|
144
|
+
properties: {
|
|
145
|
+
symbol_name: { type: 'string', description: 'Current symbol name to rename' },
|
|
146
|
+
symbol_uid: { type: 'string', description: 'Direct symbol UID from prior tool results (zero-ambiguity)' },
|
|
147
|
+
new_name: { type: 'string', description: 'The new name for the symbol' },
|
|
148
|
+
file_path: { type: 'string', description: 'File path to disambiguate common names' },
|
|
149
|
+
dry_run: { type: 'boolean', description: 'Preview edits without modifying files (default: true)', default: true },
|
|
150
|
+
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
151
|
+
},
|
|
152
|
+
required: ['new_name'],
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: 'impact',
|
|
157
|
+
description: `Analyze the blast radius of changing a code symbol.
|
|
158
|
+
Returns all symbols affected by modifying the target, grouped by depth with edge types and confidence.
|
|
143
159
|
|
|
144
|
-
|
|
145
|
-
|
|
160
|
+
WHEN TO USE: Before making code changes — especially refactoring, renaming, or modifying shared code. Shows what would break.
|
|
161
|
+
AFTER THIS: Review d=1 items (WILL BREAK). READ gitnexus://repo/{name}/processes to check affected execution flows.
|
|
146
162
|
|
|
147
163
|
Depth groups:
|
|
148
164
|
- d=1: WILL BREAK (direct callers/importers)
|
|
149
165
|
- d=2: LIKELY AFFECTED (indirect)
|
|
150
|
-
- d=3: MAY NEED TESTING (transitive)
|
|
166
|
+
- d=3: MAY NEED TESTING (transitive)
|
|
167
|
+
|
|
168
|
+
EdgeType: CALLS, IMPORTS, EXTENDS, IMPLEMENTS
|
|
169
|
+
Confidence: 1.0 = certain, <0.8 = fuzzy match`,
|
|
151
170
|
inputSchema: {
|
|
152
171
|
type: 'object',
|
|
153
172
|
properties: {
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* GitNexus Claude Code Hook
|
|
4
|
+
*
|
|
5
|
+
* PreToolUse handler — intercepts Grep/Glob/Bash searches
|
|
6
|
+
* and augments with graph context from the GitNexus index.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: SessionStart hooks are broken on Windows (Claude Code bug).
|
|
9
|
+
* Session context is injected via CLAUDE.md / skills instead.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const { execFileSync } = require('child_process');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Read JSON input from stdin synchronously.
|
|
18
|
+
*/
|
|
19
|
+
function readInput() {
|
|
20
|
+
try {
|
|
21
|
+
const data = fs.readFileSync(0, 'utf-8');
|
|
22
|
+
return JSON.parse(data);
|
|
23
|
+
} catch {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Check if a directory (or ancestor) has a .gitnexus index.
|
|
30
|
+
*/
|
|
31
|
+
function findGitNexusIndex(startDir) {
|
|
32
|
+
let dir = startDir || process.cwd();
|
|
33
|
+
for (let i = 0; i < 5; i++) {
|
|
34
|
+
if (fs.existsSync(path.join(dir, '.gitnexus'))) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
const parent = path.dirname(dir);
|
|
38
|
+
if (parent === dir) break;
|
|
39
|
+
dir = parent;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Extract search pattern from tool input.
|
|
46
|
+
*/
|
|
47
|
+
function extractPattern(toolName, toolInput) {
|
|
48
|
+
if (toolName === 'Grep') {
|
|
49
|
+
return toolInput.pattern || null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (toolName === 'Glob') {
|
|
53
|
+
const raw = toolInput.pattern || '';
|
|
54
|
+
const match = raw.match(/[*\/]([a-zA-Z][a-zA-Z0-9_-]{2,})/);
|
|
55
|
+
return match ? match[1] : null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (toolName === 'Bash') {
|
|
59
|
+
const cmd = toolInput.command || '';
|
|
60
|
+
if (!/\brg\b|\bgrep\b/.test(cmd)) return null;
|
|
61
|
+
|
|
62
|
+
const tokens = cmd.split(/\s+/);
|
|
63
|
+
let foundCmd = false;
|
|
64
|
+
let skipNext = false;
|
|
65
|
+
const flagsWithValues = new Set(['-e', '-f', '-m', '-A', '-B', '-C', '-g', '--glob', '-t', '--type', '--include', '--exclude']);
|
|
66
|
+
|
|
67
|
+
for (const token of tokens) {
|
|
68
|
+
if (skipNext) { skipNext = false; continue; }
|
|
69
|
+
if (!foundCmd) {
|
|
70
|
+
if (/\brg$|\bgrep$/.test(token)) foundCmd = true;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (token.startsWith('-')) {
|
|
74
|
+
if (flagsWithValues.has(token)) skipNext = true;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const cleaned = token.replace(/['"]/g, '');
|
|
78
|
+
return cleaned.length >= 3 ? cleaned : null;
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function main() {
|
|
87
|
+
try {
|
|
88
|
+
const input = readInput();
|
|
89
|
+
const hookEvent = input.hook_event_name || '';
|
|
90
|
+
|
|
91
|
+
if (hookEvent !== 'PreToolUse') return;
|
|
92
|
+
|
|
93
|
+
const cwd = input.cwd || process.cwd();
|
|
94
|
+
if (!findGitNexusIndex(cwd)) return;
|
|
95
|
+
|
|
96
|
+
const toolName = input.tool_name || '';
|
|
97
|
+
const toolInput = input.tool_input || {};
|
|
98
|
+
|
|
99
|
+
if (toolName !== 'Grep' && toolName !== 'Glob' && toolName !== 'Bash') return;
|
|
100
|
+
|
|
101
|
+
const pattern = extractPattern(toolName, toolInput);
|
|
102
|
+
if (!pattern || pattern.length < 3) return;
|
|
103
|
+
|
|
104
|
+
// Resolve CLI path relative to this hook script (same package)
|
|
105
|
+
// hooks/claude/gitnexus-hook.cjs → dist/cli/index.js
|
|
106
|
+
const cliPath = path.resolve(__dirname, '..', '..', 'dist', 'cli', 'index.js');
|
|
107
|
+
|
|
108
|
+
// augment CLI writes result to stderr (KuzuDB's native module captures
|
|
109
|
+
// stdout fd at OS level, making it unusable in subprocess contexts).
|
|
110
|
+
const { spawnSync } = require('child_process');
|
|
111
|
+
let result = '';
|
|
112
|
+
try {
|
|
113
|
+
const child = spawnSync(
|
|
114
|
+
process.execPath,
|
|
115
|
+
[cliPath, 'augment', pattern],
|
|
116
|
+
{ encoding: 'utf-8', timeout: 8000, cwd, stdio: ['pipe', 'pipe', 'pipe'] }
|
|
117
|
+
);
|
|
118
|
+
result = child.stderr || '';
|
|
119
|
+
} catch { /* graceful failure */ }
|
|
120
|
+
|
|
121
|
+
if (result && result.trim()) {
|
|
122
|
+
console.log(JSON.stringify({
|
|
123
|
+
hookSpecificOutput: {
|
|
124
|
+
hookEventName: 'PreToolUse',
|
|
125
|
+
additionalContext: result.trim()
|
|
126
|
+
}
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
} catch (err) {
|
|
130
|
+
// Graceful failure — log to stderr for debugging
|
|
131
|
+
console.error('GitNexus hook error:', err.message);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
main();
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# GitNexus PreToolUse hook for Claude Code
|
|
3
|
+
# Intercepts Grep/Glob/Bash searches and augments with graph context.
|
|
4
|
+
# Receives JSON on stdin with { tool_name, tool_input, cwd, ... }
|
|
5
|
+
# Returns JSON with additionalContext for graph-enriched results.
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
|
|
9
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
10
|
+
CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null)
|
|
11
|
+
|
|
12
|
+
# Extract search pattern based on tool type
|
|
13
|
+
PATTERN=""
|
|
14
|
+
|
|
15
|
+
case "$TOOL_NAME" in
|
|
16
|
+
Grep)
|
|
17
|
+
PATTERN=$(echo "$INPUT" | jq -r '.tool_input.pattern // empty' 2>/dev/null)
|
|
18
|
+
;;
|
|
19
|
+
Glob)
|
|
20
|
+
# Glob patterns are file paths, not search terms — extract meaningful part
|
|
21
|
+
RAW=$(echo "$INPUT" | jq -r '.tool_input.pattern // empty' 2>/dev/null)
|
|
22
|
+
# Strip glob syntax to get the meaningful name (e.g., "**/*.ts" → skip, "auth*.ts" → "auth")
|
|
23
|
+
PATTERN=$(echo "$RAW" | sed -n 's/.*[*\/]\([a-zA-Z][a-zA-Z0-9_-]*\).*/\1/p')
|
|
24
|
+
;;
|
|
25
|
+
Bash)
|
|
26
|
+
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
27
|
+
# Only augment grep/rg commands
|
|
28
|
+
if echo "$CMD" | grep -qE '\brg\b|\bgrep\b'; then
|
|
29
|
+
# Extract pattern from rg/grep
|
|
30
|
+
if echo "$CMD" | grep -qE '\brg\b'; then
|
|
31
|
+
PATTERN=$(echo "$CMD" | sed -n "s/.*\brg\s\+\(--[^ ]*\s\+\)*['\"]\\?\([^'\";\| >]*\\).*/\2/p")
|
|
32
|
+
elif echo "$CMD" | grep -qE '\bgrep\b'; then
|
|
33
|
+
PATTERN=$(echo "$CMD" | sed -n "s/.*\bgrep\s\+\(-[^ ]*\s\+\)*['\"]\\?\([^'\";\| >]*\\).*/\2/p")
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
;;
|
|
37
|
+
*)
|
|
38
|
+
# Not a search tool — skip
|
|
39
|
+
exit 0
|
|
40
|
+
;;
|
|
41
|
+
esac
|
|
42
|
+
|
|
43
|
+
# Skip if pattern too short or empty
|
|
44
|
+
if [ -z "$PATTERN" ] || [ ${#PATTERN} -lt 3 ]; then
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Check if we're in a GitNexus-indexed repo
|
|
49
|
+
dir="${CWD:-$PWD}"
|
|
50
|
+
found=false
|
|
51
|
+
for i in 1 2 3 4 5; do
|
|
52
|
+
if [ -d "$dir/.gitnexus" ]; then
|
|
53
|
+
found=true
|
|
54
|
+
break
|
|
55
|
+
fi
|
|
56
|
+
parent="$(dirname "$dir")"
|
|
57
|
+
[ "$parent" = "$dir" ] && break
|
|
58
|
+
dir="$parent"
|
|
59
|
+
done
|
|
60
|
+
|
|
61
|
+
if [ "$found" = false ]; then
|
|
62
|
+
exit 0
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Run gitnexus augment — must be fast (<500ms target)
|
|
66
|
+
RESULT=$(cd "$CWD" && npx -y gitnexus augment "$PATTERN" 2>/dev/null)
|
|
67
|
+
|
|
68
|
+
if [ -n "$RESULT" ]; then
|
|
69
|
+
ESCAPED=$(echo "$RESULT" | jq -Rs .)
|
|
70
|
+
jq -n --argjson ctx "$ESCAPED" '{
|
|
71
|
+
hookSpecificOutput: {
|
|
72
|
+
hookEventName: "PreToolUse",
|
|
73
|
+
additionalContext: $ctx
|
|
74
|
+
}
|
|
75
|
+
}'
|
|
76
|
+
else
|
|
77
|
+
exit 0
|
|
78
|
+
fi
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# GitNexus SessionStart hook for Claude Code
|
|
3
|
+
# Fires on session startup. Stdout is injected into Claude's context.
|
|
4
|
+
# Checks if the current directory has a GitNexus index.
|
|
5
|
+
|
|
6
|
+
dir="$PWD"
|
|
7
|
+
found=false
|
|
8
|
+
for i in 1 2 3 4 5; do
|
|
9
|
+
if [ -d "$dir/.gitnexus" ]; then
|
|
10
|
+
found=true
|
|
11
|
+
break
|
|
12
|
+
fi
|
|
13
|
+
parent="$(dirname "$dir")"
|
|
14
|
+
[ "$parent" = "$dir" ] && break
|
|
15
|
+
dir="$parent"
|
|
16
|
+
done
|
|
17
|
+
|
|
18
|
+
if [ "$found" = false ]; then
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Inject GitNexus context — this stdout goes directly into Claude's context
|
|
23
|
+
cat << 'EOF'
|
|
24
|
+
## GitNexus Code Intelligence
|
|
25
|
+
|
|
26
|
+
This codebase is indexed by GitNexus, providing a knowledge graph with execution flows, relationships, and semantic search.
|
|
27
|
+
|
|
28
|
+
**Available MCP Tools:**
|
|
29
|
+
- `query` — Process-grouped code intelligence (execution flows related to a concept)
|
|
30
|
+
- `context` — 360-degree symbol view (categorized refs, process participation)
|
|
31
|
+
- `impact` — Blast radius analysis (what breaks if you change a symbol)
|
|
32
|
+
- `detect_changes` — Git-diff impact analysis (what do your changes affect)
|
|
33
|
+
- `rename` — Multi-file coordinated rename with confidence tags
|
|
34
|
+
- `cypher` — Raw graph queries
|
|
35
|
+
- `list_repos` — Discover indexed repos
|
|
36
|
+
|
|
37
|
+
**Quick Start:** READ `gitnexus://repo/{name}/context` for codebase overview, then use `query` to find execution flows.
|
|
38
|
+
|
|
39
|
+
**Resources:** `gitnexus://repo/{name}/context` (overview), `/processes` (execution flows), `/schema` (for Cypher)
|
|
40
|
+
EOF
|
|
41
|
+
|
|
42
|
+
exit 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gitnexus",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
|
|
5
5
|
"author": "Abhigyan Patwari",
|
|
6
6
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"dist",
|
|
34
|
+
"hooks",
|
|
34
35
|
"skills",
|
|
35
36
|
"vendor"
|
|
36
37
|
],
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
"dependencies": {
|
|
43
44
|
"@huggingface/transformers": "^3.0.0",
|
|
44
45
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
46
|
+
"cli-progress": "^3.12.0",
|
|
45
47
|
"commander": "^12.0.0",
|
|
46
48
|
"cors": "^2.8.5",
|
|
47
49
|
"express": "^4.19.2",
|
|
@@ -52,7 +54,6 @@
|
|
|
52
54
|
"kuzu": "^0.11.3",
|
|
53
55
|
"lru-cache": "^11.0.0",
|
|
54
56
|
"mnemonist": "^0.39.0",
|
|
55
|
-
"ora": "^8.0.0",
|
|
56
57
|
"pandemonium": "^2.4.0",
|
|
57
58
|
"tree-sitter": "^0.21.0",
|
|
58
59
|
"tree-sitter-c": "^0.21.0",
|
|
@@ -68,6 +69,7 @@
|
|
|
68
69
|
"uuid": "^13.0.0"
|
|
69
70
|
},
|
|
70
71
|
"devDependencies": {
|
|
72
|
+
"@types/cli-progress": "^3.11.6",
|
|
71
73
|
"@types/cors": "^2.8.17",
|
|
72
74
|
"@types/express": "^4.17.21",
|
|
73
75
|
"@types/node": "^20.0.0",
|
package/skills/debugging.md
CHANGED
|
@@ -15,8 +15,8 @@ description: Trace bugs through call chains using knowledge graph
|
|
|
15
15
|
## Workflow
|
|
16
16
|
|
|
17
17
|
```
|
|
18
|
-
1.
|
|
19
|
-
2.
|
|
18
|
+
1. gitnexus_query({query: "<error or symptom>"}) → Find related execution flows
|
|
19
|
+
2. gitnexus_context({name: "<suspect>"}) → See callers/callees/processes
|
|
20
20
|
3. READ gitnexus://repo/{name}/process/{name} → Trace execution flow
|
|
21
21
|
4. gitnexus_cypher({query: "MATCH path..."}) → Custom traces if needed
|
|
22
22
|
```
|
|
@@ -27,9 +27,9 @@ description: Trace bugs through call chains using knowledge graph
|
|
|
27
27
|
|
|
28
28
|
```
|
|
29
29
|
- [ ] Understand the symptom (error message, unexpected behavior)
|
|
30
|
-
- [ ]
|
|
31
|
-
- [ ] Identify the suspect function
|
|
32
|
-
- [ ]
|
|
30
|
+
- [ ] gitnexus_query for error text or related code
|
|
31
|
+
- [ ] Identify the suspect function from returned processes
|
|
32
|
+
- [ ] gitnexus_context to see callers and callees
|
|
33
33
|
- [ ] Trace execution flow via process resource if applicable
|
|
34
34
|
- [ ] gitnexus_cypher for custom call chain traces if needed
|
|
35
35
|
- [ ] Read source files to confirm root cause
|
|
@@ -39,26 +39,27 @@ description: Trace bugs through call chains using knowledge graph
|
|
|
39
39
|
|
|
40
40
|
| Symptom | GitNexus Approach |
|
|
41
41
|
|---------|-------------------|
|
|
42
|
-
| Error message | `
|
|
43
|
-
| Wrong return value | `
|
|
44
|
-
| Intermittent failure | `
|
|
45
|
-
| Performance issue | `
|
|
46
|
-
| Recent regression | `
|
|
42
|
+
| Error message | `gitnexus_query` for error text → `context` on throw sites |
|
|
43
|
+
| Wrong return value | `context` on the function → trace callees for data flow |
|
|
44
|
+
| Intermittent failure | `context` → look for external calls, async deps |
|
|
45
|
+
| Performance issue | `context` → find symbols with many callers (hot paths) |
|
|
46
|
+
| Recent regression | `detect_changes` to see what your changes affect |
|
|
47
47
|
|
|
48
48
|
## Tools
|
|
49
49
|
|
|
50
|
-
**
|
|
50
|
+
**gitnexus_query** — find code related to error:
|
|
51
51
|
```
|
|
52
|
-
|
|
53
|
-
→
|
|
52
|
+
gitnexus_query({query: "payment validation error"})
|
|
53
|
+
→ Processes: CheckoutFlow, ErrorHandling
|
|
54
|
+
→ Symbols: validatePayment, handlePaymentError, PaymentException
|
|
54
55
|
```
|
|
55
56
|
|
|
56
|
-
**
|
|
57
|
+
**gitnexus_context** — full context for a suspect:
|
|
57
58
|
```
|
|
58
|
-
|
|
59
|
-
→
|
|
60
|
-
→
|
|
61
|
-
→
|
|
59
|
+
gitnexus_context({name: "validatePayment"})
|
|
60
|
+
→ Incoming calls: processCheckout, webhookHandler
|
|
61
|
+
→ Outgoing calls: verifyCard, fetchRates (external API!)
|
|
62
|
+
→ Processes: CheckoutFlow (step 3/7)
|
|
62
63
|
```
|
|
63
64
|
|
|
64
65
|
**gitnexus_cypher** — custom call chain traces:
|
|
@@ -70,11 +71,12 @@ RETURN [n IN nodes(path) | n.name] AS chain
|
|
|
70
71
|
## Example: "Payment endpoint returns 500 intermittently"
|
|
71
72
|
|
|
72
73
|
```
|
|
73
|
-
1.
|
|
74
|
-
→
|
|
74
|
+
1. gitnexus_query({query: "payment error handling"})
|
|
75
|
+
→ Processes: CheckoutFlow, ErrorHandling
|
|
76
|
+
→ Symbols: validatePayment, handlePaymentError
|
|
75
77
|
|
|
76
|
-
2.
|
|
77
|
-
→
|
|
78
|
+
2. gitnexus_context({name: "validatePayment"})
|
|
79
|
+
→ Outgoing calls: verifyCard, fetchRates (external API!)
|
|
78
80
|
|
|
79
81
|
3. READ gitnexus://repo/my-app/process/CheckoutFlow
|
|
80
82
|
→ Step 3: validatePayment → calls fetchRates (external)
|