claude-ex 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.
- package/README.md +65 -0
- package/dist/claude/claudemd.d.ts +3 -0
- package/dist/claude/claudemd.js +112 -0
- package/dist/claude/claudemd.js.map +1 -0
- package/dist/claude/installer.d.ts +1 -0
- package/dist/claude/installer.js +193 -0
- package/dist/claude/installer.js.map +1 -0
- package/dist/claude/mcp.d.ts +1 -0
- package/dist/claude/mcp.js +195 -0
- package/dist/claude/mcp.js.map +1 -0
- package/dist/db/schema.d.ts +25 -0
- package/dist/db/schema.js +218 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +339 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/collector.d.ts +1 -0
- package/dist/indexer/collector.js +133 -0
- package/dist/indexer/collector.js.map +1 -0
- package/dist/indexer/index.d.ts +13 -0
- package/dist/indexer/index.js +326 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/parser.d.ts +31 -0
- package/dist/indexer/parser.js +407 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/query/engine.d.ts +65 -0
- package/dist/query/engine.js +340 -0
- package/dist/query/engine.js.map +1 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +75 -0
- package/dist/utils.js.map +1 -0
- package/dist/watcher/daemon.d.ts +5 -0
- package/dist/watcher/daemon.js +136 -0
- package/dist/watcher/daemon.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# claude-ex
|
|
2
|
+
|
|
3
|
+
Local code intelligence layer for Claude Code. Indexes your codebase into a SQLite graph database (symbols + dependency edges + PageRank), then runs as a persistent MCP server that Claude Code queries in real-time.
|
|
4
|
+
|
|
5
|
+
Zero cloud. Zero API keys. Zero extra cost. Just your existing Claude Code subscription, supercharged.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install
|
|
11
|
+
npm run build
|
|
12
|
+
npm link
|
|
13
|
+
|
|
14
|
+
cd /path/to/your/project
|
|
15
|
+
claude-ex init
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Then open Claude Code — the MCP server starts automatically and gives Claude structural awareness of your entire codebase.
|
|
19
|
+
|
|
20
|
+
## How It Works
|
|
21
|
+
|
|
22
|
+
1. **Indexes** your codebase using tree-sitter (functions, classes, methods, imports, call graphs)
|
|
23
|
+
2. **Computes PageRank** to identify structurally important symbols
|
|
24
|
+
3. **Runs as MCP server** with the SQLite database held open in memory — every query answers in <5ms
|
|
25
|
+
4. **Watches files** for changes and reindexes in <15ms
|
|
26
|
+
5. **Hooks into Claude Code** to inject context before/after edits
|
|
27
|
+
|
|
28
|
+
## MCP Tools
|
|
29
|
+
|
|
30
|
+
| Tool | What it does | Speed |
|
|
31
|
+
|------|-------------|-------|
|
|
32
|
+
| `search_code` | Hybrid FTS5 + PageRank search | 1-3ms |
|
|
33
|
+
| `get_symbol` | Full context for a symbol | 2-4ms |
|
|
34
|
+
| `get_callers` | Who calls this function | 1-3ms |
|
|
35
|
+
| `get_dependents` | What breaks if a file changes | 2-5ms |
|
|
36
|
+
| `get_dependencies` | What a symbol depends on | 1-3ms |
|
|
37
|
+
| `get_architecture` | Project overview | 3-5ms |
|
|
38
|
+
|
|
39
|
+
## CLI Commands
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
claude-ex init [path] Index + install config + generate docs
|
|
43
|
+
claude-ex search <query> Search symbols
|
|
44
|
+
claude-ex callers <symbol> Find callers
|
|
45
|
+
claude-ex context <symbol> Full symbol context
|
|
46
|
+
claude-ex impact <file> Impact analysis
|
|
47
|
+
claude-ex deps <symbol> Dependencies
|
|
48
|
+
claude-ex rank Top symbols by PageRank
|
|
49
|
+
claude-ex modules Module map
|
|
50
|
+
claude-ex stats Index statistics
|
|
51
|
+
claude-ex brief Project summary (SessionStart hook)
|
|
52
|
+
claude-ex pre-edit <file> Pre-edit context (PreToolUse hook)
|
|
53
|
+
claude-ex post-edit <file> Post-edit reindex (PostToolUse hook)
|
|
54
|
+
claude-ex generate-docs Regenerate CLAUDE.md
|
|
55
|
+
claude-ex mcp Run as MCP server
|
|
56
|
+
claude-ex uninstall Remove all config
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Supported Languages
|
|
60
|
+
|
|
61
|
+
TypeScript, JavaScript, Python, Rust, Go, C, C++, Bash, JSON, CSS, HTML
|
|
62
|
+
|
|
63
|
+
## License
|
|
64
|
+
|
|
65
|
+
MIT
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateClaudeMd = generateClaudeMd;
|
|
37
|
+
exports.writeClaudeMd = writeClaudeMd;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const schema_1 = require("../db/schema");
|
|
41
|
+
const engine_1 = require("../query/engine");
|
|
42
|
+
const MARKER_START = '<!-- claude-ex:start -->';
|
|
43
|
+
const MARKER_END = '<!-- claude-ex:end -->';
|
|
44
|
+
function generateClaudeMd(rootDir, db) {
|
|
45
|
+
const shouldClose = !db;
|
|
46
|
+
if (!db)
|
|
47
|
+
db = (0, schema_1.openDatabase)(rootDir);
|
|
48
|
+
try {
|
|
49
|
+
const stats = (0, engine_1.getStats)(db);
|
|
50
|
+
const topSymbols = (0, engine_1.getRank)(db, 15);
|
|
51
|
+
const modules = (0, engine_1.getModules)(db);
|
|
52
|
+
const dirname = path.basename(rootDir);
|
|
53
|
+
// Language breakdown
|
|
54
|
+
const langs = db.prepare(`
|
|
55
|
+
SELECT language, COUNT(*) as cnt FROM files WHERE language IS NOT NULL GROUP BY language ORDER BY cnt DESC
|
|
56
|
+
`).all();
|
|
57
|
+
const lines = [];
|
|
58
|
+
lines.push(MARKER_START);
|
|
59
|
+
lines.push(`# Project: ${dirname}`);
|
|
60
|
+
lines.push('');
|
|
61
|
+
lines.push('## Architecture');
|
|
62
|
+
lines.push(`- **Languages**: ${langs.map(l => `${l.language} (${l.cnt} files)`).join(', ')}`);
|
|
63
|
+
lines.push(`- **Size**: ${stats.files} files, ${stats.symbols} symbols, ${stats.edges} relationships`);
|
|
64
|
+
lines.push('');
|
|
65
|
+
if (topSymbols.length > 0) {
|
|
66
|
+
lines.push('## Key Symbols (by structural importance)');
|
|
67
|
+
for (let i = 0; i < topSymbols.length; i++) {
|
|
68
|
+
const sym = topSymbols[i];
|
|
69
|
+
lines.push(`${i + 1}. \`${sym.qualifiedName || sym.name}\` [${sym.kind}] in ${sym.file}`);
|
|
70
|
+
}
|
|
71
|
+
lines.push('');
|
|
72
|
+
}
|
|
73
|
+
if (modules.length > 0) {
|
|
74
|
+
lines.push('## Module Map');
|
|
75
|
+
for (const mod of modules.slice(0, 15)) {
|
|
76
|
+
const imports = mod.importsFrom.length > 0
|
|
77
|
+
? ` \u2192 imports from: ${mod.importsFrom.join(', ')}`
|
|
78
|
+
: ' \u2192 imports from: (none \u2014 leaf dependency)';
|
|
79
|
+
lines.push(`${mod.name}/ (${mod.fileCount} files, ${mod.symbolCount} symbols)${imports}`);
|
|
80
|
+
}
|
|
81
|
+
lines.push('');
|
|
82
|
+
}
|
|
83
|
+
lines.push('*Auto-generated by claude-ex. Run `claude-ex generate-docs` to regenerate.*');
|
|
84
|
+
lines.push(MARKER_END);
|
|
85
|
+
return lines.join('\n');
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
if (shouldClose)
|
|
89
|
+
db.close();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function writeClaudeMd(rootDir, db) {
|
|
93
|
+
const content = generateClaudeMd(rootDir, db);
|
|
94
|
+
const claudeMdPath = path.join(rootDir, 'CLAUDE.md');
|
|
95
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
96
|
+
const existing = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
97
|
+
if (existing.includes(MARKER_START) && existing.includes(MARKER_END)) {
|
|
98
|
+
// Replace existing section
|
|
99
|
+
const before = existing.slice(0, existing.indexOf(MARKER_START));
|
|
100
|
+
const after = existing.slice(existing.indexOf(MARKER_END) + MARKER_END.length);
|
|
101
|
+
fs.writeFileSync(claudeMdPath, before + content + after);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// Append
|
|
105
|
+
fs.writeFileSync(claudeMdPath, existing.trimEnd() + '\n\n' + content + '\n');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
fs.writeFileSync(claudeMdPath, content + '\n');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=claudemd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudemd.js","sourceRoot":"","sources":["../../src/claude/claudemd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function install(rootDir: string): void;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.install = install;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const SKILL_CONTENT = `---
|
|
40
|
+
name: claude-ex
|
|
41
|
+
description: >
|
|
42
|
+
Local codebase intelligence via MCP. Use for: finding code, understanding
|
|
43
|
+
architecture, tracing dependencies, impact analysis, finding callers,
|
|
44
|
+
understanding what a file/function does in context. Triggers: "what calls",
|
|
45
|
+
"who uses", "what depends on", "where is", "how does X work", "what breaks if",
|
|
46
|
+
"find", "search codebase", "show me", refactoring, architecture questions.
|
|
47
|
+
PREFER these MCP tools over grep/ripgrep for structural queries.
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
# claude-ex — Codebase Intelligence (MCP)
|
|
51
|
+
|
|
52
|
+
This project has a live code index exposed via MCP. The MCP tools are
|
|
53
|
+
**much faster and more precise than grep** for structural questions.
|
|
54
|
+
|
|
55
|
+
## MCP Tools Available
|
|
56
|
+
|
|
57
|
+
Use these tools via the MCP connection. They answer in <5ms.
|
|
58
|
+
|
|
59
|
+
### search_code
|
|
60
|
+
Find symbols by name, description, or content. Results ranked by structural
|
|
61
|
+
importance (PageRank). Use for any "find X" or "where is X" question.
|
|
62
|
+
|
|
63
|
+
### get_symbol
|
|
64
|
+
Full context for a single symbol: its code, what it depends on, what depends
|
|
65
|
+
on it, what else is in the same file. Use before modifying any symbol.
|
|
66
|
+
|
|
67
|
+
### get_callers
|
|
68
|
+
Who calls this function/method. Use before renaming, changing signatures,
|
|
69
|
+
or removing a function.
|
|
70
|
+
|
|
71
|
+
### get_dependents
|
|
72
|
+
What files are transitively affected if a file changes. Use before any
|
|
73
|
+
refactor that changes exports or file structure.
|
|
74
|
+
|
|
75
|
+
### get_dependencies
|
|
76
|
+
What a symbol imports/uses. Understand what it needs before moving or
|
|
77
|
+
modifying it.
|
|
78
|
+
|
|
79
|
+
### get_architecture
|
|
80
|
+
Project overview: top symbols, module map, language breakdown.
|
|
81
|
+
Use when you need to understand the overall structure.
|
|
82
|
+
|
|
83
|
+
## When to prefer MCP tools over grep
|
|
84
|
+
- "What calls processPayment?" → get_callers (not grep — grep misses indirect references)
|
|
85
|
+
- "What breaks if I change auth.ts?" → get_dependents (not grep — grep can't trace transitive deps)
|
|
86
|
+
- "Find the main payment handling code" → search_code (PageRank-weighted, finds the important one)
|
|
87
|
+
- "Show me the PaymentService" → get_symbol (includes dependencies + dependents, not just code)
|
|
88
|
+
|
|
89
|
+
## When to use grep instead
|
|
90
|
+
- Simple string search: "find all TODOs" → grep
|
|
91
|
+
- Regex patterns: "find all console.log" → grep
|
|
92
|
+
- File listing: "show all test files" → find
|
|
93
|
+
`;
|
|
94
|
+
function install(rootDir) {
|
|
95
|
+
// 1. Ensure .codex/ exists and is in .gitignore
|
|
96
|
+
const codexDir = path.join(rootDir, '.codex');
|
|
97
|
+
if (!fs.existsSync(codexDir)) {
|
|
98
|
+
fs.mkdirSync(codexDir, { recursive: true });
|
|
99
|
+
}
|
|
100
|
+
addToGitignore(rootDir, '.codex/');
|
|
101
|
+
// 2. Create/merge .mcp.json
|
|
102
|
+
installMcpConfig(rootDir);
|
|
103
|
+
// 3. Create/merge .claude/settings.json
|
|
104
|
+
installHooks(rootDir);
|
|
105
|
+
// 4. Create skill file
|
|
106
|
+
installSkill(rootDir);
|
|
107
|
+
}
|
|
108
|
+
function addToGitignore(rootDir, entry) {
|
|
109
|
+
const gitignorePath = path.join(rootDir, '.gitignore');
|
|
110
|
+
let content = '';
|
|
111
|
+
if (fs.existsSync(gitignorePath)) {
|
|
112
|
+
content = fs.readFileSync(gitignorePath, 'utf-8');
|
|
113
|
+
}
|
|
114
|
+
if (!content.split('\n').some(line => line.trim() === entry)) {
|
|
115
|
+
content = content.trimEnd() + '\n' + entry + '\n';
|
|
116
|
+
fs.writeFileSync(gitignorePath, content);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function installMcpConfig(rootDir) {
|
|
120
|
+
const mcpPath = path.join(rootDir, '.mcp.json');
|
|
121
|
+
let config = {};
|
|
122
|
+
if (fs.existsSync(mcpPath)) {
|
|
123
|
+
try {
|
|
124
|
+
config = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
config = {};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!config.mcpServers)
|
|
131
|
+
config.mcpServers = {};
|
|
132
|
+
config.mcpServers.codex = {
|
|
133
|
+
type: 'stdio',
|
|
134
|
+
command: 'claude-ex',
|
|
135
|
+
args: ['mcp'],
|
|
136
|
+
};
|
|
137
|
+
fs.writeFileSync(mcpPath, JSON.stringify(config, null, 2) + '\n');
|
|
138
|
+
}
|
|
139
|
+
function installHooks(rootDir) {
|
|
140
|
+
const claudeDir = path.join(rootDir, '.claude');
|
|
141
|
+
if (!fs.existsSync(claudeDir)) {
|
|
142
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
143
|
+
}
|
|
144
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
145
|
+
let config = {};
|
|
146
|
+
if (fs.existsSync(settingsPath)) {
|
|
147
|
+
try {
|
|
148
|
+
config = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
config = {};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!config.hooks)
|
|
155
|
+
config.hooks = {};
|
|
156
|
+
// SessionStart
|
|
157
|
+
if (!config.hooks.SessionStart)
|
|
158
|
+
config.hooks.SessionStart = [];
|
|
159
|
+
if (!config.hooks.SessionStart.some((h) => h.command?.includes('claude-ex'))) {
|
|
160
|
+
config.hooks.SessionStart.push({
|
|
161
|
+
matcher: '',
|
|
162
|
+
command: 'claude-ex brief',
|
|
163
|
+
timeout: 5000,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// PreToolUse
|
|
167
|
+
if (!config.hooks.PreToolUse)
|
|
168
|
+
config.hooks.PreToolUse = [];
|
|
169
|
+
if (!config.hooks.PreToolUse.some((h) => h.command?.includes('claude-ex'))) {
|
|
170
|
+
config.hooks.PreToolUse.push({
|
|
171
|
+
matcher: 'Write|Edit|MultiEdit',
|
|
172
|
+
command: 'claude-ex pre-edit "$(cat /dev/stdin | jq -r \'.tool_input.file_path\')"',
|
|
173
|
+
timeout: 3000,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
// PostToolUse
|
|
177
|
+
if (!config.hooks.PostToolUse)
|
|
178
|
+
config.hooks.PostToolUse = [];
|
|
179
|
+
if (!config.hooks.PostToolUse.some((h) => h.command?.includes('claude-ex'))) {
|
|
180
|
+
config.hooks.PostToolUse.push({
|
|
181
|
+
matcher: 'Write|Edit|MultiEdit',
|
|
182
|
+
command: 'claude-ex post-edit "$(cat /dev/stdin | jq -r \'.tool_input.file_path\')"',
|
|
183
|
+
timeout: 5000,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
fs.writeFileSync(settingsPath, JSON.stringify(config, null, 2) + '\n');
|
|
187
|
+
}
|
|
188
|
+
function installSkill(rootDir) {
|
|
189
|
+
const skillDir = path.join(rootDir, '.claude', 'skills', 'codex');
|
|
190
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
191
|
+
fs.writeFileSync(path.join(skillDir, 'SKILL.md'), SKILL_CONTENT);
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/claude/installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runMcpServer(): Promise<void>;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runMcpServer = runMcpServer;
|
|
4
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
7
|
+
const schema_1 = require("../db/schema");
|
|
8
|
+
const utils_1 = require("../utils");
|
|
9
|
+
const daemon_1 = require("../watcher/daemon");
|
|
10
|
+
const engine_1 = require("../query/engine");
|
|
11
|
+
const indexer_1 = require("../indexer");
|
|
12
|
+
async function runMcpServer() {
|
|
13
|
+
const rootDir = (0, utils_1.findProjectRoot)() || process.env.CODEX_ROOT || process.cwd();
|
|
14
|
+
const startTime = performance.now();
|
|
15
|
+
// Open database (stays open for lifetime)
|
|
16
|
+
let db;
|
|
17
|
+
try {
|
|
18
|
+
db = (0, schema_1.openDatabase)(rootDir);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
process.stderr.write(`[codex-mcp] Failed to open database: ${err}\n`);
|
|
22
|
+
process.stderr.write(`[codex-mcp] Run 'claude-ex init' first.\n`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
// Start file watcher inside MCP server process
|
|
26
|
+
let watcher;
|
|
27
|
+
try {
|
|
28
|
+
watcher = await (0, daemon_1.startWatcher)(rootDir, db, (file) => {
|
|
29
|
+
process.stderr.write(`[codex-mcp] reindexed: ${file}\n`);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
process.stderr.write(`[codex-mcp] Watcher failed to start: ${err}\n`);
|
|
34
|
+
}
|
|
35
|
+
const server = new index_js_1.Server({ name: 'claude-ex', version: '1.0.0' }, { capabilities: { tools: {} } });
|
|
36
|
+
// Register tools
|
|
37
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
38
|
+
tools: [
|
|
39
|
+
{
|
|
40
|
+
name: 'search_code',
|
|
41
|
+
description: 'Search codebase for symbols by name, description, or content. Results ranked by structural importance (PageRank). Faster and more precise than grep for finding the right code.',
|
|
42
|
+
inputSchema: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
query: { type: 'string', description: 'Search query (natural language or symbol name)' },
|
|
46
|
+
limit: { type: 'number', description: 'Max results (default 15)' },
|
|
47
|
+
},
|
|
48
|
+
required: ['query'],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'get_symbol',
|
|
53
|
+
description: 'Get complete context for a symbol: its code, what it depends on, what depends on it, co-located symbols. Use before modifying any symbol.',
|
|
54
|
+
inputSchema: {
|
|
55
|
+
type: 'object',
|
|
56
|
+
properties: {
|
|
57
|
+
name: { type: 'string', description: 'Symbol name or qualified name (e.g., processPayment or PaymentService.processPayment)' },
|
|
58
|
+
},
|
|
59
|
+
required: ['name'],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'get_callers',
|
|
64
|
+
description: 'Find all callers of a function or method. Use before renaming, changing signatures, or removing functions.',
|
|
65
|
+
inputSchema: {
|
|
66
|
+
type: 'object',
|
|
67
|
+
properties: {
|
|
68
|
+
name: { type: 'string', description: 'Function or method name' },
|
|
69
|
+
},
|
|
70
|
+
required: ['name'],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'get_dependents',
|
|
75
|
+
description: 'Find all files transitively affected if a file changes. Use before refactors that change exports or file structure.',
|
|
76
|
+
inputSchema: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
file: { type: 'string', description: 'File path relative to project root' },
|
|
80
|
+
maxDepth: { type: 'number', description: 'Max traversal depth (default 10)' },
|
|
81
|
+
},
|
|
82
|
+
required: ['file'],
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'get_dependencies',
|
|
87
|
+
description: 'Find what a symbol depends on (imports, inherited classes, referenced types).',
|
|
88
|
+
inputSchema: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
name: { type: 'string', description: 'Symbol name' },
|
|
92
|
+
},
|
|
93
|
+
required: ['name'],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'get_architecture',
|
|
98
|
+
description: 'Get project architecture overview: top symbols by importance, module dependency map, language breakdown.',
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
top: { type: 'number', description: 'Number of top symbols to include (default 20)' },
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'reindex_file',
|
|
108
|
+
description: 'Re-index a single file immediately.',
|
|
109
|
+
inputSchema: {
|
|
110
|
+
type: 'object',
|
|
111
|
+
properties: {
|
|
112
|
+
file: { type: 'string', description: 'File path relative to project root' },
|
|
113
|
+
},
|
|
114
|
+
required: ['file'],
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
}));
|
|
119
|
+
// Handle tool calls
|
|
120
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
121
|
+
const { name, arguments: args } = request.params;
|
|
122
|
+
const callStart = performance.now();
|
|
123
|
+
try {
|
|
124
|
+
let result;
|
|
125
|
+
switch (name) {
|
|
126
|
+
case 'search_code':
|
|
127
|
+
result = (0, engine_1.search)(db, args.query, args.limit);
|
|
128
|
+
break;
|
|
129
|
+
case 'get_symbol':
|
|
130
|
+
result = (0, engine_1.getContext)(db, args.name);
|
|
131
|
+
if (!result) {
|
|
132
|
+
return { content: [{ type: 'text', text: `Symbol '${args.name}' not found in index.` }] };
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
case 'get_callers':
|
|
136
|
+
result = (0, engine_1.getCallers)(db, args.name);
|
|
137
|
+
break;
|
|
138
|
+
case 'get_dependents':
|
|
139
|
+
result = (0, engine_1.getImpact)(db, args.file, args.maxDepth);
|
|
140
|
+
break;
|
|
141
|
+
case 'get_dependencies':
|
|
142
|
+
result = (0, engine_1.getDeps)(db, args.name);
|
|
143
|
+
break;
|
|
144
|
+
case 'get_architecture':
|
|
145
|
+
result = {
|
|
146
|
+
stats: (0, engine_1.getStats)(db),
|
|
147
|
+
topSymbols: (0, engine_1.getRank)(db, args?.top || 20),
|
|
148
|
+
modules: (0, engine_1.getModules)(db),
|
|
149
|
+
};
|
|
150
|
+
break;
|
|
151
|
+
case 'reindex_file': {
|
|
152
|
+
const fileStart = performance.now();
|
|
153
|
+
(0, indexer_1.reindexFile)(rootDir, args.file, db);
|
|
154
|
+
result = { success: true, timeMs: +(performance.now() - fileStart).toFixed(1) };
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
default:
|
|
158
|
+
return {
|
|
159
|
+
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
160
|
+
isError: true,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const elapsed = (performance.now() - callStart).toFixed(1);
|
|
164
|
+
process.stderr.write(`[codex-mcp] ${name} completed in ${elapsed}ms\n`);
|
|
165
|
+
return {
|
|
166
|
+
content: [{
|
|
167
|
+
type: 'text',
|
|
168
|
+
text: JSON.stringify(result, null, 2),
|
|
169
|
+
}],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
return {
|
|
174
|
+
content: [{ type: 'text', text: `Error: ${err.message}` }],
|
|
175
|
+
isError: true,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
const elapsed = (performance.now() - startTime).toFixed(0);
|
|
180
|
+
process.stderr.write(`[codex-mcp] Server started in ${elapsed}ms (root: ${rootDir})\n`);
|
|
181
|
+
// Connect stdio transport
|
|
182
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
183
|
+
await server.connect(transport);
|
|
184
|
+
// Graceful shutdown
|
|
185
|
+
const shutdown = () => {
|
|
186
|
+
process.stderr.write('[codex-mcp] Shutting down...\n');
|
|
187
|
+
if (watcher)
|
|
188
|
+
watcher.close();
|
|
189
|
+
db.close();
|
|
190
|
+
process.exit(0);
|
|
191
|
+
};
|
|
192
|
+
process.on('SIGINT', shutdown);
|
|
193
|
+
process.on('SIGTERM', shutdown);
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/claude/mcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
export declare function openDatabase(projectRoot: string): Database.Database;
|
|
3
|
+
export interface FileRecord {
|
|
4
|
+
id: number;
|
|
5
|
+
changed: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function getOrCreateFile(db: Database.Database, filePath: string, hash: string, language: string | null, lineCount: number): FileRecord;
|
|
8
|
+
export declare function clearFileData(db: Database.Database, fileId: number): void;
|
|
9
|
+
export interface SymbolData {
|
|
10
|
+
name: string;
|
|
11
|
+
qualifiedName?: string;
|
|
12
|
+
kind: string;
|
|
13
|
+
lineStart: number;
|
|
14
|
+
lineEnd: number;
|
|
15
|
+
signature?: string;
|
|
16
|
+
docstring?: string;
|
|
17
|
+
content?: string;
|
|
18
|
+
contentHash?: string;
|
|
19
|
+
exported?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function insertSymbol(db: Database.Database, fileId: number, sym: SymbolData): number;
|
|
22
|
+
export declare function insertEdge(db: Database.Database, fromId: number, toId: number, kind: string): void;
|
|
23
|
+
export declare function insertFileDep(db: Database.Database, fromFile: number, toFile: number, kind: string, importName: string): void;
|
|
24
|
+
export declare function removeStaleFiles(db: Database.Database, validPaths: Set<string>): number;
|
|
25
|
+
export declare function removeFile(db: Database.Database, filePath: string): void;
|