gitnexus 1.0.0

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.
Files changed (110) hide show
  1. package/README.md +181 -0
  2. package/dist/cli/ai-context.d.ts +21 -0
  3. package/dist/cli/ai-context.js +219 -0
  4. package/dist/cli/analyze.d.ts +10 -0
  5. package/dist/cli/analyze.js +118 -0
  6. package/dist/cli/clean.d.ts +8 -0
  7. package/dist/cli/clean.js +29 -0
  8. package/dist/cli/index.d.ts +2 -0
  9. package/dist/cli/index.js +42 -0
  10. package/dist/cli/list.d.ts +6 -0
  11. package/dist/cli/list.js +27 -0
  12. package/dist/cli/mcp.d.ts +7 -0
  13. package/dist/cli/mcp.js +85 -0
  14. package/dist/cli/serve.d.ts +3 -0
  15. package/dist/cli/serve.js +5 -0
  16. package/dist/cli/status.d.ts +6 -0
  17. package/dist/cli/status.js +27 -0
  18. package/dist/config/ignore-service.d.ts +1 -0
  19. package/dist/config/ignore-service.js +208 -0
  20. package/dist/config/supported-languages.d.ts +11 -0
  21. package/dist/config/supported-languages.js +15 -0
  22. package/dist/core/embeddings/embedder.d.ts +60 -0
  23. package/dist/core/embeddings/embedder.js +205 -0
  24. package/dist/core/embeddings/embedding-pipeline.d.ts +50 -0
  25. package/dist/core/embeddings/embedding-pipeline.js +321 -0
  26. package/dist/core/embeddings/index.d.ts +9 -0
  27. package/dist/core/embeddings/index.js +9 -0
  28. package/dist/core/embeddings/text-generator.d.ts +24 -0
  29. package/dist/core/embeddings/text-generator.js +182 -0
  30. package/dist/core/embeddings/types.d.ts +87 -0
  31. package/dist/core/embeddings/types.js +32 -0
  32. package/dist/core/graph/graph.d.ts +2 -0
  33. package/dist/core/graph/graph.js +61 -0
  34. package/dist/core/graph/types.d.ts +50 -0
  35. package/dist/core/graph/types.js +1 -0
  36. package/dist/core/ingestion/ast-cache.d.ts +11 -0
  37. package/dist/core/ingestion/ast-cache.js +34 -0
  38. package/dist/core/ingestion/call-processor.d.ts +8 -0
  39. package/dist/core/ingestion/call-processor.js +269 -0
  40. package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
  41. package/dist/core/ingestion/cluster-enricher.js +170 -0
  42. package/dist/core/ingestion/community-processor.d.ts +39 -0
  43. package/dist/core/ingestion/community-processor.js +269 -0
  44. package/dist/core/ingestion/entry-point-scoring.d.ts +39 -0
  45. package/dist/core/ingestion/entry-point-scoring.js +235 -0
  46. package/dist/core/ingestion/filesystem-walker.d.ts +5 -0
  47. package/dist/core/ingestion/filesystem-walker.js +26 -0
  48. package/dist/core/ingestion/framework-detection.d.ts +38 -0
  49. package/dist/core/ingestion/framework-detection.js +183 -0
  50. package/dist/core/ingestion/heritage-processor.d.ts +14 -0
  51. package/dist/core/ingestion/heritage-processor.js +134 -0
  52. package/dist/core/ingestion/import-processor.d.ts +8 -0
  53. package/dist/core/ingestion/import-processor.js +490 -0
  54. package/dist/core/ingestion/parsing-processor.d.ts +8 -0
  55. package/dist/core/ingestion/parsing-processor.js +249 -0
  56. package/dist/core/ingestion/pipeline.d.ts +2 -0
  57. package/dist/core/ingestion/pipeline.js +228 -0
  58. package/dist/core/ingestion/process-processor.d.ts +51 -0
  59. package/dist/core/ingestion/process-processor.js +278 -0
  60. package/dist/core/ingestion/structure-processor.d.ts +2 -0
  61. package/dist/core/ingestion/structure-processor.js +36 -0
  62. package/dist/core/ingestion/symbol-table.d.ts +33 -0
  63. package/dist/core/ingestion/symbol-table.js +38 -0
  64. package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -0
  65. package/dist/core/ingestion/tree-sitter-queries.js +319 -0
  66. package/dist/core/ingestion/utils.d.ts +10 -0
  67. package/dist/core/ingestion/utils.js +44 -0
  68. package/dist/core/kuzu/csv-generator.d.ts +22 -0
  69. package/dist/core/kuzu/csv-generator.js +272 -0
  70. package/dist/core/kuzu/kuzu-adapter.d.ts +81 -0
  71. package/dist/core/kuzu/kuzu-adapter.js +568 -0
  72. package/dist/core/kuzu/schema.d.ts +53 -0
  73. package/dist/core/kuzu/schema.js +380 -0
  74. package/dist/core/search/bm25-index.d.ts +22 -0
  75. package/dist/core/search/bm25-index.js +52 -0
  76. package/dist/core/search/hybrid-search.d.ts +49 -0
  77. package/dist/core/search/hybrid-search.js +118 -0
  78. package/dist/core/tree-sitter/parser-loader.d.ts +4 -0
  79. package/dist/core/tree-sitter/parser-loader.js +42 -0
  80. package/dist/lib/utils.d.ts +1 -0
  81. package/dist/lib/utils.js +3 -0
  82. package/dist/mcp/core/embedder.d.ts +27 -0
  83. package/dist/mcp/core/embedder.js +93 -0
  84. package/dist/mcp/core/kuzu-adapter.d.ts +23 -0
  85. package/dist/mcp/core/kuzu-adapter.js +62 -0
  86. package/dist/mcp/local/local-backend.d.ts +73 -0
  87. package/dist/mcp/local/local-backend.js +752 -0
  88. package/dist/mcp/resources.d.ts +31 -0
  89. package/dist/mcp/resources.js +279 -0
  90. package/dist/mcp/server.d.ts +12 -0
  91. package/dist/mcp/server.js +130 -0
  92. package/dist/mcp/staleness.d.ts +15 -0
  93. package/dist/mcp/staleness.js +29 -0
  94. package/dist/mcp/tools.d.ts +24 -0
  95. package/dist/mcp/tools.js +160 -0
  96. package/dist/server/api.d.ts +6 -0
  97. package/dist/server/api.js +156 -0
  98. package/dist/storage/git.d.ts +7 -0
  99. package/dist/storage/git.js +39 -0
  100. package/dist/storage/repo-manager.d.ts +61 -0
  101. package/dist/storage/repo-manager.js +106 -0
  102. package/dist/types/pipeline.d.ts +28 -0
  103. package/dist/types/pipeline.js +16 -0
  104. package/package.json +80 -0
  105. package/skills/debugging.md +104 -0
  106. package/skills/exploring.md +112 -0
  107. package/skills/impact-analysis.md +114 -0
  108. package/skills/refactoring.md +119 -0
  109. package/vendor/leiden/index.cjs +355 -0
  110. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,156 @@
