kodelyth-ecc 2.1.2 → 2.2.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/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.2
1
+ 2.2.0
@@ -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.2",
3
+ "version": "2.2.0",
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">RTK Savings</button>
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(); }