gitnexus 1.0.0 → 1.1.1
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/README.md +54 -39
- package/dist/cli/ai-context.js +23 -18
- package/dist/cli/analyze.js +16 -3
- package/dist/cli/clean.d.ts +2 -0
- package/dist/cli/clean.js +34 -3
- package/dist/cli/index.js +9 -3
- package/dist/cli/list.d.ts +1 -1
- package/dist/cli/list.js +22 -19
- package/dist/cli/mcp.d.ts +3 -2
- package/dist/cli/mcp.js +27 -76
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +166 -0
- package/dist/core/search/bm25-index.d.ts +2 -1
- package/dist/core/search/bm25-index.js +50 -8
- package/dist/mcp/core/kuzu-adapter.d.ts +14 -12
- package/dist/mcp/core/kuzu-adapter.js +99 -35
- package/dist/mcp/local/local-backend.d.ts +50 -42
- package/dist/mcp/local/local-backend.js +218 -212
- package/dist/mcp/resources.d.ts +4 -4
- package/dist/mcp/resources.js +129 -65
- package/dist/mcp/server.d.ts +5 -3
- package/dist/mcp/server.js +7 -9
- package/dist/mcp/tools.d.ts +1 -1
- package/dist/mcp/tools.js +25 -2
- package/dist/storage/repo-manager.d.ts +42 -0
- package/dist/storage/repo-manager.js +99 -0
- package/package.json +1 -1
- package/skills/debugging.md +15 -13
- package/skills/exploring.md +34 -20
- package/skills/impact-analysis.md +14 -11
- package/skills/refactoring.md +16 -15
package/README.md
CHANGED
|
@@ -13,41 +13,46 @@ Works with **Cursor**, **Claude Code**, **Windsurf**, **Cline**, **OpenCode**, a
|
|
|
13
13
|
|
|
14
14
|
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.
|
|
15
15
|
|
|
16
|
-
**
|
|
16
|
+
**Three commands to give your AI agent full codebase awareness.**
|
|
17
17
|
|
|
18
18
|
## Quick Start
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
#
|
|
22
|
-
|
|
21
|
+
# Install
|
|
22
|
+
npm install -g gitnexus
|
|
23
|
+
|
|
24
|
+
# One-time: configure MCP for your editors
|
|
25
|
+
gitnexus setup
|
|
26
|
+
|
|
27
|
+
# Index your repository (run from repo root)
|
|
28
|
+
gitnexus analyze
|
|
23
29
|
|
|
24
|
-
#
|
|
25
|
-
npx gitnexus mcp
|
|
30
|
+
# Done! Open your editor — MCP connects automatically.
|
|
26
31
|
```
|
|
27
32
|
|
|
28
|
-
Or
|
|
33
|
+
Or without installing globally:
|
|
29
34
|
|
|
30
35
|
```bash
|
|
31
|
-
|
|
32
|
-
gitnexus analyze
|
|
33
|
-
gitnexus mcp
|
|
36
|
+
npx gitnexus setup # one-time
|
|
37
|
+
npx gitnexus analyze # per repo
|
|
34
38
|
```
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
The `setup` command auto-detects Cursor, Claude Code, and OpenCode, then writes the correct global MCP config. You only run it once.
|
|
41
|
+
|
|
42
|
+
## MCP Setup (manual)
|
|
43
|
+
|
|
44
|
+
If you prefer to configure manually instead of using `gitnexus setup`:
|
|
37
45
|
|
|
38
46
|
### Cursor / Windsurf
|
|
39
47
|
|
|
40
|
-
Add to
|
|
48
|
+
Add to `~/.cursor/mcp.json` (global — works for all projects):
|
|
41
49
|
|
|
42
50
|
```json
|
|
43
51
|
{
|
|
44
52
|
"mcpServers": {
|
|
45
53
|
"gitnexus": {
|
|
46
54
|
"command": "npx",
|
|
47
|
-
"args": ["-y", "gitnexus", "mcp"]
|
|
48
|
-
"env": {
|
|
49
|
-
"GITNEXUS_CWD": "/path/to/your/repo"
|
|
50
|
-
}
|
|
55
|
+
"args": ["-y", "gitnexus", "mcp"]
|
|
51
56
|
}
|
|
52
57
|
}
|
|
53
58
|
}
|
|
@@ -61,7 +66,7 @@ claude mcp add gitnexus -- npx -y gitnexus mcp
|
|
|
61
66
|
|
|
62
67
|
### OpenCode
|
|
63
68
|
|
|
64
|
-
Add to
|
|
69
|
+
Add to `~/.config/opencode/config.json`:
|
|
65
70
|
|
|
66
71
|
```json
|
|
67
72
|
{
|
|
@@ -92,39 +97,48 @@ The result is a **KuzuDB graph database** stored locally in `.gitnexus/` with fu
|
|
|
92
97
|
|
|
93
98
|
Your AI agent gets these tools automatically:
|
|
94
99
|
|
|
95
|
-
| Tool | What It Does |
|
|
96
|
-
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
100
|
+
| Tool | What It Does | `repo` Param |
|
|
101
|
+
|------|-------------|--------------|
|
|
102
|
+
| `list_repos` | Discover all indexed repositories | — |
|
|
103
|
+
| `search` | Hybrid search (BM25 + semantic) with cluster context | Optional |
|
|
104
|
+
| `overview` | List all clusters and processes | Optional |
|
|
105
|
+
| `explore` | Deep dive on a symbol, cluster, or process | Optional |
|
|
106
|
+
| `impact` | Blast radius analysis | Optional |
|
|
107
|
+
| `cypher` | Raw Cypher graph queries | Optional |
|
|
108
|
+
| `analyze` | Index or re-index a repository | Optional |
|
|
109
|
+
|
|
110
|
+
> With one indexed repo, the `repo` param is optional. With multiple, specify which: `search({query: "auth", repo: "my-app"})`.
|
|
104
111
|
|
|
105
112
|
## MCP Resources
|
|
106
113
|
|
|
107
114
|
| Resource | Purpose |
|
|
108
115
|
|----------|---------|
|
|
109
|
-
| `gitnexus://
|
|
110
|
-
| `gitnexus://
|
|
111
|
-
| `gitnexus://
|
|
112
|
-
| `gitnexus://
|
|
113
|
-
| `gitnexus://
|
|
114
|
-
| `gitnexus://
|
|
116
|
+
| `gitnexus://repos` | List all indexed repositories (read first) |
|
|
117
|
+
| `gitnexus://repo/{name}/context` | Codebase stats and overview |
|
|
118
|
+
| `gitnexus://repo/{name}/clusters` | All functional clusters |
|
|
119
|
+
| `gitnexus://repo/{name}/cluster/{name}` | Cluster members and details |
|
|
120
|
+
| `gitnexus://repo/{name}/processes` | All execution flows |
|
|
121
|
+
| `gitnexus://repo/{name}/process/{name}` | Full process trace |
|
|
122
|
+
| `gitnexus://repo/{name}/schema` | Graph schema for Cypher queries |
|
|
115
123
|
|
|
116
124
|
## CLI Commands
|
|
117
125
|
|
|
118
126
|
```bash
|
|
119
|
-
gitnexus
|
|
120
|
-
gitnexus analyze
|
|
121
|
-
gitnexus
|
|
122
|
-
gitnexus
|
|
123
|
-
gitnexus
|
|
124
|
-
gitnexus
|
|
125
|
-
gitnexus
|
|
127
|
+
gitnexus setup # Configure MCP for your editors (one-time)
|
|
128
|
+
gitnexus analyze [path] # Index a repository (or update stale index)
|
|
129
|
+
gitnexus analyze --force # Force full re-index
|
|
130
|
+
gitnexus mcp # Start MCP server (stdio) — serves all indexed repos
|
|
131
|
+
gitnexus serve # Start HTTP server for web UI
|
|
132
|
+
gitnexus list # List all indexed repositories
|
|
133
|
+
gitnexus status # Show index status for current repo
|
|
134
|
+
gitnexus clean # Delete index for current repo
|
|
135
|
+
gitnexus clean --all # Delete all indexes
|
|
126
136
|
```
|
|
127
137
|
|
|
138
|
+
## Multi-Repo Support
|
|
139
|
+
|
|
140
|
+
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 with lazy KuzuDB connections.
|
|
141
|
+
|
|
128
142
|
## Supported Languages
|
|
129
143
|
|
|
130
144
|
TypeScript, JavaScript, Python, Java, C, C++, C#, Go, Rust
|
|
@@ -132,7 +146,7 @@ TypeScript, JavaScript, Python, Java, C, C++, C#, Go, Rust
|
|
|
132
146
|
## How Impact Analysis Works
|
|
133
147
|
|
|
134
148
|
```
|
|
135
|
-
gitnexus_impact("UserService", "upstream")
|
|
149
|
+
gitnexus_impact({target: "UserService", direction: "upstream", repo: "my-app"})
|
|
136
150
|
|
|
137
151
|
TARGET: Class UserService (src/services/user.ts)
|
|
138
152
|
|
|
@@ -169,6 +183,7 @@ These are installed automatically to `.claude/skills/` when you run `gitnexus an
|
|
|
169
183
|
- All processing happens locally on your machine
|
|
170
184
|
- No code is sent to any server
|
|
171
185
|
- Index stored in `.gitnexus/` inside your repo (gitignored)
|
|
186
|
+
- Global registry at `~/.gitnexus/` stores only paths and metadata
|
|
172
187
|
|
|
173
188
|
## Web UI
|
|
174
189
|
|
package/dist/cli/ai-context.js
CHANGED
|
@@ -20,7 +20,7 @@ function generateGitNexusContent(projectName, stats) {
|
|
|
20
20
|
return `${GITNEXUS_START_MARKER}
|
|
21
21
|
# GitNexus MCP
|
|
22
22
|
|
|
23
|
-
This project is indexed by GitNexus, providing AI agents with deep code intelligence.
|
|
23
|
+
This project is indexed as **${projectName}** by GitNexus, providing AI agents with deep code intelligence.
|
|
24
24
|
|
|
25
25
|
## Project: ${projectName}
|
|
26
26
|
|
|
@@ -35,48 +35,53 @@ This project is indexed by GitNexus, providing AI agents with deep code intellig
|
|
|
35
35
|
## Quick Start
|
|
36
36
|
|
|
37
37
|
\`\`\`
|
|
38
|
-
1. READ gitnexus://
|
|
39
|
-
2. READ gitnexus://
|
|
40
|
-
3. READ gitnexus://
|
|
41
|
-
4. gitnexus_search(query)
|
|
38
|
+
1. READ gitnexus://repos → Discover all indexed repos
|
|
39
|
+
2. READ gitnexus://repo/${projectName}/context → Get codebase overview (~150 tokens)
|
|
40
|
+
3. READ gitnexus://repo/${projectName}/clusters → See all functional clusters
|
|
41
|
+
4. gitnexus_search({query: "...", repo: "${projectName}"}) → Find code by query
|
|
42
42
|
\`\`\`
|
|
43
43
|
|
|
44
44
|
## Available Resources
|
|
45
45
|
|
|
46
46
|
| Resource | Purpose |
|
|
47
47
|
|----------|---------|
|
|
48
|
-
| \`gitnexus://
|
|
49
|
-
| \`gitnexus://
|
|
50
|
-
| \`gitnexus://
|
|
51
|
-
| \`gitnexus://
|
|
52
|
-
| \`gitnexus://
|
|
53
|
-
| \`gitnexus://
|
|
48
|
+
| \`gitnexus://repos\` | List all indexed repositories |
|
|
49
|
+
| \`gitnexus://repo/${projectName}/context\` | Codebase stats, tools, and resources overview |
|
|
50
|
+
| \`gitnexus://repo/${projectName}/clusters\` | All clusters with symbol counts and cohesion |
|
|
51
|
+
| \`gitnexus://repo/${projectName}/cluster/{name}\` | Cluster members and details |
|
|
52
|
+
| \`gitnexus://repo/${projectName}/processes\` | All execution flows with types |
|
|
53
|
+
| \`gitnexus://repo/${projectName}/process/{name}\` | Full process trace with steps |
|
|
54
|
+
| \`gitnexus://repo/${projectName}/schema\` | Graph schema for Cypher queries |
|
|
54
55
|
|
|
55
56
|
## Available Tools
|
|
56
57
|
|
|
57
58
|
| Tool | Purpose | When to Use |
|
|
58
59
|
|------|---------|-------------|
|
|
60
|
+
| \`list_repos\` | Discover indexed repos | First step with multiple repos |
|
|
59
61
|
| \`search\` | Semantic + keyword search | Finding code by query |
|
|
60
62
|
| \`overview\` | List clusters & processes | Understanding architecture |
|
|
61
63
|
| \`explore\` | Deep dive on symbol/cluster/process | Detailed investigation |
|
|
62
64
|
| \`impact\` | Blast radius analysis | Before making changes |
|
|
63
65
|
| \`cypher\` | Raw graph queries | Complex analysis |
|
|
64
66
|
|
|
67
|
+
> **Multi-repo:** When multiple repos are indexed, pass \`repo: "${projectName}"\` to target this project.
|
|
68
|
+
|
|
65
69
|
## Workflow Examples
|
|
66
70
|
|
|
67
71
|
### Exploring the Codebase
|
|
68
72
|
\`\`\`
|
|
69
|
-
READ gitnexus://
|
|
70
|
-
READ gitnexus://
|
|
71
|
-
READ gitnexus://
|
|
72
|
-
|
|
73
|
+
READ gitnexus://repos → Discover repos
|
|
74
|
+
READ gitnexus://repo/${projectName}/context → Stats and overview
|
|
75
|
+
READ gitnexus://repo/${projectName}/clusters → Find relevant cluster
|
|
76
|
+
READ gitnexus://repo/${projectName}/cluster/Auth → Explore Auth cluster
|
|
77
|
+
gitnexus_explore({name: "validateUser", type: "symbol", repo: "${projectName}"})
|
|
73
78
|
\`\`\`
|
|
74
79
|
|
|
75
80
|
### Planning a Change
|
|
76
81
|
\`\`\`
|
|
77
|
-
gitnexus_impact("UserService", "upstream"
|
|
78
|
-
READ gitnexus://processes
|
|
79
|
-
gitnexus_explore("LoginFlow", "process"
|
|
82
|
+
gitnexus_impact({target: "UserService", direction: "upstream", repo: "${projectName}"})
|
|
83
|
+
READ gitnexus://repo/${projectName}/processes → Check affected flows
|
|
84
|
+
gitnexus_explore({name: "LoginFlow", type: "process", repo: "${projectName}"})
|
|
80
85
|
\`\`\`
|
|
81
86
|
|
|
82
87
|
## Graph Schema
|
package/dist/cli/analyze.js
CHANGED
|
@@ -8,9 +8,10 @@ import ora from 'ora';
|
|
|
8
8
|
import { runPipelineFromRepo } from '../core/ingestion/pipeline.js';
|
|
9
9
|
import { initKuzu, loadGraphToKuzu, getKuzuStats, executeQuery, executeWithReusedStatement, closeKuzu, createFTSIndex } from '../core/kuzu/kuzu-adapter.js';
|
|
10
10
|
import { runEmbeddingPipeline } from '../core/embeddings/embedding-pipeline.js';
|
|
11
|
-
import { getStoragePaths, saveMeta, loadMeta, addToGitignore } from '../storage/repo-manager.js';
|
|
11
|
+
import { getStoragePaths, saveMeta, loadMeta, addToGitignore, registerRepo, getGlobalRegistryPath } from '../storage/repo-manager.js';
|
|
12
12
|
import { getCurrentCommit, isGitRepo, getGitRoot } from '../storage/git.js';
|
|
13
13
|
import { generateAIContextFiles } from './ai-context.js';
|
|
14
|
+
import fs from 'fs/promises';
|
|
14
15
|
export const analyzeCommand = async (inputPath, options) => {
|
|
15
16
|
const spinner = ora('Checking repository...').start();
|
|
16
17
|
// If path provided, use it directly. Otherwise, find git root from cwd.
|
|
@@ -83,7 +84,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
83
84
|
}
|
|
84
85
|
// Save metadata
|
|
85
86
|
const stats = await getKuzuStats();
|
|
86
|
-
|
|
87
|
+
const meta = {
|
|
87
88
|
repoPath,
|
|
88
89
|
lastCommit: currentCommit,
|
|
89
90
|
indexedAt: new Date().toISOString(),
|
|
@@ -94,7 +95,10 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
94
95
|
communities: pipelineResult.communityResult?.stats.totalCommunities,
|
|
95
96
|
processes: pipelineResult.processResult?.stats.totalProcesses,
|
|
96
97
|
},
|
|
97
|
-
}
|
|
98
|
+
};
|
|
99
|
+
await saveMeta(storagePath, meta);
|
|
100
|
+
// Register in global registry
|
|
101
|
+
await registerRepo(repoPath, meta);
|
|
98
102
|
// Add .gitnexus to .gitignore
|
|
99
103
|
await addToGitignore(repoPath);
|
|
100
104
|
// Generate AI context files
|
|
@@ -115,4 +119,13 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
115
119
|
if (aiContext.files.length > 0) {
|
|
116
120
|
console.log(` AI Context: ${aiContext.files.join(', ')}`);
|
|
117
121
|
}
|
|
122
|
+
// Hint about setup if it hasn't been run
|
|
123
|
+
try {
|
|
124
|
+
await fs.access(getGlobalRegistryPath());
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Registry didn't exist before this run — suggest setup
|
|
128
|
+
console.log('');
|
|
129
|
+
console.log(' Tip: Run `gitnexus setup` to configure MCP for your editor.');
|
|
130
|
+
}
|
|
118
131
|
};
|
package/dist/cli/clean.d.ts
CHANGED
package/dist/cli/clean.js
CHANGED
|
@@ -2,10 +2,40 @@
|
|
|
2
2
|
* Clean Command
|
|
3
3
|
*
|
|
4
4
|
* Removes the .gitnexus index from the current repository.
|
|
5
|
+
* Also unregisters it from the global registry.
|
|
5
6
|
*/
|
|
6
7
|
import fs from 'fs/promises';
|
|
7
|
-
import { findRepo } from '../storage/repo-manager.js';
|
|
8
|
+
import { findRepo, unregisterRepo, listRegisteredRepos } from '../storage/repo-manager.js';
|
|
8
9
|
export const cleanCommand = async (options) => {
|
|
10
|
+
// --all flag: clean all indexed repos
|
|
11
|
+
if (options?.all) {
|
|
12
|
+
if (!options?.force) {
|
|
13
|
+
const entries = await listRegisteredRepos();
|
|
14
|
+
if (entries.length === 0) {
|
|
15
|
+
console.log('No indexed repositories found.');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
console.log(`This will delete GitNexus indexes for ${entries.length} repo(s):`);
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
console.log(` - ${entry.name} (${entry.path})`);
|
|
21
|
+
}
|
|
22
|
+
console.log('\nRun with --force to confirm deletion.');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const entries = await listRegisteredRepos();
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
try {
|
|
28
|
+
await fs.rm(entry.storagePath, { recursive: true, force: true });
|
|
29
|
+
await unregisterRepo(entry.path);
|
|
30
|
+
console.log(`Deleted: ${entry.name} (${entry.storagePath})`);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.error(`Failed to delete ${entry.name}:`, err);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// Default: clean current repo
|
|
9
39
|
const cwd = process.cwd();
|
|
10
40
|
const repo = await findRepo(cwd);
|
|
11
41
|
if (!repo) {
|
|
@@ -14,14 +44,15 @@ export const cleanCommand = async (options) => {
|
|
|
14
44
|
}
|
|
15
45
|
const repoName = repo.repoPath.split(/[/\\]/).pop() || repo.repoPath;
|
|
16
46
|
if (!options?.force) {
|
|
17
|
-
console.log(
|
|
47
|
+
console.log(`This will delete the GitNexus index for: ${repoName}`);
|
|
18
48
|
console.log(` Path: ${repo.storagePath}`);
|
|
19
49
|
console.log('\nRun with --force to confirm deletion.');
|
|
20
50
|
return;
|
|
21
51
|
}
|
|
22
52
|
try {
|
|
23
53
|
await fs.rm(repo.storagePath, { recursive: true, force: true });
|
|
24
|
-
|
|
54
|
+
await unregisterRepo(repo.repoPath);
|
|
55
|
+
console.log(`Deleted: ${repo.storagePath}`);
|
|
25
56
|
}
|
|
26
57
|
catch (err) {
|
|
27
58
|
console.error('Failed to delete:', err);
|
package/dist/cli/index.js
CHANGED
|
@@ -6,11 +6,16 @@ import { listCommand } from './list.js';
|
|
|
6
6
|
import { statusCommand } from './status.js';
|
|
7
7
|
import { mcpCommand } from './mcp.js';
|
|
8
8
|
import { cleanCommand } from './clean.js';
|
|
9
|
+
import { setupCommand } from './setup.js';
|
|
9
10
|
const program = new Command();
|
|
10
11
|
program
|
|
11
12
|
.name('gitnexus')
|
|
12
13
|
.description('GitNexus local CLI and MCP server')
|
|
13
|
-
.version('1.
|
|
14
|
+
.version('1.1.1');
|
|
15
|
+
program
|
|
16
|
+
.command('setup')
|
|
17
|
+
.description('One-time setup: configure MCP for Cursor, Claude Code, OpenCode')
|
|
18
|
+
.action(setupCommand);
|
|
14
19
|
program
|
|
15
20
|
.command('analyze [path]')
|
|
16
21
|
.description('Index a repository (full analysis)')
|
|
@@ -24,11 +29,11 @@ program
|
|
|
24
29
|
.action(serveCommand);
|
|
25
30
|
program
|
|
26
31
|
.command('mcp')
|
|
27
|
-
.description('Start MCP server (stdio)')
|
|
32
|
+
.description('Start MCP server (stdio) — serves all indexed repos')
|
|
28
33
|
.action(mcpCommand);
|
|
29
34
|
program
|
|
30
35
|
.command('list')
|
|
31
|
-
.description('List indexed repositories')
|
|
36
|
+
.description('List all indexed repositories')
|
|
32
37
|
.action(listCommand);
|
|
33
38
|
program
|
|
34
39
|
.command('status')
|
|
@@ -38,5 +43,6 @@ program
|
|
|
38
43
|
.command('clean')
|
|
39
44
|
.description('Delete GitNexus index for current repo')
|
|
40
45
|
.option('-f, --force', 'Skip confirmation prompt')
|
|
46
|
+
.option('--all', 'Clean all indexed repos')
|
|
41
47
|
.action(cleanCommand);
|
|
42
48
|
program.parse(process.argv);
|
package/dist/cli/list.d.ts
CHANGED
package/dist/cli/list.js
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* List Command
|
|
3
3
|
*
|
|
4
|
-
* Shows
|
|
4
|
+
* Shows all indexed repositories from the global registry.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { listRegisteredRepos } from '../storage/repo-manager.js';
|
|
7
7
|
export const listCommand = async () => {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
console.log('
|
|
12
|
-
console.log('Run `gitnexus analyze` to index your codebase.');
|
|
8
|
+
const entries = await listRegisteredRepos({ validate: true });
|
|
9
|
+
if (entries.length === 0) {
|
|
10
|
+
console.log('No indexed repositories found.');
|
|
11
|
+
console.log('Run `gitnexus analyze` in a git repo to index it.');
|
|
13
12
|
return;
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
console.log(`
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
console.log(`\n Indexed Repositories (${entries.length})\n`);
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
const indexedDate = new Date(entry.indexedAt).toLocaleString();
|
|
17
|
+
const stats = entry.stats || {};
|
|
18
|
+
const commitShort = entry.lastCommit?.slice(0, 7) || 'unknown';
|
|
19
|
+
console.log(` ${entry.name}`);
|
|
20
|
+
console.log(` Path: ${entry.path}`);
|
|
21
|
+
console.log(` Indexed: ${indexedDate}`);
|
|
22
|
+
console.log(` Commit: ${commitShort}`);
|
|
23
|
+
console.log(` Stats: ${stats.files ?? 0} files, ${stats.nodes ?? 0} symbols, ${stats.edges ?? 0} edges`);
|
|
24
|
+
if (stats.communities)
|
|
25
|
+
console.log(` Clusters: ${stats.communities}`);
|
|
26
|
+
if (stats.processes)
|
|
27
|
+
console.log(` Processes: ${stats.processes}`);
|
|
28
|
+
console.log('');
|
|
29
|
+
}
|
|
27
30
|
};
|
package/dist/cli/mcp.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Command
|
|
3
3
|
*
|
|
4
|
-
* Starts the MCP server in standalone mode
|
|
5
|
-
*
|
|
4
|
+
* Starts the MCP server in standalone mode.
|
|
5
|
+
* Loads all indexed repos from the global registry.
|
|
6
|
+
* No longer depends on cwd — works from any directory.
|
|
6
7
|
*/
|
|
7
8
|
export declare const mcpCommand: () => Promise<void>;
|
package/dist/cli/mcp.js
CHANGED
|
@@ -1,85 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Command
|
|
3
3
|
*
|
|
4
|
-
* Starts the MCP server in standalone mode
|
|
5
|
-
*
|
|
4
|
+
* Starts the MCP server in standalone mode.
|
|
5
|
+
* Loads all indexed repos from the global registry.
|
|
6
|
+
* No longer depends on cwd — works from any directory.
|
|
6
7
|
*/
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import fs from 'fs/promises';
|
|
9
8
|
import { startMCPServer } from '../mcp/server.js';
|
|
10
|
-
import { LocalBackend
|
|
11
|
-
|
|
12
|
-
* Get candidate paths to search for .gitnexus/ folder
|
|
13
|
-
*/
|
|
14
|
-
function getCandidatePaths() {
|
|
15
|
-
const candidates = [];
|
|
16
|
-
// 1. Explicit override (highest priority)
|
|
17
|
-
if (process.env.GITNEXUS_CWD) {
|
|
18
|
-
candidates.push(process.env.GITNEXUS_CWD);
|
|
19
|
-
}
|
|
20
|
-
// 2. Current working directory
|
|
21
|
-
candidates.push(process.cwd());
|
|
22
|
-
// 3. VS Code workspace folders (if available via env)
|
|
23
|
-
if (process.env.VSCODE_WORKSPACE_FOLDER) {
|
|
24
|
-
candidates.push(process.env.VSCODE_WORKSPACE_FOLDER);
|
|
25
|
-
}
|
|
26
|
-
// Deduplicate while preserving order
|
|
27
|
-
return [...new Set(candidates.map(p => path.resolve(p)))];
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Find a git repository root by walking up the directory tree
|
|
31
|
-
*/
|
|
32
|
-
async function findGitRoot(startPath) {
|
|
33
|
-
let current = path.resolve(startPath);
|
|
34
|
-
const root = path.parse(current).root;
|
|
35
|
-
while (current !== root) {
|
|
36
|
-
try {
|
|
37
|
-
const gitPath = path.join(current, '.git');
|
|
38
|
-
const stat = await fs.stat(gitPath);
|
|
39
|
-
if (stat.isDirectory())
|
|
40
|
-
return current;
|
|
41
|
-
}
|
|
42
|
-
catch { }
|
|
43
|
-
current = path.dirname(current);
|
|
44
|
-
}
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
9
|
+
import { LocalBackend } from '../mcp/local/local-backend.js';
|
|
10
|
+
import { listRegisteredRepos } from '../storage/repo-manager.js';
|
|
47
11
|
export const mcpCommand = async () => {
|
|
48
|
-
//
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
12
|
+
// Load all registered repos
|
|
13
|
+
const entries = await listRegisteredRepos({ validate: true });
|
|
14
|
+
if (entries.length === 0) {
|
|
15
|
+
console.error('');
|
|
16
|
+
console.error(' GitNexus: No indexed repositories found.');
|
|
17
|
+
console.error('');
|
|
18
|
+
console.error(' To get started:');
|
|
19
|
+
console.error(' 1. cd into a git repository');
|
|
20
|
+
console.error(' 2. Run: gitnexus analyze');
|
|
21
|
+
console.error(' 3. Restart your editor');
|
|
22
|
+
console.error('');
|
|
23
|
+
process.exit(1);
|
|
60
24
|
}
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
console.error('║ GitNexus: Repository Not Indexed ║');
|
|
68
|
-
console.error('╠════════════════════════════════════════════════════╣');
|
|
69
|
-
console.error(`║ Found git repo: ${gitRoot.slice(0, 35).padEnd(35)} ║`);
|
|
70
|
-
console.error('║ ║');
|
|
71
|
-
console.error('║ To enable AI code understanding, run: ║');
|
|
72
|
-
console.error('║ ║');
|
|
73
|
-
console.error('║ npx gitnexus analyze ║');
|
|
74
|
-
console.error('║ ║');
|
|
75
|
-
console.error('║ Then restart your IDE. ║');
|
|
76
|
-
console.error('╚════════════════════════════════════════════════════╝');
|
|
77
|
-
console.error('');
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
25
|
+
// Initialize multi-repo backend from registry
|
|
26
|
+
const backend = new LocalBackend();
|
|
27
|
+
const ok = await backend.init();
|
|
28
|
+
if (!ok) {
|
|
29
|
+
console.error('GitNexus: Failed to initialize backend from registry.');
|
|
30
|
+
process.exit(1);
|
|
80
31
|
}
|
|
81
|
-
|
|
82
|
-
console.error(
|
|
83
|
-
|
|
84
|
-
|
|
32
|
+
const repoNames = backend.listRepos().map(r => r.name);
|
|
33
|
+
console.error(`GitNexus: MCP server starting with ${repoNames.length} repo(s): ${repoNames.join(', ')}`);
|
|
34
|
+
// Start MCP server (serves all repos)
|
|
35
|
+
await startMCPServer(backend);
|
|
85
36
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup Command
|
|
3
|
+
*
|
|
4
|
+
* One-time global MCP configuration writer.
|
|
5
|
+
* Detects installed AI editors and writes the appropriate MCP config
|
|
6
|
+
* so the GitNexus MCP server is available in all projects.
|
|
7
|
+
*/
|
|
8
|
+
export declare const setupCommand: () => Promise<void>;
|