1
+ /**
2
+ * HTTP API Server
3
+ *
4
+ * REST API for browser-based clients to query the local .gitnexus/ index.
5
+ */
6
+ import express from 'express';
7
+ import cors from 'cors';
8
+ import path from 'path';
9
+ import fs from 'fs/promises';
10
+ import { findRepo } from '../storage/repo-manager.js';
11
+ import { initKuzu, executeQuery } from '../core/kuzu/kuzu-adapter.js';
12
+ import { NODE_TABLES } from '../core/kuzu/schema.js';
13
+ import { searchFTSFromKuzu } from '../core/search/bm25-index.js';
14
+ import { hybridSearch } from '../core/search/hybrid-search.js';
15
+ import { semanticSearch } from '../core/embeddings/embedding-pipeline.js';
16
+ import { isEmbedderReady } from '../core/embeddings/embedder.js';
17
+ const buildGraph = async () => {
18
+ const nodes = [];
19
+ for (const table of NODE_TABLES) {
20
+ try {
21
+ let query = '';
22
+ if (table === 'File') {
23
+ query = `MATCH (n:File) RETURN n.id AS id, n.name AS name, n.filePath AS filePath, n.content AS content`;
24
+ }
25
+ else if (table === 'Folder') {
26
+ query = `MATCH (n:Folder) RETURN n.id AS id, n.name AS name, n.filePath AS filePath`;
27
+ }
28
+ else if (table === 'Community') {
29
+ query = `MATCH (n:Community) RETURN n.id AS id, n.label AS label, n.heuristicLabel AS heuristicLabel, n.cohesion AS cohesion, n.symbolCount AS symbolCount`;
30
+ }
31
+ else if (table === 'Process') {
32
+ query = `MATCH (n:Process) RETURN n.id AS id, n.label AS label, n.heuristicLabel AS heuristicLabel, n.processType AS processType, n.stepCount AS stepCount, n.communities AS communities, n.entryPointId AS entryPointId, n.terminalId AS terminalId`;
33
+ }
34
+ else {
35
+ query = `MATCH (n:${table}) RETURN n.id AS id, n.name AS name, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine, n.content AS content`;
36
+ }
37
+ const rows = await executeQuery(query);
38
+ for (const row of rows) {
39
+ nodes.push({
40
+ id: row.id ?? row[0],
41
+ label: table,
42
+ properties: {
43
+ name: row.name ?? row.label ?? row[1],
44
+ filePath: row.filePath ?? row[2],
45
+ startLine: row.startLine,
46
+ endLine: row.endLine,
47
+ content: row.content,
48
+ heuristicLabel: row.heuristicLabel,
49
+ cohesion: row.cohesion,
50
+ symbolCount: row.symbolCount,
51
+ processType: row.processType,
52
+ stepCount: row.stepCount,
53
+ communities: row.communities,
54
+ entryPointId: row.entryPointId,
55
+ terminalId: row.terminalId,
56
+ },
57
+ });
58
+ }
59
+ }
60
+ catch {
61
+ // ignore empty tables
62
+ }
63
+ }
64
+ const relationships = [];
65
+ const relRows = await executeQuery(`MATCH (a)-[r:CodeRelation]->(b) RETURN a.id AS sourceId, b.id AS targetId, r.type AS type, r.confidence AS confidence, r.reason AS reason, r.step AS step`);
66
+ for (const row of relRows) {
67
+ relationships.push({
68
+ id: `${row.sourceId}_${row.type}_${row.targetId}`,
69
+ type: row.type,
70
+ sourceId: row.sourceId,
71
+ targetId: row.targetId,
72
+ confidence: row.confidence,
73
+ reason: row.reason,
74
+ step: row.step,
75
+ });
76
+ }
77
+ return { nodes, relationships };
78
+ };
79
+ export const createServer = async (port) => {
80
+ const app = express();
81
+ app.use(cors());
82
+ app.use(express.json({ limit: '10mb' }));
83
+ // Get repo info
84
+ app.get('/api/repo', async (_req, res) => {
85
+ const repo = await findRepo(process.cwd());
86
+ if (!repo) {
87
+ res.status(404).json({ error: 'Repository not indexed. Run: gitnexus analyze' });
88
+ return;
89
+ }
90
+ res.json({
91
+ repoPath: repo.repoPath,
92
+ indexedAt: repo.meta.indexedAt,
93
+ stats: repo.meta.stats || {},
94
+ });
95
+ });
96
+ // Get full graph
97
+ app.get('/api/graph', async (_req, res) => {
98
+ const repo = await findRepo(process.cwd());
99
+ if (!repo) {
100
+ res.status(404).json({ error: 'Repository not indexed' });
101
+ return;
102
+ }
103
+ await initKuzu(repo.kuzuPath);
104
+ const graph = await buildGraph();
105
+ res.json(graph);
106
+ });
107
+ // Execute Cypher query
108
+ app.post('/api/query', async (req, res) => {
109
+ const repo = await findRepo(process.cwd());
110
+ if (!repo) {
111
+ res.status(404).json({ error: 'Repository not indexed' });
112
+ return;
113
+ }
114
+ await initKuzu(repo.kuzuPath);
115
+ const result = await executeQuery(req.body.cypher);
116
+ res.json({ result });
117
+ });
118
+ // Search
119
+ app.post('/api/search', async (req, res) => {
120
+ const repo = await findRepo(process.cwd());
121
+ if (!repo) {
122
+ res.status(404).json({ error: 'Repository not indexed' });
123
+ return;
124
+ }
125
+ await initKuzu(repo.kuzuPath);
126
+ const query = req.body.query ?? '';
127
+ const limit = req.body.limit ?? 10;
128
+ if (isEmbedderReady()) {
129
+ const results = await hybridSearch(query, limit, executeQuery, semanticSearch);
130
+ res.json({ results });
131
+ return;
132
+ }
133
+ // FTS-only fallback when embeddings aren't loaded
134
+ const results = await searchFTSFromKuzu(query, limit);
135
+ res.json({ results });
136
+ });
137
+ // Read file
138
+ app.get('/api/file', async (req, res) => {
139
+ const repo = await findRepo(process.cwd());
140
+ if (!repo) {
141
+ res.status(404).json({ error: 'Repository not indexed' });
142
+ return;
143
+ }
144
+ const filePath = req.query.path;
145
+ if (!filePath) {
146
+ res.status(400).json({ error: 'Missing path' });
147
+ return;
148
+ }
149
+ const fullPath = path.join(repo.repoPath, filePath);
150
+ const content = await fs.readFile(fullPath, 'utf-8');
151
+ res.json({ content });
152
+ });
153
+ app.listen(port, () => {
154
+ console.log(`GitNexus server running on http://localhost:${port}`);
155
+ });
156
+ };
@@ -0,0 +1,7 @@
1
+ export declare const isGitRepo: (repoPath: string) => boolean;
2
+ export declare const getCurrentCommit: (repoPath: string) => string;
3
+ export declare const getStatusPorcelain: (repoPath: string) => string;
4
+ /**
5
+ * Find the git repository root from any path inside the repo
6
+ */
7
+ export declare const getGitRoot: (fromPath: string) => string | null;
@@ -0,0 +1,39 @@
1
+ import { execSync } from 'child_process';
2
+ export const isGitRepo = (repoPath) => {
3
+ try {
4
+ execSync('git rev-parse --is-inside-work-tree', { cwd: repoPath, stdio: 'ignore' });
5
+ return true;
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ };
11
+ export const getCurrentCommit = (repoPath) => {
12
+ try {
13
+ return execSync('git rev-parse HEAD', { cwd: repoPath }).toString().trim();
14
+ }
15
+ catch {
16
+ return '';
17
+ }
18
+ };
19
+ export const getStatusPorcelain = (repoPath) => {
20
+ try {
21
+ return execSync('git status --porcelain', { cwd: repoPath }).toString();
22
+ }
23
+ catch {
24
+ return '';
25
+ }
26
+ };
27
+ /**
28
+ * Find the git repository root from any path inside the repo
29
+ */
30
+ export const getGitRoot = (fromPath) => {
31
+ try {
32
+ return execSync('git rev-parse --show-toplevel', { cwd: fromPath })
33
+ .toString()
34
+ .trim();
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Repository Manager
3
+ *
4
+ * Manages GitNexus index storage in .gitnexus/ at repo root.
5
+ */
6
+ export interface RepoMeta {
7
+ repoPath: string;
8
+ lastCommit: string;
9
+ indexedAt: string;
10
+ stats?: {
11
+ files?: number;
12
+ nodes?: number;
13
+ edges?: number;
14
+ communities?: number;
15
+ processes?: number;
16
+ embeddings?: number;
17
+ };
18
+ }
19
+ export interface IndexedRepo {
20
+ repoPath: string;
21
+ storagePath: string;
22
+ kuzuPath: string;
23
+ metaPath: string;
24
+ meta: RepoMeta;
25
+ }
26
+ /**
27
+ * Get the .gitnexus storage path for a repository
28
+ */
29
+ export declare const getStoragePath: (repoPath: string) => string;
30
+ /**
31
+ * Get paths to key storage files
32
+ */
33
+ export declare const getStoragePaths: (repoPath: string) => {
34
+ storagePath: string;
35
+ kuzuPath: string;
36
+ metaPath: string;
37
+ };
38
+ /**
39
+ * Load metadata from an indexed repo
40
+ */
41
+ export declare const loadMeta: (storagePath: string) => Promise<RepoMeta | null>;
42
+ /**
43
+ * Save metadata to storage
44
+ */
45
+ export declare const saveMeta: (storagePath: string, meta: RepoMeta) => Promise<void>;
46
+ /**
47
+ * Check if a path has a GitNexus index
48
+ */
49
+ export declare const hasIndex: (repoPath: string) => Promise<boolean>;
50
+ /**
51
+ * Load an indexed repo from a path
52
+ */
53
+ export declare const loadRepo: (repoPath: string) => Promise<IndexedRepo | null>;
54
+ /**
55
+ * Find .gitnexus by walking up from a starting path
56
+ */
57
+ export declare const findRepo: (startPath: string) => Promise<IndexedRepo | null>;
58
+ /**
59
+ * Add .gitnexus to .gitignore if not already present
60
+ */
61
+ export declare const addToGitignore: (repoPath: string) => Promise<void>;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Repository Manager
3
+ *
4
+ * Manages GitNexus index storage in .gitnexus/ at repo root.
5
+ */
6
+ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ const GITNEXUS_DIR = '.gitnexus';
9
+ /**
10
+ * Get the .gitnexus storage path for a repository
11
+ */
12
+ export const getStoragePath = (repoPath) => {
13
+ return path.join(path.resolve(repoPath), GITNEXUS_DIR);
14
+ };
15
+ /**
16
+ * Get paths to key storage files
17
+ */
18
+ export const getStoragePaths = (repoPath) => {
19
+ const storagePath = getStoragePath(repoPath);
20
+ return {
21
+ storagePath,
22
+ kuzuPath: path.join(storagePath, 'kuzu'),
23
+ metaPath: path.join(storagePath, 'meta.json'),
24
+ };
25
+ };
26
+ /**
27
+ * Load metadata from an indexed repo
28
+ */
29
+ export const loadMeta = async (storagePath) => {
30
+ try {
31
+ const metaPath = path.join(storagePath, 'meta.json');
32
+ const raw = await fs.readFile(metaPath, 'utf-8');
33
+ return JSON.parse(raw);
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ };
39
+ /**
40
+ * Save metadata to storage
41
+ */
42
+ export const saveMeta = async (storagePath, meta) => {
43
+ await fs.mkdir(storagePath, { recursive: true });
44
+ const metaPath = path.join(storagePath, 'meta.json');
45
+ await fs.writeFile(metaPath, JSON.stringify(meta, null, 2), 'utf-8');
46
+ };
47
+ /**
48
+ * Check if a path has a GitNexus index
49
+ */
50
+ export const hasIndex = async (repoPath) => {
51
+ const { metaPath } = getStoragePaths(repoPath);
52
+ try {
53
+ await fs.access(metaPath);
54
+ return true;
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ };
60
+ /**
61
+ * Load an indexed repo from a path
62
+ */
63
+ export const loadRepo = async (repoPath) => {
64
+ const paths = getStoragePaths(repoPath);
65
+ const meta = await loadMeta(paths.storagePath);
66
+ if (!meta)
67
+ return null;
68
+ return {
69
+ repoPath: path.resolve(repoPath),
70
+ ...paths,
71
+ meta,
72
+ };
73
+ };
74
+ /**
75
+ * Find .gitnexus by walking up from a starting path
76
+ */
77
+ export const findRepo = async (startPath) => {
78
+ let current = path.resolve(startPath);
79
+ const root = path.parse(current).root;
80
+ while (current !== root) {
81
+ const repo = await loadRepo(current);
82
+ if (repo)
83
+ return repo;
84
+ current = path.dirname(current);
85
+ }
86
+ return null;
87
+ };
88
+ /**
89
+ * Add .gitnexus to .gitignore if not already present
90
+ */
91
+ export const addToGitignore = async (repoPath) => {
92
+ const gitignorePath = path.join(repoPath, '.gitignore');
93
+ try {
94
+ const content = await fs.readFile(gitignorePath, 'utf-8');
95
+ if (content.includes(GITNEXUS_DIR))
96
+ return;
97
+ const newContent = content.endsWith('\n')
98
+ ? `${content}${GITNEXUS_DIR}\n`
99
+ : `${content}\n${GITNEXUS_DIR}\n`;
100
+ await fs.writeFile(gitignorePath, newContent, 'utf-8');
101
+ }
102
+ catch {
103
+ // .gitignore doesn't exist, create it
104
+ await fs.writeFile(gitignorePath, `${GITNEXUS_DIR}\n`, 'utf-8');
105
+ }
106
+ };
@@ -0,0 +1,28 @@
1
+ import { GraphNode, GraphRelationship, KnowledgeGraph } from '../core/graph/types.js';
2
+ import { CommunityDetectionResult } from '../core/ingestion/community-processor.js';
3
+ import { ProcessDetectionResult } from '../core/ingestion/process-processor.js';
4
+ export type PipelinePhase = 'idle' | 'extracting' | 'structure' | 'parsing' | 'imports' | 'calls' | 'heritage' | 'communities' | 'processes' | 'enriching' | 'complete' | 'error';
5
+ export interface PipelineProgress {
6
+ phase: PipelinePhase;
7
+ percent: number;
8
+ message: string;
9
+ detail?: string;
10
+ stats?: {
11
+ filesProcessed: number;
12
+ totalFiles: number;
13
+ nodesCreated: number;
14
+ };
15
+ }
16
+ export interface PipelineResult {
17
+ graph: KnowledgeGraph;
18
+ fileContents: Map<string, string>;
19
+ communityResult?: CommunityDetectionResult;
20
+ processResult?: ProcessDetectionResult;
21
+ }
22
+ export interface SerializablePipelineResult {
23
+ nodes: GraphNode[];
24
+ relationships: GraphRelationship[];
25
+ fileContents: Record<string, string>;
26
+ }
27
+ export declare const serializePipelineResult: (result: PipelineResult) => SerializablePipelineResult;
28
+ export declare const deserializePipelineResult: (serialized: SerializablePipelineResult, createGraph: () => KnowledgeGraph) => PipelineResult;
@@ -0,0 +1,16 @@
1
+ // Helper to convert PipelineResult to serializable format
2
+ export const serializePipelineResult = (result) => ({
3
+ nodes: result.graph.nodes,
4
+ relationships: result.graph.relationships,
5
+ fileContents: Object.fromEntries(result.fileContents),
6
+ });
7
+ // Helper to reconstruct from serializable format (used in main thread)
8
+ export const deserializePipelineResult = (serialized, createGraph) => {
9
+ const graph = createGraph();
10
+ serialized.nodes.forEach(node => graph.addNode(node));
11
+ serialized.relationships.forEach(rel => graph.addRelationship(rel));
12
+ return {
13
+ graph,
14
+ fileContents: new Map(Object.entries(serialized.fileContents)),
15
+ };
16
+ };
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "gitnexus",
3
+ "version": "1.0.0",
4
+ "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
+ "author": "Abhigyan Patwari",
6
+ "license": "PolyForm-Noncommercial-1.0.0",
7
+ "homepage": "https://github.com/abhigyanpatwari/GitNexus#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/abhigyanpatwari/GitNexus.git",
11
+ "directory": "gitnexus"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/abhigyanpatwari/GitNexus/issues"
15
+ },
16
+ "keywords": [
17
+ "mcp",
18
+ "model-context-protocol",
19
+ "code-intelligence",
20
+ "knowledge-graph",
21
+ "cursor",
22
+ "claude",
23
+ "ai-agent",
24
+ "gitnexus",
25
+ "static-analysis",
26
+ "codebase-indexing"
27
+ ],
28
+ "type": "module",
29
+ "bin": {
30
+ "gitnexus": "dist/cli/index.js"
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "skills",
35
+ "vendor"
36
+ ],
37
+ "scripts": {
38
+ "build": "tsc",
39
+ "dev": "tsx watch src/cli/index.ts",
40
+ "prepare": "npm run build"
41
+ },
42
+ "dependencies": {
43
+ "@huggingface/transformers": "^3.0.0",
44
+ "@modelcontextprotocol/sdk": "^1.0.0",
45
+ "commander": "^12.0.0",
46
+ "cors": "^2.8.5",
47
+ "express": "^4.19.2",
48
+ "glob": "^11.0.0",
49
+ "graphology": "^0.25.4",
50
+ "graphology-indices": "^0.17.0",
51
+ "graphology-utils": "^2.3.0",
52
+ "kuzu": "^0.11.3",
53
+ "lru-cache": "^11.0.0",
54
+ "mnemonist": "^0.39.0",
55
+ "ora": "^8.0.0",
56
+ "pandemonium": "^2.4.0",
57
+ "tree-sitter": "^0.21.0",
58
+ "tree-sitter-c": "^0.21.0",
59
+ "tree-sitter-c-sharp": "^0.21.0",
60
+ "tree-sitter-cpp": "^0.22.0",
61
+ "tree-sitter-go": "^0.21.0",
62
+ "tree-sitter-java": "^0.21.0",
63
+ "tree-sitter-javascript": "^0.21.0",
64
+ "tree-sitter-python": "^0.21.0",
65
+ "tree-sitter-rust": "^0.21.0",
66
+ "tree-sitter-typescript": "^0.21.0",
67
+ "typescript": "^5.4.5",
68
+ "uuid": "^13.0.0"
69
+ },
70
+ "devDependencies": {
71
+ "@types/cors": "^2.8.17",
72
+ "@types/express": "^4.17.21",
73
+ "@types/node": "^20.0.0",
74
+ "@types/uuid": "^10.0.0",
75
+ "tsx": "^4.0.0"
76
+ },
77
+ "engines": {
78
+ "node": ">=18.0.0"
79
+ }
80
+ }
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: gitnexus-debugging
3
+ description: Trace bugs through call chains using knowledge graph
4
+ ---
5
+
6
+ # Debugging with GitNexus
7
+
8
+ ## Quick Start
9
+ ```
10
+ 0. If "Index is stale" → gitnexus_analyze({})
11
+ 1. gitnexus_search({query}) → Find code related to error
12
+ 2. gitnexus_explore({name, type: "symbol"}) → Get callers and callees
13
+ 3. READ gitnexus://process/{name} → Trace execution flow
14
+ ```
15
+
16
+ ## When to Use
17
+ - "Why is this function failing?"
18
+ - "Trace where this error comes from"
19
+ - "Who calls this method?"
20
+ - "Debug the payment issue"
21
+
22
+ ## Workflow Checklist
23
+ ```
24
+ Bug Investigation:
25
+ - [ ] Understand the symptom (error message, behavior)
26
+ - [ ] gitnexus_search to find related code
27
+ - [ ] Identify the suspect function
28
+ - [ ] gitnexus_explore to see callers/callees
29
+ - [ ] READ gitnexus://process/{name} if suspect is in a process
30
+ - [ ] READ gitnexus://schema for Cypher query help
31
+ - [ ] gitnexus_cypher for custom traces
32
+ ```
33
+
34
+ ## Resource Reference
35
+
36
+ ### gitnexus://schema
37
+ Graph schema for writing Cypher queries:
38
+ ```yaml
39
+ nodes: [Function, Class, Method, File, Community, Process]
40
+ relationships: [CALLS, IMPORTS, EXTENDS, IMPLEMENTS, MEMBER_OF, STEP_IN_PROCESS]
41
+ example_queries:
42
+ find_callers: |
43
+ MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "X"})
44
+ RETURN caller.name
45
+ ```
46
+
47
+ ### gitnexus://process/{name}
48
+ Trace execution flow to find where bug might occur:
49
+ ```yaml
50
+ name: CheckoutFlow
51
+ trace:
52
+ 1: handleCheckout
53
+ 2: validateCart
54
+ 3: processPayment ← bug here?
55
+ 4: sendConfirmation
56
+ ```
57
+
58
+ ## Tool Reference
59
+
60
+ ### gitnexus_search
61
+ Find code related to error or symptom:
62
+ ```
63
+ gitnexus_search({query: "payment validation error", depth: "full"})
64
+ ```
65
+
66
+ ### gitnexus_explore
67
+ Get symbol context:
68
+ ```
69
+ gitnexus_explore({name: "validatePayment", type: "symbol"})
70
+ → Callers: processCheckout, webhookHandler
71
+ → Callees: verifyCard, fetchRates
72
+ ```
73
+
74
+ ### gitnexus_cypher
75
+ Custom graph queries for tracing:
76
+ ```cypher
77
+ // Trace call chain (2 hops)
78
+ MATCH path = (a)-[:CodeRelation {type: 'CALLS'}*1..2]->(b:Function {name: "validatePayment"})
79
+ RETURN [n IN nodes(path) | n.name] AS chain
80
+ ```
81
+
82
+ ## Example: "Payment endpoint returns 500 intermittently"
83
+
84
+ ```
85
+ 1. gitnexus_search({query: "payment error handling"})
86
+ → validatePayment, handlePaymentError, PaymentException
87
+
88
+ 2. gitnexus_explore({name: "validatePayment", type: "symbol"})
89
+ → Callees: verifyCard, fetchRates (external API!)
90
+
91
+ 3. READ gitnexus://process/CheckoutFlow
92
+ → Step 3: validatePayment → calls external API
93
+
94
+ 4. Root cause: fetchRates calls external API without proper timeout
95
+ ```
96
+
97
+ ## Debugging Patterns
98
+
99
+ | Symptom | Approach |
100
+ |---------|----------|
101
+ | Error message | Search for error text, trace throw sites |
102
+ | Wrong return value | Trace data flow through callees |
103
+ | Intermittent failure | Look for external calls, timeouts |
104
+ | Performance issue | Find hot paths via callers count |