kodelyth-ecc 2.3.0 → 2.4.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 +70 -0
- package/README.md +193 -0
- package/VERSION +1 -1
- package/bin/kodelyth-ecc.js +51 -1
- package/package.json +1 -1
- package/rules/common/agent-intent-routing.md +126 -1
- package/scripts/cli/menu.js +41 -0
- package/scripts/cli/uninstall.js +148 -0
- package/scripts/codebase/index.js +16 -1
- package/scripts/dashboard/static/index.html +10 -0
- package/scripts/mcp/register-self.js +116 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,76 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Kodelyth ECC are documented here.
|
|
4
4
|
|
|
5
|
+
## v2.4.1 — Intent routing v2 (July 2026)
|
|
6
|
+
|
|
7
|
+
Full design pass on `rules/common/agent-intent-routing.md` — the always-on rule that maps plain-language user intent to specialist agents. Deferred from 2.4.0.
|
|
8
|
+
|
|
9
|
+
### Added — 8 new routing dimensions layered above the existing 10-tier signal tables
|
|
10
|
+
|
|
11
|
+
1. **Confidence tiers** — high (route silently), medium (route + "not X? say so" tail), low (name 2 candidates, ask), none (answer directly, don't announce)
|
|
12
|
+
2. **Session-state awareness** — once routed to an agent, stay in its voice for follow-ups. Do NOT re-announce the same routing. Only re-route when the user's message contains a stronger signal for a different agent
|
|
13
|
+
3. **Anti-routing whitelist** — 6 situations where routing MUST be skipped (under 5 words with no code, one-line factual questions, explicit `use X`, "don't route", mid-workflow, ECC-itself bug reports)
|
|
14
|
+
4. **New signal families for v2.4+** — routes for `/terse`, `/terse-compress`, `codebase-memory-mcp` queries, `kodelythecc uninstall`, `kodelythecc dashboard`, IDE install
|
|
15
|
+
5. **Compound intent → parallel commands** — when 2 tables match at once, fire the parallel command instead of both agents sequentially (security+review → `/security-audit`, bug+multi-layer → `/debug-blitz`, etc.)
|
|
16
|
+
6. **Announcement style adapts to terse mode** — if `/terse` is active this session, drop the tip line and use one-token announcement `→ debug-detective` instead of the full form
|
|
17
|
+
7. **Cultural / multi-language cues** — read emotional markers in any language, strip filler like "bro"/"yaar"/"man", respond in the user's this-turn language, never translate code/errors/commands
|
|
18
|
+
8. **Evolve integration** — routing misses feed `~/.kodelythecc/evolve/routing-misses.jsonl` so the evolve pipeline can propose new triggers later
|
|
19
|
+
|
|
20
|
+
### Added — 5 new output-format examples
|
|
21
|
+
|
|
22
|
+
- Default (verbose)
|
|
23
|
+
- Terse mode active — one-token announcement
|
|
24
|
+
- Medium-confidence single match — with "wrong?" tail
|
|
25
|
+
- Low-confidence, two candidates — asks user to pick
|
|
26
|
+
- Sticky routing continuation — no re-announcement
|
|
27
|
+
- Compound intent → parallel command
|
|
28
|
+
|
|
29
|
+
### Verified
|
|
30
|
+
|
|
31
|
+
- All 21 tests pass
|
|
32
|
+
- Rule file grew from 707 → 832 lines (net +125 lines of new dimensions), 69 sections total
|
|
33
|
+
- The 10-tier priority signal tables (unchanged) remain the workhorse; the 8 new dimensions layer above them
|
|
34
|
+
|
|
35
|
+
## v2.4.0 — MCP auto-register + full uninstall (July 2026)
|
|
36
|
+
|
|
37
|
+
Real bugs surfaced by live user testing on a fresh Mac install.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- **ECC's own MCP server was never registered anywhere** on install. Result: Claude Desktop showed "1 setup issue: MCP", the Codebase / MCP status views showed nothing, and no tool got to talk to our own MCP. `scripts/mcp/register-self.js` now writes `kodelyth-ecc` under `mcpServers` in both `~/.claude.json` (Claude Code) and `~/Library/Application Support/Claude/claude_desktop_config.json` (Claude Desktop). Idempotent — no duplicates on re-run.
|
|
42
|
+
- **Codebase Architecture snapshot was empty** on the dashboard when no active session graph existed. Dashboard now falls back to a per-project list (project name + nodes + edges) via `list_projects`, so users can see the 8 projects codebase-memory-mcp has indexed even before opening one in-session.
|
|
43
|
+
- **`mcp-register` subcommand was swallowed** by the `mcp-*` catch-all (like `mcp-status` was earlier). Excluded properly.
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
**MCP self-registration**
|
|
48
|
+
- `kodelythecc mcp-register` — write ECC's MCP entry into Claude Code + Desktop configs
|
|
49
|
+
- `kodelythecc mcp-register --status` — show which configs already have it
|
|
50
|
+
- `kodelythecc mcp-register --unregister` — remove ECC's entry
|
|
51
|
+
- **Auto-runs in post-install** — after `--target claude-code` succeeds, ECC registers itself in both configs and prints a summary. Opt out with `--no-mcp-register`
|
|
52
|
+
|
|
53
|
+
**Full uninstall** (`scripts/cli/uninstall.js`)
|
|
54
|
+
- New menu row: **Uninstall ECC completely**
|
|
55
|
+
- CLI: `kodelythecc uninstall --dry-run | --yes | --yes --keep-memory`
|
|
56
|
+
- Removes only files that were shipped by ECC (checks against the package's own `agents/skills/commands/hooks/rules/scripts/` — safe for user-authored siblings)
|
|
57
|
+
- Unwires RTK (`rtk init -g --uninstall`)
|
|
58
|
+
- Removes codebase-memory-mcp agent configs (`codebase-memory-mcp uninstall`)
|
|
59
|
+
- Removes ECC's MCP entry from Claude Code + Desktop
|
|
60
|
+
- Removes `~/.kodelythecc/` (memory + ledgers + cache)
|
|
61
|
+
- Removes legacy `.kodelyth.backup-*` dirs
|
|
62
|
+
- Dry-run mode identifies **759 ECC files** across 6 subdirs on a fresh install
|
|
63
|
+
|
|
64
|
+
### Verified live end-to-end on this Mac
|
|
65
|
+
|
|
66
|
+
- `mcp-register --status` (before): both configs empty
|
|
67
|
+
- `mcp-register` writes both:
|
|
68
|
+
```json
|
|
69
|
+
"kodelyth-ecc": { "command": "kodelythecc", "args": ["mcp"], "env": {} }
|
|
70
|
+
```
|
|
71
|
+
- `~/.claude.json` now has `mcpServers.kodelyth-ecc` + existing `mcpServers.codebase-memory-mcp` (co-existing, no clobber)
|
|
72
|
+
- `uninstall --dry-run` correctly counts 70 agents + 301 skills + 99 commands + 12 hooks + 104 rules + 173 scripts = 759 files, plus 1 backup dir
|
|
73
|
+
- Nothing removed on dry-run — verified
|
|
74
|
+
|
|
5
75
|
## v2.3.0 — Interactive arrow-key CLI menu (July 2026)
|
|
6
76
|
|
|
7
77
|
Run `kodelythecc` (or `kodelyth-ecc`) with no args in a real terminal and an arrow-key menu opens.
|
package/README.md
CHANGED
|
@@ -19,11 +19,22 @@
|
|
|
19
19
|

|
|
20
20
|

|
|
21
21
|

|
|
22
|
+

|
|
23
|
+

|
|
24
|
+

|
|
25
|
+

|
|
22
26
|
|
|
23
27
|
</div>
|
|
24
28
|
|
|
25
29
|
**Kodelyth ECC** is a production-grade AI coding toolkit — **70 specialist agents (incl. an 8-agent devil-mode adversarial crew), 194 skills, 97 commands**, a god-tier **semantic intent-routing system**, local self-learning memory, MCP server, swarm orchestrator, and an observability dashboard — all local, zero telemetry.
|
|
26
30
|
|
|
31
|
+
Now bundled with:
|
|
32
|
+
|
|
33
|
+
- **RTK** (Rust Token Killer, Apache-2.0) — auto-compresses shell command output for **60-90% input token savings**
|
|
34
|
+
- **Terse mode** (ECC-native, inspired by Caveman) — 4-level output-token compression dial for **40-70% output savings**
|
|
35
|
+
- **Codebase graph** (via [codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp), MIT) — AST-parsed knowledge graph across 158 languages; structural queries at **99% fewer tokens** than file-by-file grep
|
|
36
|
+
- **Interactive CLI** — type `kodelythecc` alone in a terminal for an arrow-key menu with live update check, dashboard, background daemon
|
|
37
|
+
|
|
27
38
|
Works with **Claude Code**, **Windsurf**, **Cursor**, **Codex CLI**, **Google Antigravity**, **OpenCode**, **Cline**, **Roo Code**, **Aider**, **Kimi**, and **Gemini CLI**.
|
|
28
39
|
|
|
29
40
|
> No telemetry. No cloud. Just rules, agents, skills, MCP server, and your own private memory store — all on your disk. The local dashboard gives you full visibility without sending anything anywhere.
|
|
@@ -88,6 +99,25 @@ You never typed `use debug-detective`. You didn't have to. The toolkit read the
|
|
|
88
99
|
<img src="social/section-install.svg" alt="Install — One command, 11 platforms, any OS" width="900"/>
|
|
89
100
|
</div>
|
|
90
101
|
|
|
102
|
+
### The lazy install (one command, everything wired up)
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npm i -g kodelyth-ecc
|
|
106
|
+
kodelythecc --target claude-code --codebase-graph
|
|
107
|
+
# then restart your AI tool
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
That's it. This single flow:
|
|
111
|
+
|
|
112
|
+
1. Installs both binaries (`kodelyth-ecc` and short-form `kodelythecc`) to your PATH
|
|
113
|
+
2. Copies 70 agents + 194 skills + 97 commands + 22 hooks + 14 rules into your AI tool's config dir
|
|
114
|
+
3. Auto-installs **RTK** binary and wires its PreToolUse hook (input compression starts on next AI restart)
|
|
115
|
+
4. Installs **Terse mode** skill + `/terse` and `/terse-compress` slash commands (dormant — user types `/terse` to activate)
|
|
116
|
+
5. Auto-installs **codebase-memory-mcp** and registers its MCP entries in your AI tool (with `--codebase-graph`)
|
|
117
|
+
6. Runs legacy-memory migration if you had `~/.kodelyth/` from an older install → `~/.kodelythecc/`
|
|
118
|
+
|
|
119
|
+
After it finishes, run `kodelythecc` alone to open the interactive menu.
|
|
120
|
+
|
|
91
121
|
### Option 1 — npx from npm (recommended, any platform)
|
|
92
122
|
|
|
93
123
|
```bash
|
|
@@ -398,6 +428,169 @@ Full reference: [`docs/dashboard.md`](docs/dashboard.md).
|
|
|
398
428
|
|
|
399
429
|
---
|
|
400
430
|
|
|
431
|
+
## RTK — Input Token Savings (60-90%)
|
|
432
|
+
|
|
433
|
+
[RTK (Rust Token Killer)](https://github.com/rtk-ai/rtk) — Apache-2.0, single Rust binary — intercepts shell commands before they run and filters the output. Common commands like `git status`, `ls`, `cargo test`, `docker ps` return ~80% less text with zero information loss for the LLM.
|
|
434
|
+
|
|
435
|
+
ECC bundles RTK end-to-end:
|
|
436
|
+
|
|
437
|
+
- Auto-installs the binary via Homebrew (macOS) or curl script (Linux / WSL)
|
|
438
|
+
- Auto-configures the PreToolUse hook in your AI tool's settings
|
|
439
|
+
- Live ledger surfaced in the dashboard's **Token Savings** tab
|
|
440
|
+
|
|
441
|
+
### Manage from the CLI
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
kodelythecc rtk install # install rtk binary
|
|
445
|
+
kodelythecc rtk enable --target X # wire into one IDE
|
|
446
|
+
kodelythecc rtk enable --all # wire into every ECC-installed IDE at once
|
|
447
|
+
kodelythecc rtk status # version + active integrations
|
|
448
|
+
kodelythecc rtk gain --all # raw rtk savings output
|
|
449
|
+
kodelythecc rtk --help # focused help
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Live proof (from this repo maintainer's Mac)
|
|
453
|
+
|
|
454
|
+
```
|
|
455
|
+
total_commands: 1,285
|
|
456
|
+
total_input: 7,964,612 (raw)
|
|
457
|
+
total_output: 2,858,501 (after RTK filter)
|
|
458
|
+
total_saved: 5,107,394 ← 64.1% average reduction
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Terse Mode — Output Token Savings (40-70%)
|
|
464
|
+
|
|
465
|
+
RTK compresses input. **Terse mode** compresses output. Together they stack — savings on both sides of every turn.
|
|
466
|
+
|
|
467
|
+
ECC's own implementation, inspired by [Caveman](https://github.com/JuliusBrussee/caveman) (MIT), independently written. Ships as a skill + two slash commands + a deterministic zero-dep memory-file compressor.
|
|
468
|
+
|
|
469
|
+
### Four levels
|
|
470
|
+
|
|
471
|
+
Type `/terse` in your AI tool. Level sticks until you switch or session ends.
|
|
472
|
+
|
|
473
|
+
| Level | Style |
|
|
474
|
+
|---|---|
|
|
475
|
+
| `/terse off` | Normal AI voice |
|
|
476
|
+
| `/terse lite` | Light trim, drop filler ("basically", "essentially") |
|
|
477
|
+
| `/terse full` | Telegram-style fragments (default) |
|
|
478
|
+
| `/terse ultra` | Maximum compression, symbols over words |
|
|
479
|
+
|
|
480
|
+
**Byte-preserved always**: fenced code blocks, inline code, shell commands, error text, URLs, file paths, identifiers, numbers, versions.
|
|
481
|
+
|
|
482
|
+
### Compress memory files permanently
|
|
483
|
+
|
|
484
|
+
`/terse-compress` (or `kodelythecc terse compress <file>`) rewrites `CLAUDE.md`-style memory files into terse form so they cost fewer tokens **every session forever**. ~30% average byte reduction on real prose, 100% code/URL/path integrity.
|
|
485
|
+
|
|
486
|
+
### CLI
|
|
487
|
+
|
|
488
|
+
```bash
|
|
489
|
+
kodelythecc terse status # skill install state
|
|
490
|
+
kodelythecc terse stats # tokens saved from ledger
|
|
491
|
+
kodelythecc terse compress <file> # rewrite a file, byte-preserves code
|
|
492
|
+
kodelythecc terse enable --all # install skill + commands into every ECC IDE
|
|
493
|
+
kodelythecc terse --help
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
## Codebase Graph — 158 Languages, Structural Queries
|
|
499
|
+
|
|
500
|
+
Powered by [DeusData/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp) (MIT). AST-parsed knowledge graph via tree-sitter across **158 languages**, Hybrid LSP semantic type resolution for 11 major languages, cross-service HTTP/gRPC/GraphQL linking, 14 MCP tools for structural queries.
|
|
501
|
+
|
|
502
|
+
**Why this matters**: "Who calls `ProcessOrder`?" via file-by-file grep = ~412k tokens. Same question via the graph = ~3.4k tokens. That's a **99% reduction** on structural questions.
|
|
503
|
+
|
|
504
|
+
### Auto-install path
|
|
505
|
+
|
|
506
|
+
Pass `--codebase-graph` on ECC install and it auto-runs their official curl script + auto-configures the MCP server entry in every installed AI-coding agent.
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
kodelythecc --target claude-code --codebase-graph
|
|
510
|
+
# ↑ installs ECC + RTK + Terse + codebase-memory-mcp, all wired up
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
Then in your AI tool, say **"Index this project"**. Done.
|
|
514
|
+
|
|
515
|
+
### CLI
|
|
516
|
+
|
|
517
|
+
```bash
|
|
518
|
+
kodelythecc codebase install # install + auto-register
|
|
519
|
+
kodelythecc codebase status # version + indexed projects
|
|
520
|
+
kodelythecc codebase query search_graph '{"name_pattern": ".*Handler.*"}'
|
|
521
|
+
kodelythecc codebase query trace_path '{"function_name": "main"}'
|
|
522
|
+
kodelythecc codebase query get_architecture '{}'
|
|
523
|
+
kodelythecc codebase --help
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
## Interactive CLI Menu
|
|
529
|
+
|
|
530
|
+
Type `kodelythecc` alone in a real terminal → arrow-key menu opens.
|
|
531
|
+
|
|
532
|
+
```
|
|
533
|
+
⚙ Kodelyth ECC v2.3.0 · Elite Code Crew up to date
|
|
534
|
+
|
|
535
|
+
▸ Open Dashboard localhost — RTK, Terse, Codebase, Memory
|
|
536
|
+
Install ECC for another IDE 13-target picker
|
|
537
|
+
RTK status Version + wired IDEs + savings
|
|
538
|
+
Terse status Skill install state, ledger totals
|
|
539
|
+
Codebase graph status 158 languages, structural queries
|
|
540
|
+
Memory stats BM25 recall — captures, projects, tags
|
|
541
|
+
Run in background Detached dashboard daemon
|
|
542
|
+
Exit
|
|
543
|
+
|
|
544
|
+
↑/↓ navigate · ⏎ select · q / esc / Ctrl+C to quit
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Behaviour rules
|
|
548
|
+
|
|
549
|
+
| Situation | Menu opens? |
|
|
550
|
+
|---|---|
|
|
551
|
+
| `kodelythecc` in Terminal / iTerm | **Yes** |
|
|
552
|
+
| `kodelythecc rtk status` (any subcommand) | No — runs subcommand |
|
|
553
|
+
| `echo hi \| kodelythecc` (piped) | No — runs installer |
|
|
554
|
+
| CI environment (`$CI` set) | No |
|
|
555
|
+
| `KODELYTH_NO_MENU=1 kodelythecc` | No |
|
|
556
|
+
|
|
557
|
+
### Uninstall
|
|
558
|
+
|
|
559
|
+
The menu's **Uninstall ECC completely** row runs an interactive full cleanup: removes the 759 ECC-installed files from `~/.claude/`, unwires RTK from your AI tool, removes codebase-memory-mcp agent configs, removes ECC's MCP entry from Claude Code + Claude Desktop, and deletes `~/.kodelythecc/` (memory + ledgers). Prompts confirm before anything is deleted; a dry-run mode previews what would be removed without touching anything.
|
|
560
|
+
|
|
561
|
+
You can also run it non-interactively:
|
|
562
|
+
|
|
563
|
+
```bash
|
|
564
|
+
kodelythecc uninstall --dry-run # preview what would be removed
|
|
565
|
+
kodelythecc uninstall --yes # full cleanup
|
|
566
|
+
kodelythecc uninstall --yes --keep-memory # remove files but keep ~/.kodelythecc/
|
|
567
|
+
npm uninstall -g kodelyth-ecc # finally remove the npm package itself
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
### Update check
|
|
571
|
+
|
|
572
|
+
The menu polls `https://registry.npmjs.org/kodelyth-ecc/latest` on open. Cached 24h in `~/.kodelythecc/update-check.json`. When a newer version exists, an extra menu row appears at the top:
|
|
573
|
+
|
|
574
|
+
```
|
|
575
|
+
▸ Update to v2.3.1 [NEW] npm i -g kodelyth-ecc
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### Background daemon
|
|
579
|
+
|
|
580
|
+
Selecting "Run in background" forks the dashboard as a detached process:
|
|
581
|
+
|
|
582
|
+
```
|
|
583
|
+
✓ Dashboard daemon started (pid 12345)
|
|
584
|
+
URL: http://127.0.0.1:5747
|
|
585
|
+
Log: /Users/you/.kodelythecc/dashboard-daemon.log
|
|
586
|
+
Pid: /Users/you/.kodelythecc/dashboard-daemon.pid
|
|
587
|
+
Stop: kill $(cat ~/.kodelythecc/dashboard-daemon.pid)
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Survives shell exit. Real daemon.
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
401
594
|
## Kodelyth Memory — Local Self-Learning
|
|
402
595
|
|
|
403
596
|
<div align="center">
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.4.1
|
package/bin/kodelyth-ecc.js
CHANGED
|
@@ -135,7 +135,7 @@ if (args[0] === 'mcp') {
|
|
|
135
135
|
// kodelyth-ecc mcp-remove <name>
|
|
136
136
|
// kodelyth-ecc mcp-tools <name>
|
|
137
137
|
// kodelyth-ecc mcp-call <name> <tool> [--json '{"arg":"value"}']
|
|
138
|
-
if (args[0] && args[0].startsWith('mcp-')) {
|
|
138
|
+
if (args[0] && args[0].startsWith('mcp-') && !['mcp-register'].includes(args[0])) {
|
|
139
139
|
(async () => {
|
|
140
140
|
const sub = args[0].slice(4);
|
|
141
141
|
const client = require(path.join(ROOT, 'scripts', 'mcp', 'client.js'));
|
|
@@ -339,6 +339,40 @@ if (args[0] === 'rtk') {
|
|
|
339
339
|
return;
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
+
// ── Subcommand: uninstall (full ECC removal) ────────────────────────────────
|
|
343
|
+
if (args[0] === 'uninstall') {
|
|
344
|
+
const un = require(path.join(ROOT, 'scripts', 'cli', 'uninstall.js'));
|
|
345
|
+
const dryRun = args.includes('--dry-run');
|
|
346
|
+
const keepMemory = args.includes('--keep-memory');
|
|
347
|
+
const yes = args.includes('--yes') || args.includes('-y');
|
|
348
|
+
if (!yes && !dryRun) {
|
|
349
|
+
process.stderr.write('This removes ECC files, RTK hooks, codebase-memory-mcp configs, and (unless --keep-memory) ~/.kodelythecc/. Add --yes to confirm or --dry-run to preview.\n');
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
const r = un.run({ log: (m) => process.stdout.write(m + '\n'), dryRun, keepMemory });
|
|
353
|
+
process.stdout.write(`\nRemoved ${r.removed_files} files across ${r.subsystems_uninstalled.length} subsystems.\n`);
|
|
354
|
+
if (r.errors.length) process.stdout.write(`Errors: ${r.errors.length}\n${r.errors.map(e => ' ' + e).join('\n')}\n`);
|
|
355
|
+
process.stdout.write(dryRun ? '(dry-run — no changes made)\n' : 'ECC removed. Uninstall the npm package: npm uninstall -g kodelyth-ecc\n');
|
|
356
|
+
process.exit(0);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ── Subcommand: mcp-register (self-register ECC MCP in Claude Code + Desktop)
|
|
360
|
+
if (args[0] === 'mcp-register') {
|
|
361
|
+
const reg = require(path.join(ROOT, 'scripts', 'mcp', 'register-self.js'));
|
|
362
|
+
if (args.includes('--status')) {
|
|
363
|
+
const s = reg.statusAll();
|
|
364
|
+
for (const row of s) process.stdout.write(`${row.present ? '✓' : '·'} ${row.file}${row.exists ? '' : ' (file missing)'}\n`);
|
|
365
|
+
process.exit(0);
|
|
366
|
+
}
|
|
367
|
+
if (args.includes('--unregister')) {
|
|
368
|
+
reg.unregisterAll({ log: (m) => process.stdout.write(m + '\n') });
|
|
369
|
+
process.exit(0);
|
|
370
|
+
}
|
|
371
|
+
reg.registerAll({ log: (m) => process.stdout.write(m + '\n') });
|
|
372
|
+
process.stdout.write('\nRestart Claude Code / Claude Desktop to pick up the new MCP server.\n');
|
|
373
|
+
process.exit(0);
|
|
374
|
+
}
|
|
375
|
+
|
|
342
376
|
// ── Subcommand: codebase (DeusData code-graph MCP integration) ───────────────
|
|
343
377
|
// Usage:
|
|
344
378
|
// kodelyth-ecc codebase install install the codebase-memory-mcp binary
|
|
@@ -1451,6 +1485,22 @@ if (isWin) {
|
|
|
1451
1485
|
fs.chmodSync(sh, 0o755);
|
|
1452
1486
|
const result = spawnSync('bash', [sh, ...args], { stdio: 'inherit', shell: false });
|
|
1453
1487
|
|
|
1488
|
+
// Post-install: auto-register ECC's own MCP server in Claude Code + Desktop.
|
|
1489
|
+
if (result.status === 0 && !args.includes('--no-mcp-register')) {
|
|
1490
|
+
try {
|
|
1491
|
+
const reg = require(path.join(ROOT, 'scripts', 'mcp', 'register-self.js'));
|
|
1492
|
+
process.stdout.write('\n━ ECC MCP server registration ' + '─'.repeat(31) + '\n');
|
|
1493
|
+
const rows = reg.registerAll({ log: () => {} });
|
|
1494
|
+
for (const r of rows) {
|
|
1495
|
+
const marker = r.action === 'added' ? '✓ added' : r.action === 'updated' ? '✓ updated' : r.action === 'unchanged' ? '· unchanged' : `· ${r.action}`;
|
|
1496
|
+
process.stdout.write(` ${marker}: ${r.file}\n`);
|
|
1497
|
+
}
|
|
1498
|
+
process.stdout.write(` · Restart Claude Code / Claude Desktop to pick up the server\n`);
|
|
1499
|
+
} catch (e) {
|
|
1500
|
+
process.stderr.write(`[mcp] self-register skipped: ${e.message}\n`);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1454
1504
|
// Post-install: auto-install + wire RTK for the target IDE (opt-out via --no-rtk).
|
|
1455
1505
|
if (result.status === 0 && !args.includes('--no-rtk')) {
|
|
1456
1506
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kodelyth-ecc",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.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",
|
|
@@ -16,6 +16,96 @@ If multiple agents match, pick the **highest priority** below (priority decrease
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## Routing v2 — The Eight Dimensions
|
|
20
|
+
|
|
21
|
+
The signal tables below tell you **which agent** matches. These dimensions tell you **how confidently to route, when to stay silent, how to announce, and how to handle compound intent**. Apply them in order.
|
|
22
|
+
|
|
23
|
+
### 1. Confidence tiers
|
|
24
|
+
|
|
25
|
+
| Tier | Trigger | AI behaviour |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| **High** — 2+ signals from one table, OR 1 signal + emotion, OR explicit `use X` / `@X` | Route immediately with one-line announcement |
|
|
28
|
+
| **Medium** — 1 clean signal, no counter-signals | Route with one-line announcement AND a "Not X? Say so, I'll switch" tail |
|
|
29
|
+
| **Low** — 1 weak signal, or signals from 2+ tables of similar priority | **Do NOT auto-route.** Name the 2 best candidates in one line, ask which fits |
|
|
30
|
+
| **None** — no signal, or explicit anti-routing | Answer directly, no routing announcement |
|
|
31
|
+
|
|
32
|
+
### 2. Session-state awareness (sticky routing)
|
|
33
|
+
|
|
34
|
+
Once you have routed to an agent this session, **stay in that agent's voice** for follow-ups on the same thread unless:
|
|
35
|
+
|
|
36
|
+
- The user's next message contains a **stronger signal** for a different agent
|
|
37
|
+
- The user says "back to normal", "stop routing", "just answer me"
|
|
38
|
+
- The task has clearly concluded (test passes, PR merged, question answered)
|
|
39
|
+
|
|
40
|
+
**Never re-announce the same routing.** Sticky = quiet. Only announce again when the agent actually changes.
|
|
41
|
+
|
|
42
|
+
### 3. Anti-routing whitelist
|
|
43
|
+
|
|
44
|
+
Route to **no one** in these cases (skip Priority 1-10 entirely):
|
|
45
|
+
|
|
46
|
+
- Message is under 5 words AND has no error/code paste (e.g. "hi", "ok", "thanks", "cool", "yes")
|
|
47
|
+
- Message is a factual question with a one-line answer ("what does `git stash pop` do?")
|
|
48
|
+
- User already invoked with `use X`, `@X`, `run <agent>` — respect explicit choice
|
|
49
|
+
- User said "don't route" / "just answer" / "stop routing" this session
|
|
50
|
+
- User is in the middle of a multi-step interactive workflow the previous agent started
|
|
51
|
+
- The message is a bug report about ECC itself (routing bugs, install bugs) — answer as the maintainer, not as a specialist
|
|
52
|
+
|
|
53
|
+
### 4. New signal families (v2.4+)
|
|
54
|
+
|
|
55
|
+
Beyond the 10 priority tiers below, watch for these newer signals — they map to features shipped in ECC 2.x:
|
|
56
|
+
|
|
57
|
+
| User says | Route to |
|
|
58
|
+
|---|---|
|
|
59
|
+
| "compress this memory file" / "shrink CLAUDE.md" / "make my rules smaller" | `/terse-compress` |
|
|
60
|
+
| "talk shorter" / "be brief" / "less verbose" / "caveman mode" | `/terse` (skill activation) |
|
|
61
|
+
| "who calls X" / "where is X used" / "trace the call chain" / "impact analysis" | `codebase-memory-mcp` via `search_graph` / `trace_path` |
|
|
62
|
+
| "index this project" / "build the graph" / "scan the codebase" | `codebase-memory-mcp` via `index_repository` |
|
|
63
|
+
| "remove ECC" / "uninstall kodelythecc" / "clean this up" | Suggest `kodelythecc uninstall --dry-run` |
|
|
64
|
+
| "how much did I save" / "show my token savings" / "RTK stats" | `kodelythecc dashboard` OR `kodelythecc rtk gain` |
|
|
65
|
+
| "install for another IDE" / "add to Cursor / Windsurf / Antigravity" | `kodelythecc --target <ide>` |
|
|
66
|
+
|
|
67
|
+
### 5. Compound intent → parallel agents
|
|
68
|
+
|
|
69
|
+
Some messages match **two priority tables at once**. When they do, fire the parallel command, not both agents sequentially.
|
|
70
|
+
|
|
71
|
+
| User signals | Fire |
|
|
72
|
+
|---|---|
|
|
73
|
+
| security question + review question | `/security-audit` |
|
|
74
|
+
| bug + been-stuck-for-hours + multi-layer | `/debug-blitz` |
|
|
75
|
+
| architecture + security + a11y (new project) | `/project-launch` |
|
|
76
|
+
| pre-release + full audit | `/pre-release` |
|
|
77
|
+
| refactor + types + tests | `/refactor-sprint` |
|
|
78
|
+
| attacker mindset + multi-vector | `/devil-mode` |
|
|
79
|
+
| new codebase + orientation | `/onboard` |
|
|
80
|
+
| general audit + multiple angles | `/team-review` |
|
|
81
|
+
|
|
82
|
+
### 6. Announcement style adapts to terse mode
|
|
83
|
+
|
|
84
|
+
If the user has typed `/terse` this session:
|
|
85
|
+
|
|
86
|
+
- Drop the `Tip: next time you can type "use <agent>"` line
|
|
87
|
+
- Use a one-token announcement: `→ debug-detective` instead of `→ Routing to debug-detective (stack trace + frustration match)`
|
|
88
|
+
- No trailing decoration
|
|
89
|
+
|
|
90
|
+
If terse is **off**, use the full form documented in the "Output Format" section at the bottom.
|
|
91
|
+
|
|
92
|
+
### 7. Cultural + multi-language cues
|
|
93
|
+
|
|
94
|
+
The user may write in a mixed register (English + native language + technical shorthand). Read the cues:
|
|
95
|
+
|
|
96
|
+
- Emotional markers in any language route the same way: "arre yaar broken hai" = frustration = `debug-detective`
|
|
97
|
+
- Filler like "bro", "yaar", "man", "please" is not a signal — strip it, read the substance
|
|
98
|
+
- If the user's message language differs from previous turns, respond in the same language they used **this turn**, not their previous one
|
|
99
|
+
- Code identifiers, commands, and error text stay in their original language (never translate `NullPointerException`)
|
|
100
|
+
|
|
101
|
+
### 8. Evolve integration — routing misses become proposals
|
|
102
|
+
|
|
103
|
+
When you route (or explicitly do NOT route because the signal was weak) and the outcome is unsatisfying, the ECC evolve system writes this to `~/.kodelythecc/evolve/routing-misses.jsonl` so proposals for new triggers can be surfaced later.
|
|
104
|
+
|
|
105
|
+
You never write this file yourself. Just be honest in the routing announcement: if the match is weak, say "medium confidence — routing to X, not Y, because Z" so the evolve pipeline has a clean signal.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
19
109
|
## How to Apply This Rule — Semantic Intent, Not Keyword Matching
|
|
20
110
|
|
|
21
111
|
**Read the intent behind the words, not just the words.**
|
|
@@ -696,6 +786,7 @@ When the user's request spans multiple concerns, name the parallel agents:
|
|
|
696
786
|
|
|
697
787
|
## Output Format When Routing
|
|
698
788
|
|
|
789
|
+
**Default (verbose)**:
|
|
699
790
|
```
|
|
700
791
|
→ Routing to debug-detective (stack trace + frustration signals match the bug-tracking pattern)
|
|
701
792
|
|
|
@@ -704,4 +795,38 @@ When the user's request spans multiple concerns, name the parallel agents:
|
|
|
704
795
|
Tip: next time you can type "use debug-detective" to invoke me directly.
|
|
705
796
|
```
|
|
706
797
|
|
|
707
|
-
|
|
798
|
+
**Terse mode active (see Dimension 6)**:
|
|
799
|
+
```
|
|
800
|
+
→ debug-detective
|
|
801
|
+
|
|
802
|
+
[response — no tip line, no explanation of why]
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
**Medium-confidence single match** (add a "wrong?" tail):
|
|
806
|
+
```
|
|
807
|
+
→ Routing to code-reviewer (single file paste, no other context — treating as review)
|
|
808
|
+
|
|
809
|
+
[response as code-reviewer]
|
|
810
|
+
|
|
811
|
+
Not what you wanted? Say "use debug-detective" or "just answer" to switch.
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
**Low-confidence, two candidates** (ask, do not pick):
|
|
815
|
+
```
|
|
816
|
+
Two agents fit this: debug-detective (bug + error) or silent-failure-hunter (no error thrown).
|
|
817
|
+
Which one? Or should I answer directly?
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
**Sticky routing continuation** (already in an agent, no announcement):
|
|
821
|
+
```
|
|
822
|
+
[response continues in the same agent's voice — no re-announcement]
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
**Compound intent → parallel command**:
|
|
826
|
+
```
|
|
827
|
+
→ Firing /debug-blitz — 3 agents in parallel (debug-detective + silent-failure-hunter + env-debugger)
|
|
828
|
+
|
|
829
|
+
[synthesised result]
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
This keeps the user **informed**, **never surprised**, and **learning the toolkit** with every interaction — while still respecting terse mode and session context.
|
package/scripts/cli/menu.js
CHANGED
|
@@ -89,6 +89,11 @@ async function buildOptions({ ROOT }) {
|
|
|
89
89
|
hint: 'Detach dashboard as a daemon so /api routes stay reachable',
|
|
90
90
|
run: () => runBackground(),
|
|
91
91
|
});
|
|
92
|
+
opts.push({
|
|
93
|
+
label: 'Uninstall ECC completely',
|
|
94
|
+
hint: 'Remove agents/skills/commands/hooks, RTK hook, codebase-mcp, and ~/.kodelythecc/',
|
|
95
|
+
run: () => runUninstall(ROOT),
|
|
96
|
+
});
|
|
92
97
|
opts.push({
|
|
93
98
|
label: 'Exit',
|
|
94
99
|
hint: '',
|
|
@@ -149,6 +154,42 @@ async function pickIdeAndInstall(ROOT) {
|
|
|
149
154
|
waitForEnter().then(() => main().catch(() => process.exit(0)));
|
|
150
155
|
}
|
|
151
156
|
|
|
157
|
+
async function runUninstall(ROOT) {
|
|
158
|
+
cleanup();
|
|
159
|
+
console.log(`${C.red}${C.bold}⚠ Uninstall Kodelyth ECC${C.reset}`);
|
|
160
|
+
console.log('');
|
|
161
|
+
console.log('This will remove:');
|
|
162
|
+
console.log(` ${C.gray}·${C.reset} All ECC agents/skills/commands/hooks/rules installed under ~/.claude/`);
|
|
163
|
+
console.log(` ${C.gray}·${C.reset} RTK hook (rtk binary stays — remove with brew uninstall rtk)`);
|
|
164
|
+
console.log(` ${C.gray}·${C.reset} codebase-memory-mcp agent configs (binary stays)`);
|
|
165
|
+
console.log(` ${C.gray}·${C.reset} ECC MCP server entry from Claude Code + Claude Desktop`);
|
|
166
|
+
console.log(` ${C.gray}·${C.reset} ~/.kodelythecc/ (memory, ledgers, cache) — unless you keep it`);
|
|
167
|
+
console.log('');
|
|
168
|
+
const choice = await pick('Confirm', [
|
|
169
|
+
'Uninstall — remove EVERYTHING including memory',
|
|
170
|
+
'Uninstall — keep ~/.kodelythecc/ memory + ledgers',
|
|
171
|
+
'Dry run — show what would be removed, change nothing',
|
|
172
|
+
'Cancel',
|
|
173
|
+
]);
|
|
174
|
+
if (choice == null || choice === 3) return main();
|
|
175
|
+
const dryRun = choice === 2;
|
|
176
|
+
const keepMemory = choice === 1;
|
|
177
|
+
cleanup();
|
|
178
|
+
console.log('');
|
|
179
|
+
const un = require(path.join(ROOT, 'scripts', 'cli', 'uninstall.js'));
|
|
180
|
+
const r = un.run({ log: (m) => console.log(m), dryRun, keepMemory });
|
|
181
|
+
console.log('');
|
|
182
|
+
console.log(`${C.green}✓${C.reset} Removed ${C.bold}${r.removed_files}${C.reset} files across ${r.subsystems_uninstalled.length} subsystems.`);
|
|
183
|
+
if (r.errors.length) console.log(`${C.yellow}Errors: ${r.errors.length}${C.reset}`);
|
|
184
|
+
if (dryRun) {
|
|
185
|
+
console.log(`${C.dim}(dry-run — nothing was changed)${C.reset}`);
|
|
186
|
+
} else {
|
|
187
|
+
console.log('');
|
|
188
|
+
console.log(`Finish by removing the npm package: ${C.cyan}npm uninstall -g kodelyth-ecc${C.reset}`);
|
|
189
|
+
}
|
|
190
|
+
process.exit(0);
|
|
191
|
+
}
|
|
192
|
+
|
|
152
193
|
function runBackground() {
|
|
153
194
|
cleanup();
|
|
154
195
|
const logDir = path.join(os.homedir(), '.kodelythecc');
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// scripts/cli/uninstall.js
|
|
2
|
+
// Full ECC cleanup — reverses everything the installer + post-install did.
|
|
3
|
+
// Safe: only removes files installed BY ECC (checks for known markers).
|
|
4
|
+
// Never touches user's own custom agents/skills/commands they added themselves.
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { spawnSync } = require('child_process');
|
|
12
|
+
|
|
13
|
+
// ── What ECC ships — used to identify which files WE installed ─────────────
|
|
14
|
+
function listShippedFiles(ROOT, subdir) {
|
|
15
|
+
const src = path.join(ROOT, subdir);
|
|
16
|
+
if (!fs.existsSync(src)) return [];
|
|
17
|
+
const out = [];
|
|
18
|
+
const walk = (dir, prefix = '') => {
|
|
19
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
20
|
+
const rel = path.join(prefix, entry.name);
|
|
21
|
+
const abs = path.join(dir, entry.name);
|
|
22
|
+
if (entry.isDirectory()) walk(abs, rel);
|
|
23
|
+
else out.push(rel);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
walk(src);
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Only remove files that also exist in the ECC package.
|
|
31
|
+
// Preserves user-authored files in the same directory.
|
|
32
|
+
function removeInstalledFiles(destDir, shipped) {
|
|
33
|
+
if (!fs.existsSync(destDir)) return { removed: 0, skipped: 0 };
|
|
34
|
+
let removed = 0, skipped = 0;
|
|
35
|
+
for (const rel of shipped) {
|
|
36
|
+
const abs = path.join(destDir, rel);
|
|
37
|
+
if (fs.existsSync(abs)) {
|
|
38
|
+
try { fs.unlinkSync(abs); removed++; } catch { skipped++; }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Clean up now-empty ECC-owned directories.
|
|
42
|
+
const dirs = new Set(shipped.map(f => path.dirname(f)).filter(d => d !== '.'));
|
|
43
|
+
for (const rel of [...dirs].sort((a, b) => b.length - a.length)) {
|
|
44
|
+
const abs = path.join(destDir, rel);
|
|
45
|
+
try {
|
|
46
|
+
if (fs.existsSync(abs) && fs.readdirSync(abs).length === 0) fs.rmdirSync(abs);
|
|
47
|
+
} catch { /* keep going */ }
|
|
48
|
+
}
|
|
49
|
+
return { removed, skipped };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function rmrf(dir) {
|
|
53
|
+
try { fs.rmSync(dir, { recursive: true, force: true }); return true; }
|
|
54
|
+
catch { return false; }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ── The uninstall plan (dry-run friendly) ──────────────────────────────────
|
|
58
|
+
function plan(ROOT) {
|
|
59
|
+
const home = os.homedir();
|
|
60
|
+
const claudeDir = path.join(home, '.claude');
|
|
61
|
+
const shipped = {
|
|
62
|
+
agents: listShippedFiles(ROOT, 'agents'),
|
|
63
|
+
skills: listShippedFiles(ROOT, 'skills'),
|
|
64
|
+
commands: listShippedFiles(ROOT, 'commands'),
|
|
65
|
+
hooks: listShippedFiles(ROOT, 'hooks'),
|
|
66
|
+
rules: listShippedFiles(ROOT, 'rules'),
|
|
67
|
+
scripts: listShippedFiles(ROOT, 'scripts'),
|
|
68
|
+
};
|
|
69
|
+
const dests = {
|
|
70
|
+
agents: path.join(claudeDir, 'agents'),
|
|
71
|
+
skills: path.join(claudeDir, 'skills'),
|
|
72
|
+
commands: path.join(claudeDir, 'commands'),
|
|
73
|
+
hooks: path.join(claudeDir, 'hooks'),
|
|
74
|
+
rules: path.join(claudeDir, 'rules'),
|
|
75
|
+
scripts: path.join(claudeDir, 'scripts'),
|
|
76
|
+
};
|
|
77
|
+
return { home, claudeDir, shipped, dests };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ── Run the uninstall ──────────────────────────────────────────────────────
|
|
81
|
+
function run({ log = () => {}, keepMemory = false, dryRun = false } = {}) {
|
|
82
|
+
const ROOT = path.join(__dirname, '..', '..');
|
|
83
|
+
const p = plan(ROOT);
|
|
84
|
+
const results = { removed_files: 0, dirs_removed: [], subsystems_uninstalled: [], errors: [] };
|
|
85
|
+
|
|
86
|
+
log('Removing ECC-installed files from ~/.claude/ …');
|
|
87
|
+
for (const kind of Object.keys(p.shipped)) {
|
|
88
|
+
if (dryRun) {
|
|
89
|
+
log(` [dry-run] would remove ${p.shipped[kind].length} ${kind} files from ${p.dests[kind]}`);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const r = removeInstalledFiles(p.dests[kind], p.shipped[kind]);
|
|
93
|
+
results.removed_files += r.removed;
|
|
94
|
+
log(` ${kind}: removed ${r.removed} files (${r.skipped} skipped)`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Remove ECC's own MCP entries from Claude Code / Claude Desktop configs.
|
|
98
|
+
try {
|
|
99
|
+
const reg = require('../mcp/register-self.js');
|
|
100
|
+
if (!dryRun) reg.unregisterAll({ log: (m) => log(' ' + m) });
|
|
101
|
+
else log(' [dry-run] would unregister kodelyth-ecc MCP server from Claude Code + Desktop');
|
|
102
|
+
results.subsystems_uninstalled.push('mcp-registration');
|
|
103
|
+
} catch (e) { results.errors.push('mcp-unregister: ' + e.message); }
|
|
104
|
+
|
|
105
|
+
// Remove RTK integration (uses their own uninstall flag).
|
|
106
|
+
try {
|
|
107
|
+
log('Unwiring RTK integrations …');
|
|
108
|
+
if (!dryRun) {
|
|
109
|
+
const r = spawnSync('rtk', ['init', '-g', '--uninstall'], { encoding: 'utf8' });
|
|
110
|
+
log(r.status === 0 ? ' ✓ rtk uninstalled from claude-code' : ' · rtk uninstall skipped (may not be present)');
|
|
111
|
+
}
|
|
112
|
+
results.subsystems_uninstalled.push('rtk');
|
|
113
|
+
} catch (e) { results.errors.push('rtk: ' + e.message); }
|
|
114
|
+
|
|
115
|
+
// Remove codebase-memory-mcp registration (their own uninstall).
|
|
116
|
+
try {
|
|
117
|
+
log('Uninstalling codebase-memory-mcp agent configs …');
|
|
118
|
+
if (!dryRun) {
|
|
119
|
+
const r = spawnSync('codebase-memory-mcp', ['uninstall'], { encoding: 'utf8' });
|
|
120
|
+
log(r.status === 0 ? ' ✓ codebase-memory-mcp configs removed' : ' · codebase-memory-mcp uninstall skipped (binary not present)');
|
|
121
|
+
}
|
|
122
|
+
results.subsystems_uninstalled.push('codebase-memory-mcp');
|
|
123
|
+
} catch (e) { results.errors.push('codebase-memory-mcp: ' + e.message); }
|
|
124
|
+
|
|
125
|
+
// Remove memory + ledgers.
|
|
126
|
+
if (!keepMemory) {
|
|
127
|
+
log(`${dryRun ? '[dry-run] would remove' : 'Removing'} ~/.kodelythecc/ (memory, ledgers, cache) …`);
|
|
128
|
+
const target = path.join(p.home, '.kodelythecc');
|
|
129
|
+
if (!dryRun && rmrf(target)) results.dirs_removed.push(target);
|
|
130
|
+
} else {
|
|
131
|
+
log('Keeping ~/.kodelythecc/ (memory preserved as requested)');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Remove legacy migration backup if present.
|
|
135
|
+
try {
|
|
136
|
+
for (const name of fs.readdirSync(p.home)) {
|
|
137
|
+
if (name.startsWith('.kodelyth.backup-')) {
|
|
138
|
+
const abs = path.join(p.home, name);
|
|
139
|
+
if (dryRun) log(` [dry-run] would remove backup ${abs}`);
|
|
140
|
+
else { rmrf(abs); results.dirs_removed.push(abs); }
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} catch { /* home dir listing failed — skip */ }
|
|
144
|
+
|
|
145
|
+
return results;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
module.exports = { plan, run };
|
|
@@ -86,6 +86,21 @@ function dashboardSnapshot() {
|
|
|
86
86
|
const st = status();
|
|
87
87
|
if (!st.installed) return { ok: false, installed: false, install_hint: 'Run: kodelyth-ecc codebase install' };
|
|
88
88
|
const out = { ok: true, installed: true, version: st.version, indexed_projects: st.indexed_projects, cache_dir: st.cache_dir };
|
|
89
|
+
// Try to list projects with names — richer than just a count.
|
|
90
|
+
try {
|
|
91
|
+
const list = query('list_projects', '{}');
|
|
92
|
+
if (Array.isArray(list)) {
|
|
93
|
+
out.projects = list.slice(0, 20).map(p => ({
|
|
94
|
+
name: p.name || p.path || p.project || 'unnamed',
|
|
95
|
+
path: p.path || null,
|
|
96
|
+
nodes: p.node_count ?? p.nodes ?? null,
|
|
97
|
+
edges: p.edge_count ?? p.edges ?? null,
|
|
98
|
+
}));
|
|
99
|
+
} else if (list && Array.isArray(list.projects)) {
|
|
100
|
+
out.projects = list.projects.slice(0, 20);
|
|
101
|
+
}
|
|
102
|
+
} catch { /* older binaries may not support list_projects */ }
|
|
103
|
+
// Try architecture snapshot for whichever project is 'active'.
|
|
89
104
|
try {
|
|
90
105
|
const arch = query('get_architecture', '{}');
|
|
91
106
|
if (arch && typeof arch === 'object') {
|
|
@@ -96,7 +111,7 @@ function dashboardSnapshot() {
|
|
|
96
111
|
entry_points: (arch.entry_points || []).slice(0, 5),
|
|
97
112
|
};
|
|
98
113
|
}
|
|
99
|
-
} catch { /* no active project yet */ }
|
|
114
|
+
} catch { /* no active project yet — dashboard shows CTA */ }
|
|
100
115
|
return out;
|
|
101
116
|
}
|
|
102
117
|
|
|
@@ -813,6 +813,16 @@ kodelyth-ecc codebase query detect_changes '{}'</pre>
|
|
|
813
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
814
|
</tbody>
|
|
815
815
|
</table>`;
|
|
816
|
+
} else if ((r.projects || []).length) {
|
|
817
|
+
$('#codebaseArch').innerHTML = `<div class="muted" style="font-size:13px;">
|
|
818
|
+
${(r.projects || []).length} project(s) indexed. Architecture snapshot is per-active-session — open a project in your AI tool and it appears here.
|
|
819
|
+
</div><table style="margin-top:10px;">
|
|
820
|
+
<thead><tr><th>Project</th><th style="text-align:right;">Nodes</th><th style="text-align:right;">Edges</th></tr></thead>
|
|
821
|
+
<tbody>${r.projects.map(p => `<tr>
|
|
822
|
+
<td><code style="font-size:11.5px;">${escapeHtml(p.name)}</code></td>
|
|
823
|
+
<td style="text-align:right;">${fmtN(p.nodes || 0)}</td>
|
|
824
|
+
<td style="text-align:right;">${fmtN(p.edges || 0)}</td>
|
|
825
|
+
</tr>`).join('')}</tbody></table>`;
|
|
816
826
|
} else {
|
|
817
827
|
$('#codebaseArch').innerHTML = '<div class="empty">no active project graph yet — open a repo in your AI tool and say "Index this project"</div>';
|
|
818
828
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// scripts/mcp/register-self.js
|
|
2
|
+
// Auto-register ECC's own MCP server in Claude Code (~/.claude.json) and
|
|
3
|
+
// Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json).
|
|
4
|
+
//
|
|
5
|
+
// Idempotent — updates in place, never duplicates. Handles missing files.
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
const SERVER_NAME = 'kodelyth-ecc';
|
|
14
|
+
|
|
15
|
+
function claudeCodeConfigPath() {
|
|
16
|
+
// Claude Code reads user-level MCP from ~/.claude.json
|
|
17
|
+
return path.join(os.homedir(), '.claude.json');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function claudeDesktopConfigPath() {
|
|
21
|
+
const home = os.homedir();
|
|
22
|
+
if (os.platform() === 'darwin') return path.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
23
|
+
if (os.platform() === 'win32') return path.join(process.env.APPDATA || '', 'Claude', 'claude_desktop_config.json');
|
|
24
|
+
return path.join(home, '.config', 'Claude', 'claude_desktop_config.json');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function readJson(file) {
|
|
28
|
+
try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch { return null; }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function writeJson(file, obj) {
|
|
32
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
33
|
+
fs.writeFileSync(file, JSON.stringify(obj, null, 2));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function serverEntry() {
|
|
37
|
+
return {
|
|
38
|
+
command: 'kodelythecc',
|
|
39
|
+
args: ['mcp'],
|
|
40
|
+
env: {},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function registerInFile(file, opts = {}) {
|
|
45
|
+
const existing = readJson(file) || {};
|
|
46
|
+
const servers = existing.mcpServers || {};
|
|
47
|
+
const already = servers[SERVER_NAME];
|
|
48
|
+
const desired = serverEntry();
|
|
49
|
+
if (already && JSON.stringify(already) === JSON.stringify(desired)) {
|
|
50
|
+
return { file, action: 'unchanged' };
|
|
51
|
+
}
|
|
52
|
+
servers[SERVER_NAME] = desired;
|
|
53
|
+
const next = { ...existing, mcpServers: servers };
|
|
54
|
+
if (!opts.dryRun) writeJson(file, next);
|
|
55
|
+
return { file, action: already ? 'updated' : 'added' };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function unregisterInFile(file) {
|
|
59
|
+
const existing = readJson(file);
|
|
60
|
+
if (!existing || !existing.mcpServers || !existing.mcpServers[SERVER_NAME]) {
|
|
61
|
+
return { file, action: 'not-present' };
|
|
62
|
+
}
|
|
63
|
+
delete existing.mcpServers[SERVER_NAME];
|
|
64
|
+
writeJson(file, existing);
|
|
65
|
+
return { file, action: 'removed' };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function registerAll({ log = () => {} } = {}) {
|
|
69
|
+
const results = [];
|
|
70
|
+
for (const p of [claudeCodeConfigPath(), claudeDesktopConfigPath()]) {
|
|
71
|
+
try {
|
|
72
|
+
const r = registerInFile(p);
|
|
73
|
+
log(` ${r.action}: ${r.file}`);
|
|
74
|
+
results.push(r);
|
|
75
|
+
} catch (e) {
|
|
76
|
+
log(` skipped ${p}: ${e.message}`);
|
|
77
|
+
results.push({ file: p, action: 'error', error: e.message });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return results;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function unregisterAll({ log = () => {} } = {}) {
|
|
84
|
+
const results = [];
|
|
85
|
+
for (const p of [claudeCodeConfigPath(), claudeDesktopConfigPath()]) {
|
|
86
|
+
try {
|
|
87
|
+
const r = unregisterInFile(p);
|
|
88
|
+
log(` ${r.action}: ${r.file}`);
|
|
89
|
+
results.push(r);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
log(` skipped ${p}: ${e.message}`);
|
|
92
|
+
results.push({ file: p, action: 'error', error: e.message });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return results;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function statusAll() {
|
|
99
|
+
const rows = [];
|
|
100
|
+
for (const p of [claudeCodeConfigPath(), claudeDesktopConfigPath()]) {
|
|
101
|
+
const cfg = readJson(p);
|
|
102
|
+
const present = !!(cfg && cfg.mcpServers && cfg.mcpServers[SERVER_NAME]);
|
|
103
|
+
rows.push({ file: p, present, exists: !!cfg });
|
|
104
|
+
}
|
|
105
|
+
return rows;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = {
|
|
109
|
+
SERVER_NAME,
|
|
110
|
+
serverEntry,
|
|
111
|
+
claudeCodeConfigPath,
|
|
112
|
+
claudeDesktopConfigPath,
|
|
113
|
+
registerAll,
|
|
114
|
+
unregisterAll,
|
|
115
|
+
statusAll,
|
|
116
|
+
};
|