kodelyth-ecc 2.1.1 → 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 +96 -0
- package/VERSION +1 -1
- package/bin/kodelyth-ecc.js +248 -12
- package/install.sh +10 -6
- 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/scripts/rtk/index.js +22 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,102 @@
|
|
|
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
|
+
|
|
70
|
+
## v2.1.2 — Install-flow fixes caught by live user testing (July 2026)
|
|
71
|
+
|
|
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.
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- **`--target claude-code` was rejected** with "Unknown target." install.sh only knew `claude-home`, but every doc, README, and CHANGELOG example uses `claude-code`. install.sh now accepts both (`claude-home|claude-code)` case)
|
|
77
|
+
- **Post-install RTK block silently skipped** on the (correct) `--target claude-code` because `TARGET_MAP` was keyed on `claude-home`. Added `normalizeTarget()` and both the RTK and terse post-install blocks now normalise the target before lookup. `gemini-cli` → `gemini-home`, `cursor` → `cursor-project` also normalised
|
|
78
|
+
- **install.sh `/dev/tty` read failed on piped/CI shells** even though the guard tested `-e /dev/tty`. Guard now also tests `-r /dev/tty` and honours `KODELYTH_NONINTERACTIVE=1` env (Windows PowerShell path already set this)
|
|
79
|
+
- **install.sh footer showed stale `v1.8.1`** from a leftover VERSION file. Bumped to current
|
|
80
|
+
|
|
81
|
+
### Verified end-to-end on this Mac
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
$ npm i -g kodelyth-ecc && kodelyth-ecc --target claude-code
|
|
85
|
+
...
|
|
86
|
+
━ RTK token savings ─────────────────────────────
|
|
87
|
+
✓ RTK 0.42.4 — wired for claude-home
|
|
88
|
+
✓ Restart your AI tool to activate. 60-90% token savings on shell commands.
|
|
89
|
+
|
|
90
|
+
━ Terse mode ────────────────────────────────────
|
|
91
|
+
✓ /terse and /terse-compress installed for claude-home
|
|
92
|
+
· Activate any time: type /terse in your AI tool (dormant until you do)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Files land at `~/.claude/skills/terse-mode/SKILL.md` and `~/.claude/commands/terse.md`. Discoverable by the AI on next session.
|
|
96
|
+
|
|
97
|
+
### Added
|
|
98
|
+
|
|
99
|
+
- `scripts/rtk/index.js` — `normalizeTarget(target)` exported. Accepts `claude-code`, `gemini-cli`, `cursor` and returns the canonical install.sh target names. `roocode` and `kimi` also added to `TARGET_MAP`
|
|
100
|
+
|
|
5
101
|
## v2.0.0 — Terse mode: output-token compressor + memory compressor (July 2026)
|
|
6
102
|
|
|
7
103
|
RTK saves input tokens. Terse mode now saves output tokens. Together — on a typical coding session — ECC cuts ~55-65% of total token cost while keeping code, commands, and errors byte-exact.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
2.2.0
|
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
|
|
@@ -351,30 +469,39 @@ if (args[0] === 'terse') {
|
|
|
351
469
|
}
|
|
352
470
|
}
|
|
353
471
|
|
|
472
|
+
// Normalise alias → canonical target (matches scripts/rtk/index.js).
|
|
473
|
+
function _canon(target) {
|
|
474
|
+
if (target === 'claude-code') return 'claude-home';
|
|
475
|
+
if (target === 'gemini-cli') return 'gemini-home';
|
|
476
|
+
if (target === 'cursor') return 'cursor-project';
|
|
477
|
+
return target;
|
|
478
|
+
}
|
|
354
479
|
function getTargetSkillsDir(target) {
|
|
355
480
|
const home = os.homedir();
|
|
356
|
-
switch (target) {
|
|
357
|
-
case 'claude-
|
|
358
|
-
case 'cursor':
|
|
481
|
+
switch (_canon(target)) {
|
|
482
|
+
case 'claude-home': return path.join(home, '.claude', 'skills');
|
|
359
483
|
case 'cursor-project': return path.join(home, '.cursor', 'skills');
|
|
360
|
-
case 'windsurf-home':
|
|
484
|
+
case 'windsurf-home':
|
|
485
|
+
case 'windsurf-project': return path.join(home, '.codeium', 'windsurf', 'skills');
|
|
361
486
|
case 'antigravity': return path.join(home, '.antigravity', 'skills');
|
|
362
487
|
case 'codex-home': return path.join(home, '.codex', 'skills');
|
|
363
|
-
case 'gemini-
|
|
488
|
+
case 'gemini-home': return path.join(home, '.gemini', 'skills');
|
|
489
|
+
case 'gemini-project': return path.join(process.cwd(), '.gemini', 'skills');
|
|
364
490
|
case 'opencode': return path.join(home, '.config', 'opencode', 'skills');
|
|
365
491
|
default: return null;
|
|
366
492
|
}
|
|
367
493
|
}
|
|
368
494
|
function getTargetCommandsDir(target) {
|
|
369
495
|
const home = os.homedir();
|
|
370
|
-
switch (target) {
|
|
371
|
-
case 'claude-
|
|
372
|
-
case 'cursor':
|
|
496
|
+
switch (_canon(target)) {
|
|
497
|
+
case 'claude-home': return path.join(home, '.claude', 'commands');
|
|
373
498
|
case 'cursor-project': return path.join(home, '.cursor', 'commands');
|
|
374
|
-
case 'windsurf-home':
|
|
499
|
+
case 'windsurf-home':
|
|
500
|
+
case 'windsurf-project': return path.join(home, '.codeium', 'windsurf', 'commands');
|
|
375
501
|
case 'antigravity': return path.join(home, '.antigravity', 'commands');
|
|
376
502
|
case 'codex-home': return path.join(home, '.codex', 'commands');
|
|
377
|
-
case 'gemini-
|
|
503
|
+
case 'gemini-home': return path.join(home, '.gemini', 'commands');
|
|
504
|
+
case 'gemini-project': return path.join(process.cwd(), '.gemini', 'commands');
|
|
378
505
|
case 'opencode': return path.join(home, '.config', 'opencode', 'commands');
|
|
379
506
|
default: return null;
|
|
380
507
|
}
|
|
@@ -1033,6 +1160,91 @@ if (args[0] === 'evolve') {
|
|
|
1033
1160
|
return;
|
|
1034
1161
|
}
|
|
1035
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
|
+
|
|
1036
1248
|
// ── Help shortcut ─────────────────────────────────────────────────────────────
|
|
1037
1249
|
if (args.includes('--help') || args.includes('-h')) {
|
|
1038
1250
|
console.log(`
|
|
@@ -1232,7 +1444,8 @@ if (isWin) {
|
|
|
1232
1444
|
try {
|
|
1233
1445
|
const rtk = require(path.join(ROOT, 'scripts', 'rtk', 'index.js'));
|
|
1234
1446
|
const targetIdx = args.indexOf('--target');
|
|
1235
|
-
const
|
|
1447
|
+
const rawTarget = targetIdx >= 0 && args[targetIdx + 1] ? args[targetIdx + 1] : 'claude-code';
|
|
1448
|
+
const target = rtk.normalizeTarget(rawTarget);
|
|
1236
1449
|
if (rtk.TARGET_MAP[target]) {
|
|
1237
1450
|
const w = (m) => process.stdout.write(m + '\n');
|
|
1238
1451
|
w('');
|
|
@@ -1261,7 +1474,8 @@ if (isWin) {
|
|
|
1261
1474
|
try {
|
|
1262
1475
|
const rtk2 = require(path.join(ROOT, 'scripts', 'rtk', 'index.js'));
|
|
1263
1476
|
const targetIdx = args.indexOf('--target');
|
|
1264
|
-
const
|
|
1477
|
+
const rawTarget = targetIdx >= 0 && args[targetIdx + 1] ? args[targetIdx + 1] : 'claude-code';
|
|
1478
|
+
const target = rtk2.normalizeTarget(rawTarget);
|
|
1265
1479
|
const skillsDir = getTargetSkillsDir(target);
|
|
1266
1480
|
const cmdsDir = getTargetCommandsDir(target);
|
|
1267
1481
|
if (skillsDir && cmdsDir) {
|
|
@@ -1280,6 +1494,28 @@ if (isWin) {
|
|
|
1280
1494
|
} catch (e) {
|
|
1281
1495
|
process.stderr.write(`[terse] setup skipped: ${e.message}\n`);
|
|
1282
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
|
+
}
|
|
1283
1519
|
}
|
|
1284
1520
|
|
|
1285
1521
|
process.exit(result.status ?? 1);
|
package/install.sh
CHANGED
|
@@ -233,7 +233,7 @@ HOME_DIR="$HOME"
|
|
|
233
233
|
WINDSURFRULES_DEST="" # only set for windsurf targets
|
|
234
234
|
|
|
235
235
|
case "$TARGET" in
|
|
236
|
-
claude-home)
|
|
236
|
+
claude-home|claude-code)
|
|
237
237
|
DEST="$HOME_DIR/.claude"
|
|
238
238
|
AGENTS_DEST="$DEST/agents"
|
|
239
239
|
SKILLS_DEST="$DEST/skills"
|
|
@@ -361,7 +361,7 @@ case "$TARGET" in
|
|
|
361
361
|
;;
|
|
362
362
|
*)
|
|
363
363
|
echo -e "${RED}Unknown target: $TARGET${RESET}"
|
|
364
|
-
echo "Valid targets: claude-home, antigravity, cursor-project, windsurf-project, windsurf-home, codex-home, opencode, cline, roocode, aider, kimi, gemini-project, gemini-home"
|
|
364
|
+
echo "Valid targets: claude-home (aka claude-code), antigravity, cursor-project, windsurf-project, windsurf-home, codex-home, opencode, cline, roocode, aider, kimi, gemini-project, gemini-home"
|
|
365
365
|
exit 1
|
|
366
366
|
;;
|
|
367
367
|
esac
|
|
@@ -375,8 +375,12 @@ fi
|
|
|
375
375
|
echo ""
|
|
376
376
|
|
|
377
377
|
# ── Confirm ───────────────────────────────────────────────────────────────────
|
|
378
|
-
|
|
379
|
-
|
|
378
|
+
# Honour KODELYTH_NONINTERACTIVE=1 for CI, npx pipes, and Windows powershell path.
|
|
379
|
+
if [[ "${KODELYTH_NONINTERACTIVE:-}" == "1" ]]; then
|
|
380
|
+
CONFIRM="Y"
|
|
381
|
+
echo -e "${CYAN} Non-interactive mode (KODELYTH_NONINTERACTIVE=1) — proceeding.${RESET}"
|
|
382
|
+
elif [[ -e /dev/tty ]] && [[ -r /dev/tty ]]; then
|
|
383
|
+
read -r -p "$(echo -e "${YELLOW}Proceed with install? [Y/n] ${RESET}")" CONFIRM </dev/tty || CONFIRM="Y"
|
|
380
384
|
CONFIRM="${CONFIRM:-Y}"
|
|
381
385
|
else
|
|
382
386
|
CONFIRM="Y"
|
|
@@ -476,7 +480,7 @@ echo -e "${BOLD}Installing components...${RESET}"
|
|
|
476
480
|
echo ""
|
|
477
481
|
|
|
478
482
|
case "$TARGET" in
|
|
479
|
-
claude-home)
|
|
483
|
+
claude-home|claude-code)
|
|
480
484
|
install_dir "$SCRIPT_DIR/agents" "$AGENTS_DEST" "Agents ($AGENT_COUNT)"
|
|
481
485
|
install_dir "$SCRIPT_DIR/skills" "$SKILLS_DEST" "Skills ($SKILL_COUNT)"
|
|
482
486
|
install_dir "$SCRIPT_DIR/commands" "$COMMANDS_DEST" "Commands ($CMD_COUNT)"
|
|
@@ -685,7 +689,7 @@ echo -e "${GREEN}${BOLD} ARMED AND OPERATIONAL.${RESET}"
|
|
|
685
689
|
echo ""
|
|
686
690
|
|
|
687
691
|
case "$TARGET" in
|
|
688
|
-
claude-home)
|
|
692
|
+
claude-home|claude-code)
|
|
689
693
|
echo -e "${BOLD} Claude Code — what to do now:${RESET}"
|
|
690
694
|
echo ""
|
|
691
695
|
echo " Open any project in Claude Code, then:"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kodelyth-ecc",
|
|
3
|
-
"version": "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">
|
|
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(); }
|
package/scripts/rtk/index.js
CHANGED
|
@@ -18,9 +18,10 @@ const fs = require('fs');
|
|
|
18
18
|
|
|
19
19
|
// ── ECC install target → RTK agent flag ──────────────────────────────────────
|
|
20
20
|
// Reference: `rtk init --help` and RTK README "Supported AI Tools" table.
|
|
21
|
+
// Keyed by canonical install.sh target names (claude-home, gemini-home, ...).
|
|
22
|
+
// Common aliases (claude-code, gemini-cli) are normalised in normalizeTarget().
|
|
21
23
|
const TARGET_MAP = {
|
|
22
|
-
'claude-
|
|
23
|
-
'cursor': ['init', '-g', '--agent', 'cursor'],
|
|
24
|
+
'claude-home': ['init', '-g'],
|
|
24
25
|
'cursor-project': ['init', '--agent', 'cursor'],
|
|
25
26
|
'windsurf-home': ['init', '-g', '--agent', 'windsurf'],
|
|
26
27
|
'windsurf-project': ['init', '--agent', 'windsurf'],
|
|
@@ -28,22 +29,32 @@ const TARGET_MAP = {
|
|
|
28
29
|
'codex-home': ['init', '-g', '--codex'],
|
|
29
30
|
'opencode': ['init', '-g', '--opencode'],
|
|
30
31
|
'cline': ['init', '--agent', 'cline'],
|
|
31
|
-
'gemini-
|
|
32
|
+
'gemini-home': ['init', '-g', '--gemini'],
|
|
33
|
+
'roocode': ['init', '--agent', 'cline'], // roocode is cline-compatible per RTK
|
|
34
|
+
'kimi': ['init', '-g'], // treat like claude-code hook
|
|
32
35
|
};
|
|
33
36
|
|
|
37
|
+
// Normalise well-known aliases → canonical target names used by install.sh.
|
|
38
|
+
function normalizeTarget(t) {
|
|
39
|
+
if (t === 'claude-code') return 'claude-home';
|
|
40
|
+
if (t === 'gemini-cli') return 'gemini-home';
|
|
41
|
+
if (t === 'cursor') return 'cursor-project';
|
|
42
|
+
return t;
|
|
43
|
+
}
|
|
44
|
+
|
|
34
45
|
// ── Detect which IDEs ECC has already been installed for on this machine ─────
|
|
35
46
|
// Returns list of ECC install-target strings that have visible ECC artifacts.
|
|
36
47
|
function detectInstalledTargets() {
|
|
37
48
|
const home = os.homedir();
|
|
38
49
|
const targets = [];
|
|
39
50
|
const checks = [
|
|
40
|
-
{ target: 'claude-
|
|
41
|
-
{ target: 'cursor',
|
|
51
|
+
{ target: 'claude-home', dir: path.join(home, '.claude', 'agents') },
|
|
52
|
+
{ target: 'cursor-project', dir: path.join(home, '.cursor', 'rules') },
|
|
42
53
|
{ target: 'windsurf-home', dir: path.join(home, '.codeium', 'windsurf', 'memories') },
|
|
43
54
|
{ target: 'antigravity', dir: path.join(home, '.antigravity') },
|
|
44
55
|
{ target: 'codex-home', dir: path.join(home, '.codex') },
|
|
45
56
|
{ target: 'opencode', dir: path.join(home, '.config', 'opencode') },
|
|
46
|
-
{ target: 'gemini-
|
|
57
|
+
{ target: 'gemini-home', dir: path.join(home, '.gemini') },
|
|
47
58
|
];
|
|
48
59
|
for (const { target, dir } of checks) {
|
|
49
60
|
try {
|
|
@@ -116,15 +127,16 @@ function enableFor(target, { log = () => {} } = {}) {
|
|
|
116
127
|
if (!isInstalled()) {
|
|
117
128
|
return { enabled: false, skipped: true, reason: 'rtk binary not on PATH' };
|
|
118
129
|
}
|
|
119
|
-
const
|
|
130
|
+
const canonical = normalizeTarget(target);
|
|
131
|
+
const rtkArgs = TARGET_MAP[canonical];
|
|
120
132
|
if (!rtkArgs) {
|
|
121
133
|
return { enabled: false, skipped: true, reason: `no RTK mapping for target "${target}"` };
|
|
122
134
|
}
|
|
123
135
|
|
|
124
|
-
log(`[rtk] wiring RTK into ${
|
|
136
|
+
log(`[rtk] wiring RTK into ${canonical} …`);
|
|
125
137
|
// --auto-patch is only accepted by the default Claude Code hook flow.
|
|
126
138
|
// Other agent flags (--codex, --gemini, --opencode, --agent X) reject it.
|
|
127
|
-
const finalArgs =
|
|
139
|
+
const finalArgs = canonical === 'claude-home' ? [...rtkArgs, '--auto-patch'] : rtkArgs;
|
|
128
140
|
const r = spawnSync('rtk', finalArgs, { encoding: 'utf8' });
|
|
129
141
|
const output = (r.stdout || '') + (r.stderr || '');
|
|
130
142
|
if (r.status !== 0) {
|
|
@@ -175,6 +187,7 @@ function savings({ days = 30 } = {}) {
|
|
|
175
187
|
|
|
176
188
|
module.exports = {
|
|
177
189
|
TARGET_MAP,
|
|
190
|
+
normalizeTarget,
|
|
178
191
|
detectInstalledTargets,
|
|
179
192
|
isInstalled,
|
|
180
193
|
getVersion,
|