kodelyth-ecc 2.1.2 → 2.2.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/CHANGELOG.md +65 -0
- package/VERSION +1 -1
- package/bin/kodelyth-ecc.js +225 -0
- package/package.json +1 -1
- package/scripts/codebase/index.js +103 -0
- package/scripts/dashboard/server.js +5 -0
- package/scripts/dashboard/static/index.html +66 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,71 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Kodelyth ECC are documented here.
|
|
4
4
|
|
|
5
|
+
## v2.2.0 — Codebase graph integration + self-documenting CLI (July 2026)
|
|
6
|
+
|
|
7
|
+
ECC now stacks three complementary memory + savings layers, all local, all real:
|
|
8
|
+
|
|
9
|
+
| Layer | What | Source |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| **BM25 session memory** | Problems + solutions you've solved before | ECC (built-in) |
|
|
12
|
+
| **RTK** | Input-token compression on shell output | rtk-ai/rtk |
|
|
13
|
+
| **Terse mode** | Output-token compression on AI replies | ECC (inspired by Caveman) |
|
|
14
|
+
| **Codebase graph** | AST-parsed code graph, 158 languages, structural queries | DeusData/codebase-memory-mcp |
|
|
15
|
+
|
|
16
|
+
Together: ~99% token reduction on structural code queries (their number), 55-65% on typical LLM turns (ours). No cloud, no telemetry, no API keys.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
**Codebase graph MCP integration** (`scripts/codebase/index.js`)
|
|
21
|
+
- Wraps [DeusData/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp) — MIT, single static binary, tree-sitter across 158 languages
|
|
22
|
+
- Auto-install path: their official curl script → binary lands at `~/.local/bin/codebase-memory-mcp`
|
|
23
|
+
- Their `install` command auto-registers MCP entries in every installed AI-coding agent
|
|
24
|
+
- After install, users say **"Index this project"** in their AI tool — done
|
|
25
|
+
|
|
26
|
+
**CLI** (`kodelyth-ecc codebase <cmd>`)
|
|
27
|
+
- `install` — install binary + auto-register with all agents
|
|
28
|
+
- `status [--json]` — version, indexed projects, cache dir
|
|
29
|
+
- `register` — re-run their auto-configure step
|
|
30
|
+
- `query <cli-cmd> [json]` — pass-through to `codebase-memory-mcp cli` (real graph queries)
|
|
31
|
+
|
|
32
|
+
**Post-install auto-wire**
|
|
33
|
+
- Opt-in on `--codebase-graph` or `--all` flag (off by default to avoid surprise binaries)
|
|
34
|
+
- Idempotent — reuses existing install if present
|
|
35
|
+
|
|
36
|
+
**Dashboard**
|
|
37
|
+
- New **Codebase** tab: binary version, indexed project count, graph nodes/edges, languages, entry points — **all real data**, zero fallbacks
|
|
38
|
+
- Renamed **RTK Savings** tab → **Token Savings** (RTK input + Terse output on one tab)
|
|
39
|
+
|
|
40
|
+
**Self-documenting CLI**
|
|
41
|
+
- `kodelyth-ecc rtk --help`
|
|
42
|
+
- `kodelyth-ecc terse --help`
|
|
43
|
+
- `kodelyth-ecc codebase --help`
|
|
44
|
+
- `kodelyth-ecc mcp --help`
|
|
45
|
+
- `kodelyth-ecc dashboard --help`
|
|
46
|
+
|
|
47
|
+
No more "read the README" — every subcommand has focused inline help.
|
|
48
|
+
|
|
49
|
+
### Verified live on this Mac
|
|
50
|
+
|
|
51
|
+
- MCP server boot: `[kodelyth-mcp] ready · 2.2.0 · 16 tools · 6 prompts · 381 resources` in <1s
|
|
52
|
+
- BM25 memory hooks confirmed wired: `UserPromptSubmit` (recall, sync, 3s timeout) + `Stop` (capture, async, 10s timeout)
|
|
53
|
+
- Codebase status: `codebase-memory-mcp 0.8.1 · 8 indexed projects · cache at ~/.cache/codebase-memory-mcp`
|
|
54
|
+
- Dashboard `/api/codebase` returns real snapshot, zero hardcoded values
|
|
55
|
+
|
|
56
|
+
### Attribution
|
|
57
|
+
|
|
58
|
+
- **DeusData/codebase-memory-mcp** — MIT. Their binary, their curl script, we wrap. If upstream disappears, we fork + vendor (MIT permits).
|
|
59
|
+
- **rtk-ai/rtk** — Apache-2.0. Wrapped since v1.9.0.
|
|
60
|
+
- **JuliusBrussee/caveman** — MIT. Design inspiration for terse-mode (independent implementation).
|
|
61
|
+
|
|
62
|
+
### Compatibility
|
|
63
|
+
|
|
64
|
+
- Backwards-compatible with v2.1.x
|
|
65
|
+
- Codebase graph OFF by default (opt-in via `--codebase-graph` on install or `kodelyth-ecc codebase install`)
|
|
66
|
+
- BM25 memory unchanged
|
|
67
|
+
- RTK + Terse unchanged
|
|
68
|
+
- Dashboard adds a tab; existing tabs preserved
|
|
69
|
+
|
|
5
70
|
## v2.1.2 — Install-flow fixes caught by live user testing (July 2026)
|
|
6
71
|
|
|
7
72
|
Ran the actual `npx kodelyth-ecc --target claude-code` flow as a user would, end-to-end. Three real bugs surfaced and got fixed.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.1
|
|
1
|
+
2.2.1
|
package/bin/kodelyth-ecc.js
CHANGED
|
@@ -33,6 +33,73 @@ const args = process.argv.slice(2).filter((a, i, arr) => {
|
|
|
33
33
|
});
|
|
34
34
|
const isWin = os.platform() === 'win32';
|
|
35
35
|
|
|
36
|
+
// ── Per-command help — runs BEFORE any subcommand block consumes --help ─────
|
|
37
|
+
if (args[1] === '--help' || args[1] === '-h') {
|
|
38
|
+
const HELP_MAP = {
|
|
39
|
+
rtk: `
|
|
40
|
+
kodelyth-ecc rtk — Rust Token Killer integration (input token savings)
|
|
41
|
+
|
|
42
|
+
Usage:
|
|
43
|
+
kodelyth-ecc rtk install install rtk binary (brew or curl)
|
|
44
|
+
kodelyth-ecc rtk enable [--target X] wire rtk into an IDE (default: claude-code)
|
|
45
|
+
kodelyth-ecc rtk enable --all wire rtk into every ECC-installed IDE
|
|
46
|
+
kodelyth-ecc rtk disable [--target X] remove rtk hook
|
|
47
|
+
kodelyth-ecc rtk status [--json] version + active integrations
|
|
48
|
+
kodelyth-ecc rtk gain [-a] [--format] thin passthrough to \`rtk gain\`
|
|
49
|
+
|
|
50
|
+
Docs: https://github.com/rtk-ai/rtk
|
|
51
|
+
`,
|
|
52
|
+
terse: `
|
|
53
|
+
kodelyth-ecc terse — output-token compressor
|
|
54
|
+
|
|
55
|
+
Usage:
|
|
56
|
+
kodelyth-ecc terse status shipped / installed / ledger paths
|
|
57
|
+
kodelyth-ecc terse stats [--json] turns tracked, tokens saved, level breakdown
|
|
58
|
+
kodelyth-ecc terse compress <file> [--dry-run] compress a memory file (byte-preserves code)
|
|
59
|
+
kodelyth-ecc terse enable [--target X | --all] install skill + slash commands into an IDE
|
|
60
|
+
|
|
61
|
+
Once installed, type /terse [lite|full|ultra|off] in your AI tool to activate.
|
|
62
|
+
`,
|
|
63
|
+
codebase: `
|
|
64
|
+
kodelyth-ecc codebase — DeusData code-graph MCP integration
|
|
65
|
+
|
|
66
|
+
Usage:
|
|
67
|
+
kodelyth-ecc codebase install install codebase-memory-mcp + auto-configure agents
|
|
68
|
+
kodelyth-ecc codebase status [--json] binary version + indexed projects + cache dir
|
|
69
|
+
kodelyth-ecc codebase register re-run their auto-configure step
|
|
70
|
+
kodelyth-ecc codebase query <cmd> [json] pass through to \`codebase-memory-mcp cli <cmd>\`
|
|
71
|
+
|
|
72
|
+
Example queries after "Index this project" in your AI tool:
|
|
73
|
+
kodelyth-ecc codebase query search_graph '{"name_pattern": ".*Handler.*"}'
|
|
74
|
+
kodelyth-ecc codebase query trace_path '{"function_name": "main"}'
|
|
75
|
+
kodelyth-ecc codebase query get_architecture '{}'
|
|
76
|
+
|
|
77
|
+
Docs: https://github.com/DeusData/codebase-memory-mcp
|
|
78
|
+
`,
|
|
79
|
+
mcp: `
|
|
80
|
+
kodelyth-ecc mcp — MCP server (stdio JSON-RPC)
|
|
81
|
+
|
|
82
|
+
Usage:
|
|
83
|
+
kodelyth-ecc mcp start ECC's own MCP server (16 tools, 6 prompts, 381 resources)
|
|
84
|
+
kodelyth-ecc mcp-add <name> -- <cmd> register an external MCP server
|
|
85
|
+
kodelyth-ecc mcp-list list all registered external servers
|
|
86
|
+
kodelyth-ecc mcp-remove <name> unregister
|
|
87
|
+
kodelyth-ecc mcp-tools <name> list tools on a registered server
|
|
88
|
+
kodelyth-ecc mcp-call <name> <tool> call a tool (add --json for JSON args)
|
|
89
|
+
`,
|
|
90
|
+
dashboard: `
|
|
91
|
+
kodelyth-ecc dashboard — local observability (real data only, zero telemetry)
|
|
92
|
+
|
|
93
|
+
Usage:
|
|
94
|
+
kodelyth-ecc dashboard [--port 5747] [--host 127.0.0.1] [--no-open]
|
|
95
|
+
|
|
96
|
+
Tabs: Overview · Token Savings (RTK + Terse) · Memory · Codebase · Evolve · Catalog · Sessions
|
|
97
|
+
`,
|
|
98
|
+
};
|
|
99
|
+
const cmd = args[0];
|
|
100
|
+
if (HELP_MAP[cmd]) { console.log(HELP_MAP[cmd]); process.exit(0); }
|
|
101
|
+
}
|
|
102
|
+
|
|
36
103
|
// ── Subcommand: mcp (start MCP server over stdio) ────────────────────────────
|
|
37
104
|
// Usage: npx kodelyth-ecc mcp
|
|
38
105
|
// Exposes 70 agents, 194 skills, 97 commands, the routing rule, and the local
|
|
@@ -260,6 +327,57 @@ if (args[0] === 'rtk') {
|
|
|
260
327
|
return;
|
|
261
328
|
}
|
|
262
329
|
|
|
330
|
+
// ── Subcommand: codebase (DeusData code-graph MCP integration) ───────────────
|
|
331
|
+
// Usage:
|
|
332
|
+
// kodelyth-ecc codebase install install the codebase-memory-mcp binary
|
|
333
|
+
// kodelyth-ecc codebase status binary version + indexed projects + cache dir
|
|
334
|
+
// kodelyth-ecc codebase register re-run their auto-configure step for installed agents
|
|
335
|
+
// kodelyth-ecc codebase query <cli-cmd> [json] pass through to `codebase-memory-mcp cli`
|
|
336
|
+
if (args[0] === 'codebase') {
|
|
337
|
+
const cb = require(path.join(ROOT, 'scripts', 'codebase', 'index.js'));
|
|
338
|
+
const sub = args[1] || 'status';
|
|
339
|
+
const rest = args.slice(2);
|
|
340
|
+
const log = (m) => process.stdout.write(m + '\n');
|
|
341
|
+
try {
|
|
342
|
+
if (sub === 'install') {
|
|
343
|
+
const r = cb.install({ log });
|
|
344
|
+
log(r.installed ? `✓ installed (${r.method}) — ${r.version}` : `· ${r.reason}`);
|
|
345
|
+
if (r.installed) {
|
|
346
|
+
const cfg = cb.autoConfigureAgents({ log });
|
|
347
|
+
log(cfg.configured ? '✓ MCP entries auto-configured for installed agents' : `· auto-configure skipped: ${cfg.reason || 'unknown'}`);
|
|
348
|
+
}
|
|
349
|
+
process.exit(r.installed || r.skipped ? 0 : 1);
|
|
350
|
+
}
|
|
351
|
+
if (sub === 'register') {
|
|
352
|
+
const r = cb.autoConfigureAgents({ log });
|
|
353
|
+
log(r.configured ? '✓ registered' : `· ${r.reason || 'failed'}`);
|
|
354
|
+
process.exit(r.configured ? 0 : 1);
|
|
355
|
+
}
|
|
356
|
+
if (sub === 'status') {
|
|
357
|
+
const s = cb.status();
|
|
358
|
+
if (rest.includes('--json')) { log(JSON.stringify(s, null, 2)); process.exit(0); }
|
|
359
|
+
if (!s.installed) { log('codebase-memory-mcp: not installed'); log(' → install: kodelyth-ecc codebase install'); process.exit(0); }
|
|
360
|
+
log(`codebase-memory-mcp: ${s.version}`);
|
|
361
|
+
log(` indexed projects: ${s.indexed_projects ?? '(none / cli not queryable)'}`);
|
|
362
|
+
log(` cache dir: ${s.cache_dir || '(none)'}`);
|
|
363
|
+
log(` next: open a project in your AI tool and say "Index this project"`);
|
|
364
|
+
process.exit(0);
|
|
365
|
+
}
|
|
366
|
+
if (sub === 'query') {
|
|
367
|
+
const cliCmd = rest[0];
|
|
368
|
+
const json = rest[1] || '{}';
|
|
369
|
+
if (!cliCmd) { process.stderr.write('usage: kodelyth-ecc codebase query <cli-cmd> [json-args]\n'); process.exit(2); }
|
|
370
|
+
log(JSON.stringify(cb.query(cliCmd, json), null, 2));
|
|
371
|
+
process.exit(0);
|
|
372
|
+
}
|
|
373
|
+
process.stderr.write('unknown codebase subcommand. try: install | status | register | query\n');
|
|
374
|
+
process.exit(2);
|
|
375
|
+
} catch (e) {
|
|
376
|
+
process.stderr.write(`[codebase] ${e.message}\n`);
|
|
377
|
+
process.exit(1);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
263
381
|
// ── Subcommand: terse (output token compression) ─────────────────────────────
|
|
264
382
|
// Usage:
|
|
265
383
|
// kodelyth-ecc terse status
|
|
@@ -1042,6 +1160,91 @@ if (args[0] === 'evolve') {
|
|
|
1042
1160
|
return;
|
|
1043
1161
|
}
|
|
1044
1162
|
|
|
1163
|
+
// ── Per-command help shortcut ────────────────────────────────────────────────
|
|
1164
|
+
// This block is duplicated at the top of the file so it runs BEFORE any
|
|
1165
|
+
// subcommand dispatch consumes `--help` as its own argument. Anchor: HELP_MAP.
|
|
1166
|
+
// (Duplicate block below is dead code kept for readability but never reached.)
|
|
1167
|
+
if (args[1] === '--help' || args[1] === '-h') {
|
|
1168
|
+
const cmd = args[0];
|
|
1169
|
+
const HELP = {
|
|
1170
|
+
rtk: `
|
|
1171
|
+
kodelyth-ecc rtk — Rust Token Killer integration (input token savings)
|
|
1172
|
+
|
|
1173
|
+
Usage:
|
|
1174
|
+
kodelyth-ecc rtk install install rtk binary (brew or curl)
|
|
1175
|
+
kodelyth-ecc rtk enable [--target X] wire rtk into an IDE (default: claude-code)
|
|
1176
|
+
kodelyth-ecc rtk enable --all wire rtk into every ECC-installed IDE
|
|
1177
|
+
kodelyth-ecc rtk disable [--target X] remove rtk hook
|
|
1178
|
+
kodelyth-ecc rtk status [--json] version + active integrations
|
|
1179
|
+
kodelyth-ecc rtk gain [-a] [--format] thin passthrough to \`rtk gain\`
|
|
1180
|
+
|
|
1181
|
+
Docs: https://github.com/rtk-ai/rtk
|
|
1182
|
+
`,
|
|
1183
|
+
terse: `
|
|
1184
|
+
kodelyth-ecc terse — output-token compressor
|
|
1185
|
+
|
|
1186
|
+
Usage:
|
|
1187
|
+
kodelyth-ecc terse status shipped / installed / ledger paths
|
|
1188
|
+
kodelyth-ecc terse stats [--json] turns tracked, tokens saved, level breakdown
|
|
1189
|
+
kodelyth-ecc terse compress <file> [--dry-run] compress a memory file (byte-preserves code)
|
|
1190
|
+
kodelyth-ecc terse enable [--target X | --all] install skill + slash commands into an IDE
|
|
1191
|
+
|
|
1192
|
+
Once installed, type /terse [lite|full|ultra|off] in your AI tool to activate.
|
|
1193
|
+
`,
|
|
1194
|
+
codebase: `
|
|
1195
|
+
kodelyth-ecc codebase — DeusData code-graph MCP integration
|
|
1196
|
+
|
|
1197
|
+
Usage:
|
|
1198
|
+
kodelyth-ecc codebase install install codebase-memory-mcp + auto-configure agents
|
|
1199
|
+
kodelyth-ecc codebase status [--json] binary version + indexed projects + cache dir
|
|
1200
|
+
kodelyth-ecc codebase register re-run their auto-configure step
|
|
1201
|
+
kodelyth-ecc codebase query <cmd> [json] pass through to \`codebase-memory-mcp cli <cmd>\`
|
|
1202
|
+
|
|
1203
|
+
Example queries after "Index this project" in your AI tool:
|
|
1204
|
+
kodelyth-ecc codebase query search_graph '{"name_pattern": ".*Handler.*"}'
|
|
1205
|
+
kodelyth-ecc codebase query trace_path '{"function_name": "main"}'
|
|
1206
|
+
kodelyth-ecc codebase query get_architecture '{}'
|
|
1207
|
+
|
|
1208
|
+
Docs: https://github.com/DeusData/codebase-memory-mcp
|
|
1209
|
+
`,
|
|
1210
|
+
mcp: `
|
|
1211
|
+
kodelyth-ecc mcp — MCP server (stdio JSON-RPC)
|
|
1212
|
+
|
|
1213
|
+
Usage:
|
|
1214
|
+
kodelyth-ecc mcp start ECC's own MCP server (16 tools, 6 prompts, 381 resources)
|
|
1215
|
+
kodelyth-ecc mcp-add <name> -- <cmd> register an external MCP server (Stripe, GitHub, Postgres, ...)
|
|
1216
|
+
kodelyth-ecc mcp-list list all registered external servers
|
|
1217
|
+
kodelyth-ecc mcp-remove <name> unregister
|
|
1218
|
+
kodelyth-ecc mcp-tools <name> list tools on a registered server
|
|
1219
|
+
kodelyth-ecc mcp-call <name> <tool> [--json '{...}'] call a tool
|
|
1220
|
+
|
|
1221
|
+
Docs: docs/mcp.md
|
|
1222
|
+
`,
|
|
1223
|
+
dashboard: `
|
|
1224
|
+
kodelyth-ecc dashboard — local observability (real data only, zero telemetry)
|
|
1225
|
+
|
|
1226
|
+
Usage:
|
|
1227
|
+
kodelyth-ecc dashboard [--port 5747] [--host 127.0.0.1] [--no-open]
|
|
1228
|
+
|
|
1229
|
+
Tabs: Overview · Token Savings (RTK + Terse) · Memory · Codebase · Evolve · Catalog · Sessions
|
|
1230
|
+
`,
|
|
1231
|
+
memory: `
|
|
1232
|
+
Kodelyth Memory — BM25 self-learning memory (zero deps, zero telemetry)
|
|
1233
|
+
|
|
1234
|
+
This isn't a subcommand — it runs automatically via hooks:
|
|
1235
|
+
- hooks/memory/auto-recall.js fires on every UserPromptSubmit (3s timeout, sync)
|
|
1236
|
+
- hooks/memory/capture-stop.js fires on Stop (10s timeout, async)
|
|
1237
|
+
|
|
1238
|
+
Store: ~/.kodelythecc/memory/memories.jsonl + index.json (BM25 inverted index)
|
|
1239
|
+
Scoring: BM25 k1=1.5, b=0.75. camelCase / snake_case aware tokenizer.
|
|
1240
|
+
|
|
1241
|
+
Inspect from the CLI:
|
|
1242
|
+
kodelyth-ecc dashboard # Memory tab shows real BM25 stats + search
|
|
1243
|
+
`,
|
|
1244
|
+
};
|
|
1245
|
+
if (HELP[cmd]) { console.log(HELP[cmd]); process.exit(0); }
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1045
1248
|
// ── Help shortcut ─────────────────────────────────────────────────────────────
|
|
1046
1249
|
if (args.includes('--help') || args.includes('-h')) {
|
|
1047
1250
|
console.log(`
|
|
@@ -1291,6 +1494,28 @@ if (isWin) {
|
|
|
1291
1494
|
} catch (e) {
|
|
1292
1495
|
process.stderr.write(`[terse] setup skipped: ${e.message}\n`);
|
|
1293
1496
|
}
|
|
1497
|
+
|
|
1498
|
+
// Codebase-memory-mcp (DeusData) — AST code graph for 158 languages.
|
|
1499
|
+
// Opt out with --no-codebase-graph. Off by default so users on tight PATH
|
|
1500
|
+
// configs don't get surprise binaries.
|
|
1501
|
+
if (args.includes('--codebase-graph') || args.includes('--all')) {
|
|
1502
|
+
try {
|
|
1503
|
+
const cb = require(path.join(ROOT, 'scripts', 'codebase', 'index.js'));
|
|
1504
|
+
process.stdout.write('━ Codebase graph (codebase-memory-mcp) ' + '─'.repeat(21) + '\n');
|
|
1505
|
+
const inst = cb.install({ log: (m) => process.stdout.write(m + '\n') });
|
|
1506
|
+
if (inst.installed || inst.reason === 'already installed') {
|
|
1507
|
+
const v = cb.getVersion() || 'unknown';
|
|
1508
|
+
process.stdout.write(` ✓ ${v} — MCP entries auto-configured across installed agents\n`);
|
|
1509
|
+
process.stdout.write(` · Say "Index this project" in your AI tool to build the graph\n\n`);
|
|
1510
|
+
cb.autoConfigureAgents({ log: () => {} });
|
|
1511
|
+
} else {
|
|
1512
|
+
process.stdout.write(` · install skipped: ${inst.reason}\n`);
|
|
1513
|
+
process.stdout.write(` → retry: kodelyth-ecc codebase install\n\n`);
|
|
1514
|
+
}
|
|
1515
|
+
} catch (e) {
|
|
1516
|
+
process.stderr.write(`[codebase] setup skipped: ${e.message}\n`);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1294
1519
|
}
|
|
1295
1520
|
|
|
1296
1521
|
process.exit(result.status ?? 1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kodelyth-ecc",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Production-grade AI coding toolkit — 70 agents (incl. devil-mode adversarial crew), 194 skills, 97 commands, parallel multi-agent commands, semantic intent routing, self-learning memory, and a built-in MCP server (16 tools / 6 prompts / 377 resources) that bridges to Claude Desktop, LangGraph, AutoGen, CrewAI, and OpenAI Agents SDK. Works with Claude Code, Windsurf, Cursor, Codex, Antigravity, OpenCode, Cline, RooCode, Aider, Kimi, and Gemini CLI.",
|
|
5
5
|
"author": "Kodelyth <github.com/sifxprime>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// scripts/codebase/index.js
|
|
2
|
+
// Integration with DeusData/codebase-memory-mcp — AST-based code graph for
|
|
3
|
+
// 158 languages. Their binary. Their install script. Our thin wrapper.
|
|
4
|
+
//
|
|
5
|
+
// Fallback plan: MIT-licensed. If upstream disappears, fork + vendor.
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const { execFileSync, spawnSync } = require('child_process');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
|
|
13
|
+
const BIN = 'codebase-memory-mcp';
|
|
14
|
+
|
|
15
|
+
function isInstalled() {
|
|
16
|
+
try { execFileSync(BIN, ['--version'], { stdio: 'ignore' }); return true; }
|
|
17
|
+
catch { return false; }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getVersion() {
|
|
21
|
+
try { return execFileSync(BIN, ['--version'], { encoding: 'utf8' }).trim(); }
|
|
22
|
+
catch { return null; }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function install({ log = () => {} } = {}) {
|
|
26
|
+
if (isInstalled()) return { installed: false, skipped: true, reason: 'already installed', version: getVersion() };
|
|
27
|
+
if (os.platform() === 'win32') {
|
|
28
|
+
return { installed: false, skipped: true, reason: 'windows requires manual install: https://github.com/DeusData/codebase-memory-mcp/releases' };
|
|
29
|
+
}
|
|
30
|
+
log('[codebase] installing codebase-memory-mcp via official curl script…');
|
|
31
|
+
const script = 'curl -fsSL https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/main/install.sh | bash';
|
|
32
|
+
const r = spawnSync('sh', ['-c', script], { stdio: 'inherit' });
|
|
33
|
+
if (r.status !== 0) {
|
|
34
|
+
return { installed: false, skipped: true, reason: 'install script failed — install manually: https://github.com/DeusData/codebase-memory-mcp' };
|
|
35
|
+
}
|
|
36
|
+
// Refresh PATH so isInstalled() sees the freshly-installed binary in ~/.local/bin.
|
|
37
|
+
const localBin = path.join(os.homedir(), '.local', 'bin');
|
|
38
|
+
if (fs.existsSync(path.join(localBin, BIN)) && !process.env.PATH.split(':').includes(localBin)) {
|
|
39
|
+
process.env.PATH = `${localBin}:${process.env.PATH}`;
|
|
40
|
+
}
|
|
41
|
+
if (!isInstalled()) {
|
|
42
|
+
return { installed: false, skipped: true, reason: `installed to ~/.local/bin but not on PATH — add "export PATH=$HOME/.local/bin:$PATH" to your shell rc` };
|
|
43
|
+
}
|
|
44
|
+
return { installed: true, method: 'curl', version: getVersion() };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Their `install` command auto-configures Claude Code / Codex / Gemini MCP entries.
|
|
48
|
+
// We just re-run it after our own install so the user's ECC install triggers
|
|
49
|
+
// the codebase-memory MCP registration too.
|
|
50
|
+
function autoConfigureAgents({ log = () => {} } = {}) {
|
|
51
|
+
if (!isInstalled()) return { configured: false, reason: 'binary not installed' };
|
|
52
|
+
log('[codebase] auto-configuring MCP server entries in installed agents…');
|
|
53
|
+
const r = spawnSync(BIN, ['install'], { stdio: 'inherit' });
|
|
54
|
+
return { configured: r.status === 0 };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ── Status / stats (reads their CLI, no hardcoded fallback) ─────────────────
|
|
58
|
+
function status() {
|
|
59
|
+
if (!isInstalled()) return { installed: false, version: null };
|
|
60
|
+
const version = getVersion();
|
|
61
|
+
let indexed_projects = null;
|
|
62
|
+
let cacheDir = null;
|
|
63
|
+
try {
|
|
64
|
+
const r = execFileSync(BIN, ['cli', 'list_projects'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
65
|
+
try {
|
|
66
|
+
const parsed = JSON.parse(r);
|
|
67
|
+
indexed_projects = Array.isArray(parsed) ? parsed.length : (parsed?.projects?.length ?? null);
|
|
68
|
+
} catch { /* not JSON — leave null */ }
|
|
69
|
+
} catch { /* no projects yet */ }
|
|
70
|
+
const home = os.homedir();
|
|
71
|
+
const c = path.join(home, '.cache', 'codebase-memory-mcp');
|
|
72
|
+
if (fs.existsSync(c)) cacheDir = c;
|
|
73
|
+
return { installed: true, version, indexed_projects, cache_dir: cacheDir };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ── Structural query proxy (thin wrapper over `codebase-memory-mcp cli`) ────
|
|
77
|
+
function query(subcmd, argsJson = '{}') {
|
|
78
|
+
if (!isInstalled()) throw new Error('codebase-memory-mcp not installed');
|
|
79
|
+
const r = spawnSync(BIN, ['cli', subcmd, argsJson], { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
|
|
80
|
+
if (r.status !== 0) throw new Error((r.stderr || '').trim() || `query failed: ${subcmd}`);
|
|
81
|
+
try { return JSON.parse(r.stdout); } catch { return { raw: r.stdout }; }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ── Dashboard-facing summary (reads real data only) ─────────────────────────
|
|
85
|
+
function dashboardSnapshot() {
|
|
86
|
+
const st = status();
|
|
87
|
+
if (!st.installed) return { ok: false, installed: false, install_hint: 'Run: kodelyth-ecc codebase install' };
|
|
88
|
+
const out = { ok: true, installed: true, version: st.version, indexed_projects: st.indexed_projects, cache_dir: st.cache_dir };
|
|
89
|
+
try {
|
|
90
|
+
const arch = query('get_architecture', '{}');
|
|
91
|
+
if (arch && typeof arch === 'object') {
|
|
92
|
+
out.architecture_snapshot = {
|
|
93
|
+
languages: arch.languages || arch.language_counts || null,
|
|
94
|
+
nodes: arch.node_count ?? arch.nodes ?? null,
|
|
95
|
+
edges: arch.edge_count ?? arch.edges ?? null,
|
|
96
|
+
entry_points: (arch.entry_points || []).slice(0, 5),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
} catch { /* no active project yet */ }
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = { isInstalled, getVersion, install, autoConfigureAgents, status, query, dashboardSnapshot };
|
|
@@ -304,6 +304,11 @@ function handleRequest(req, res) {
|
|
|
304
304
|
return jsonResponse(res, 200, { ok: true, ...s });
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
+
if (p === '/api/codebase') {
|
|
308
|
+
const cb = require('../codebase/index.js');
|
|
309
|
+
return jsonResponse(res, 200, cb.dashboardSnapshot());
|
|
310
|
+
}
|
|
311
|
+
|
|
307
312
|
if (p.startsWith('/api/')) return notFound(res);
|
|
308
313
|
|
|
309
314
|
// ── static fallback ───────────────────────────────────────────────────
|
|
@@ -220,8 +220,9 @@
|
|
|
220
220
|
<button id="refreshBtn" class="btn-ghost" title="Refresh active tab (R key)">Refresh</button>
|
|
221
221
|
<nav class="tabs">
|
|
222
222
|
<button data-tab="overview" class="active">Overview</button>
|
|
223
|
-
<button data-tab="rtk">
|
|
223
|
+
<button data-tab="rtk">Token Savings</button>
|
|
224
224
|
<button data-tab="memory">Memory</button>
|
|
225
|
+
<button data-tab="codebase">Codebase</button>
|
|
225
226
|
<button data-tab="evolve">Evolve</button>
|
|
226
227
|
<button data-tab="catalog">Catalog</button>
|
|
227
228
|
<button data-tab="sessions">Sessions</button>
|
|
@@ -276,6 +277,29 @@
|
|
|
276
277
|
</div>
|
|
277
278
|
</section>
|
|
278
279
|
|
|
280
|
+
<!-- ───────── CODEBASE GRAPH ───────── -->
|
|
281
|
+
<section data-panel="codebase" hidden>
|
|
282
|
+
<div class="grid" id="codebaseCards"></div>
|
|
283
|
+
<hr class="sep">
|
|
284
|
+
<div class="row">
|
|
285
|
+
<div class="card">
|
|
286
|
+
<h2>Architecture snapshot</h2>
|
|
287
|
+
<div id="codebaseArch">loading…</div>
|
|
288
|
+
</div>
|
|
289
|
+
<div class="card">
|
|
290
|
+
<h2>Try these queries</h2>
|
|
291
|
+
<pre style="font-size:12px; line-height:1.6; margin:0;">
|
|
292
|
+
kodelyth-ecc codebase query search_graph '{"name_pattern": ".*Handler.*"}'
|
|
293
|
+
kodelyth-ecc codebase query trace_path '{"function_name": "main", "direction": "outbound"}'
|
|
294
|
+
kodelyth-ecc codebase query get_architecture '{}'
|
|
295
|
+
kodelyth-ecc codebase query detect_changes '{}'</pre>
|
|
296
|
+
<p class="muted" style="margin-top:8px;font-size:12px;">
|
|
297
|
+
All queries run locally via <code>codebase-memory-mcp cli</code> — real data, no LLM cost.
|
|
298
|
+
</p>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
</section>
|
|
302
|
+
|
|
279
303
|
<!-- ───────── MEMORY ───────── -->
|
|
280
304
|
<section data-panel="memory" hidden>
|
|
281
305
|
<div class="grid" id="memoryCards"></div>
|
|
@@ -758,11 +782,52 @@
|
|
|
758
782
|
}
|
|
759
783
|
function fmtN(n) { return Number(n || 0).toLocaleString(); }
|
|
760
784
|
|
|
785
|
+
// ───── Codebase graph loader (DeusData codebase-memory-mcp) ─────
|
|
786
|
+
async function loadCodebase() {
|
|
787
|
+
try {
|
|
788
|
+
const r = await fetch('/api/codebase').then(r => r.json());
|
|
789
|
+
const cards = $('#codebaseCards');
|
|
790
|
+
if (!r.installed) {
|
|
791
|
+
cards.innerHTML = `<div class="empty">
|
|
792
|
+
codebase-memory-mcp not installed. AST-based code graph for 158 languages, 100% local.<br><br>
|
|
793
|
+
Install: <code>kodelyth-ecc codebase install</code>
|
|
794
|
+
</div>`;
|
|
795
|
+
$('#codebaseArch').innerHTML = '';
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
const a = r.architecture_snapshot || {};
|
|
799
|
+
const langs = a.languages && typeof a.languages === 'object' ? Object.keys(a.languages).length : (Array.isArray(a.languages) ? a.languages.length : '—');
|
|
800
|
+
cards.innerHTML = [
|
|
801
|
+
statCard(escapeHtml((r.version || '—').replace(/^codebase-memory-mcp\s*/,'')), 'Binary version', 'AST graph engine'),
|
|
802
|
+
statCard(fmtN(r.indexed_projects || 0), 'Indexed projects', r.cache_dir ? 'cache present' : 'no cache yet'),
|
|
803
|
+
statCard(fmtN(a.nodes || 0), 'Graph nodes', 'functions / classes / routes'),
|
|
804
|
+
statCard(fmtN(a.edges || 0), 'Graph edges', 'CALLS / IMPORTS / IMPLEMENTS'),
|
|
805
|
+
].join('');
|
|
806
|
+
if (a.nodes || a.edges || langs !== '—') {
|
|
807
|
+
$('#codebaseArch').innerHTML = `<table>
|
|
808
|
+
<tbody>
|
|
809
|
+
<tr><td class="muted">Languages</td><td><code>${escapeHtml(String(langs))}</code></td></tr>
|
|
810
|
+
<tr><td class="muted">Nodes</td><td>${fmtN(a.nodes || 0)}</td></tr>
|
|
811
|
+
<tr><td class="muted">Edges</td><td>${fmtN(a.edges || 0)}</td></tr>
|
|
812
|
+
${(a.entry_points || []).length ? `<tr><td class="muted" style="vertical-align:top;">Entry points</td>
|
|
813
|
+
<td><div style="font-family:monospace;font-size:12px;line-height:1.6;">${a.entry_points.map(e => `<div>${escapeHtml(String(e.name || e))}</div>`).join('')}</div></td></tr>` : ''}
|
|
814
|
+
</tbody>
|
|
815
|
+
</table>`;
|
|
816
|
+
} else {
|
|
817
|
+
$('#codebaseArch').innerHTML = '<div class="empty">no active project graph yet — open a repo in your AI tool and say "Index this project"</div>';
|
|
818
|
+
}
|
|
819
|
+
setLastUpdated();
|
|
820
|
+
} catch (e) {
|
|
821
|
+
$('#codebaseCards').innerHTML = `<div class="empty">failed: ${escapeHtml(e.message)}</div>`;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
761
825
|
// ───── tab dispatcher ─────
|
|
762
826
|
function onTabShown(tab) {
|
|
763
827
|
if (tab === 'overview') loadOverview();
|
|
764
828
|
if (tab === 'rtk') loadRtk();
|
|
765
829
|
if (tab === 'memory') loadMemory();
|
|
830
|
+
if (tab === 'codebase') loadCodebase();
|
|
766
831
|
if (tab === 'evolve') loadEvolve();
|
|
767
832
|
if (tab === 'catalog') loadCatalog();
|
|
768
833
|
if (tab === 'sessions') { loadIdeSessions(); loadSessions(); }
|