kodelyth-ecc 1.5.9 → 1.7.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/.github/workflows/publish.yml +19 -0
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +455 -0
- package/CLAUDE.md +48 -16
- package/README.md +265 -81
- package/VERSION +1 -1
- package/actions/ecc-review/README.md +243 -0
- package/actions/ecc-review/action.yml +158 -0
- package/actions/ecc-review/post-comment.js +171 -0
- package/actions/ecc-review/run-review.js +285 -0
- package/agents/backdoor-hunter.md +260 -0
- package/agents/chaos-engineer.md +251 -0
- package/agents/code-stealer-detector.md +228 -0
- package/agents/jailbreak-tester.md +222 -0
- package/agents/license-violation-finder.md +212 -0
- package/agents/prompt-injection-hunter.md +126 -0
- package/agents/secret-hunter.md +209 -0
- package/agents/supply-chain-auditor.md +195 -0
- package/bin/kodelyth-ecc.js +875 -1
- package/bundles/enterprise.md +172 -0
- package/bundles/indie-hacker.md +106 -0
- package/bundles/red-team.md +138 -0
- package/cat +0 -0
- package/commands/dashboard.md +67 -0
- package/commands/devil-mode.md +121 -0
- package/commands/memory-evolve.md +71 -0
- package/commands/replay.md +61 -0
- package/commands/route-model.md +48 -0
- package/commands/swarm.md +68 -0
- package/commands/verify-supply-chain.md +59 -0
- package/docs/dashboard.md +211 -0
- package/docs/evolve.md +303 -0
- package/docs/mcp-clients.md +167 -0
- package/docs/mcp.md +178 -0
- package/docs/replay.md +244 -0
- package/docs/supply-chain.md +207 -0
- package/docs/swarm.md +243 -0
- package/hooks/hooks.json +52 -0
- package/hooks/memory/auto-recall.js +29 -1
- package/hooks/safety/README.md +124 -0
- package/hooks/safety/lib/patterns.js +179 -0
- package/hooks/safety/prompt-injection-guard.js +179 -0
- package/hooks/safety/token-budget.js +229 -0
- package/install.ps1 +199 -2
- package/install.sh +286 -4
- package/package.json +30 -4
- package/rules/common/agent-intent-routing.md +182 -0
- package/rules/common/cost-aware-model-routing.md +152 -0
- package/scripts/dashboard/data.js +353 -0
- package/scripts/dashboard/server.js +324 -0
- package/scripts/dashboard/static/index.html +645 -0
- package/scripts/evolve/analyze.js +303 -0
- package/scripts/evolve/proposals.js +162 -0
- package/scripts/evolve/stats.js +219 -0
- package/scripts/mcp/catalog.js +244 -0
- package/scripts/mcp/client.js +181 -0
- package/scripts/mcp/prompts.js +133 -0
- package/scripts/mcp/resources.js +94 -0
- package/scripts/mcp/server.js +153 -0
- package/scripts/mcp/tools.js +465 -0
- package/scripts/replay/bundle.js +191 -0
- package/scripts/replay/replay.js +107 -0
- package/scripts/router/classify.js +232 -0
- package/scripts/supply-chain/manifest.js +154 -0
- package/scripts/supply-chain/sbom.js +202 -0
- package/scripts/supply-chain/verify.js +102 -0
- package/scripts/swarm/build-plan.js +193 -0
- package/skills/cost-aware-model-routing/SKILL.md +153 -0
- package/skills/kodelyth-quickstart/SKILL.md +7 -0
- package/skills/observability-dashboard/SKILL.md +119 -0
- package/skills/self-evolving-memory/SKILL.md +175 -0
- package/skills/session-replay/SKILL.md +199 -0
- package/skills/supply-chain-verification/SKILL.md +201 -0
- package/skills/swarm-orchestrator/SKILL.md +177 -0
- package/social/card-install.svg +1 -1
- package/social/facebook-group/POST.md +121 -0
- package/social/facebook-group/fb-1-3am-debug.png +0 -0
- package/social/facebook-group/fb-1-3am-debug.svg +97 -0
- package/social/facebook-group/fb-2-cpu-upgrade.png +0 -0
- package/social/facebook-group/fb-2-cpu-upgrade.svg +132 -0
- package/social/facebook-group/fb-3-before-after.png +0 -0
- package/social/facebook-group/fb-3-before-after.svg +94 -0
- package/social/facebook-v150.svg +5 -5
- package/social/github-social-preview.svg +119 -100
- package/social/readme-hero.svg +11 -11
- package/social/section-agents.svg +57 -0
- package/social/section-author.svg +54 -0
- package/social/section-dashboard.svg +59 -0
- package/social/section-devil.svg +54 -0
- package/social/section-hooks.svg +51 -0
- package/social/section-install.svg +42 -0
- package/social/section-learning.svg +52 -0
- package/social/section-mcp.svg +46 -0
- package/social/section-memory.svg +57 -0
- package/social/section-parallel.svg +72 -0
- package/social/section-routing.svg +51 -0
- package/social/x-card-agents-grid.svg +6 -6
- package/tests/dashboard/data.test.js +235 -0
- package/tests/dashboard/server.test.js +240 -0
- package/tests/evolve/analyze.test.js +169 -0
- package/tests/evolve/proposals.test.js +173 -0
- package/tests/evolve/stats.test.js +159 -0
- package/tests/mcp/catalog.test.js +98 -0
- package/tests/mcp/client.test.js +109 -0
- package/tests/mcp/resources-prompts.test.js +70 -0
- package/tests/mcp/tools.test.js +159 -0
- package/tests/replay/bundle.test.js +181 -0
- package/tests/replay/replay.test.js +131 -0
- package/tests/router/classify.test.js +164 -0
- package/tests/safety/patterns.test.js +94 -0
- package/tests/safety/prompt-injection-guard.test.js +111 -0
- package/tests/safety/token-budget.test.js +119 -0
- package/tests/supply-chain/manifest.test.js +147 -0
- package/tests/supply-chain/sbom.test.js +170 -0
- package/tests/supply-chain/verify.test.js +146 -0
- package/tests/swarm/build-plan.test.js +188 -0
- package/wiki/Agent-Reference.md +58 -7
- package/wiki/FAQ.md +204 -7
- package/wiki/Home.md +104 -28
- package/wiki/Hook-Reference.md +1 -1
- package/wiki/Installation-Guide.md +109 -6
- package/wiki/Platform-Support.md +239 -25
- package/wiki/Skill-Reference.md +101 -6
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// =============================================================================
|
|
3
|
+
// Kodelyth ECC — Token Budget Enforcer
|
|
4
|
+
//
|
|
5
|
+
// A safety hook that tracks per-session token usage and blocks new turns once
|
|
6
|
+
// a configurable budget is exceeded. Wires into:
|
|
7
|
+
//
|
|
8
|
+
// - Stop (after each AI response — accumulate usage, write state)
|
|
9
|
+
// - SessionStart (before each new turn — block if budget already exhausted)
|
|
10
|
+
//
|
|
11
|
+
// Token estimation:
|
|
12
|
+
// Hooks don't get authoritative token counts from the platform, so we use
|
|
13
|
+
// a 4-chars-per-token heuristic over the visible transcript path supplied
|
|
14
|
+
// in the Stop payload (transcript_path). On UserPromptSubmit we also count
|
|
15
|
+
// the user message; on PostToolUse we count the tool response.
|
|
16
|
+
//
|
|
17
|
+
// Modes (env var KODELYTH_TOKEN_BUDGET):
|
|
18
|
+
// off — never run (default if unset)
|
|
19
|
+
// warn — exit 0; write usage to stderr; never block
|
|
20
|
+
// <number> — hard budget in tokens (e.g. 200000). Warns at WARN_AT_PCT.
|
|
21
|
+
// Blocks SessionStart once usage >= budget.
|
|
22
|
+
//
|
|
23
|
+
// Optional knobs:
|
|
24
|
+
// KODELYTH_TOKEN_BUDGET_DIR=/custom/path default ~/.kodelyth/safety
|
|
25
|
+
// KODELYTH_TOKEN_BUDGET_WARN=0.7 warn threshold (0-1, default 0.7)
|
|
26
|
+
// KODELYTH_TOKEN_BUDGET_RESET=1 wipe usage and exit (admin op)
|
|
27
|
+
//
|
|
28
|
+
// Always exits 0 on internal errors so the hook never blocks accidentally.
|
|
29
|
+
// =============================================================================
|
|
30
|
+
|
|
31
|
+
'use strict';
|
|
32
|
+
|
|
33
|
+
const fs = require('fs');
|
|
34
|
+
const os = require('os');
|
|
35
|
+
const path = require('path');
|
|
36
|
+
|
|
37
|
+
const RAW_BUDGET = String(process.env.KODELYTH_TOKEN_BUDGET || 'off').toLowerCase();
|
|
38
|
+
const WARN_PCT = Math.max(0, Math.min(1, Number(process.env.KODELYTH_TOKEN_BUDGET_WARN) || 0.7));
|
|
39
|
+
const RESET = !!process.env.KODELYTH_TOKEN_BUDGET_RESET;
|
|
40
|
+
|
|
41
|
+
const STATE_DIR = process.env.KODELYTH_TOKEN_BUDGET_DIR
|
|
42
|
+
|| path.join(os.homedir(), '.kodelyth', 'safety');
|
|
43
|
+
|
|
44
|
+
function safeExit(code) {
|
|
45
|
+
try { process.stdout.write(''); } catch {}
|
|
46
|
+
process.exit(code);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function readStdinSync() {
|
|
50
|
+
try {
|
|
51
|
+
const chunks = [];
|
|
52
|
+
const tmp = Buffer.alloc(64 * 1024);
|
|
53
|
+
while (true) {
|
|
54
|
+
let n;
|
|
55
|
+
try { n = fs.readSync(0, tmp, 0, tmp.length, null); }
|
|
56
|
+
catch { break; }
|
|
57
|
+
if (!n) break;
|
|
58
|
+
chunks.push(Buffer.from(tmp.subarray(0, n)));
|
|
59
|
+
}
|
|
60
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
61
|
+
} catch {
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function loadState(sessionId) {
|
|
67
|
+
try {
|
|
68
|
+
const file = path.join(STATE_DIR, `budget-${sessionId}.json`);
|
|
69
|
+
if (!fs.existsSync(file)) return { tokens: 0, turns: 0 };
|
|
70
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
71
|
+
} catch {
|
|
72
|
+
return { tokens: 0, turns: 0 };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function saveState(sessionId, state) {
|
|
77
|
+
try {
|
|
78
|
+
fs.mkdirSync(STATE_DIR, { recursive: true });
|
|
79
|
+
const file = path.join(STATE_DIR, `budget-${sessionId}.json`);
|
|
80
|
+
fs.writeFileSync(file, JSON.stringify(state, null, 2));
|
|
81
|
+
} catch { /* never block on persistence */ }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function resetState(sessionId) {
|
|
85
|
+
try {
|
|
86
|
+
const file = path.join(STATE_DIR, `budget-${sessionId}.json`);
|
|
87
|
+
if (fs.existsSync(file)) fs.unlinkSync(file);
|
|
88
|
+
} catch {}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── Token estimation ─────────────────────────────────────────────────────────
|
|
92
|
+
// Rough heuristic — 1 token ≈ 4 characters. Good enough for budget guards.
|
|
93
|
+
function estimateTokensFromChars(s) {
|
|
94
|
+
if (typeof s !== 'string' || !s) return 0;
|
|
95
|
+
return Math.ceil(s.length / 4);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function estimateTokensFromTranscript(transcriptPath) {
|
|
99
|
+
if (!transcriptPath || typeof transcriptPath !== 'string') return 0;
|
|
100
|
+
try {
|
|
101
|
+
if (!fs.existsSync(transcriptPath)) return 0;
|
|
102
|
+
const stat = fs.statSync(transcriptPath);
|
|
103
|
+
// Each transcript line is JSON with `text` fields. We approximate by
|
|
104
|
+
// file size (proxy for transcript length); rough but stable.
|
|
105
|
+
return Math.ceil(stat.size / 4);
|
|
106
|
+
} catch {
|
|
107
|
+
return 0;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function parseBudget() {
|
|
112
|
+
if (RAW_BUDGET === 'off') return { mode: 'off', limit: 0 };
|
|
113
|
+
if (RAW_BUDGET === 'warn') return { mode: 'warn', limit: 0 };
|
|
114
|
+
const n = Number(RAW_BUDGET);
|
|
115
|
+
if (Number.isFinite(n) && n > 0) return { mode: 'block', limit: Math.floor(n) };
|
|
116
|
+
return { mode: 'off', limit: 0 };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ── Main ─────────────────────────────────────────────────────────────────────
|
|
120
|
+
function main() {
|
|
121
|
+
const cfg = parseBudget();
|
|
122
|
+
if (cfg.mode === 'off') return safeExit(0);
|
|
123
|
+
|
|
124
|
+
let raw = '';
|
|
125
|
+
try { raw = readStdinSync(); } catch { return safeExit(0); }
|
|
126
|
+
|
|
127
|
+
let payload = null;
|
|
128
|
+
try { payload = raw ? JSON.parse(raw) : null; } catch { payload = null; }
|
|
129
|
+
|
|
130
|
+
// Echo stdin so chained hooks still see it.
|
|
131
|
+
if (raw) process.stdout.write(raw);
|
|
132
|
+
if (!payload) return safeExit(0);
|
|
133
|
+
|
|
134
|
+
const sessionId =
|
|
135
|
+
payload.session_id ||
|
|
136
|
+
payload.sessionId ||
|
|
137
|
+
process.env.CLAUDE_SESSION_ID ||
|
|
138
|
+
'default';
|
|
139
|
+
|
|
140
|
+
if (RESET) {
|
|
141
|
+
resetState(sessionId);
|
|
142
|
+
process.stderr.write(`[Kodelyth Safety] token-budget reset for session ${sessionId}\n`);
|
|
143
|
+
return safeExit(0);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const event = payload.hook_event_name || '';
|
|
147
|
+
|
|
148
|
+
// ── SessionStart: pre-check, block if already over ─────────────────────────
|
|
149
|
+
if (/SessionStart/i.test(event)) {
|
|
150
|
+
const state = loadState(sessionId);
|
|
151
|
+
if (cfg.mode === 'block' && state.tokens >= cfg.limit) {
|
|
152
|
+
process.stderr.write(
|
|
153
|
+
`\n[Kodelyth Safety] BLOCKED — session token budget exhausted.\n` +
|
|
154
|
+
` session=${sessionId}\n` +
|
|
155
|
+
` used=${state.tokens.toLocaleString()} tokens\n` +
|
|
156
|
+
` budget=${cfg.limit.toLocaleString()} tokens\n` +
|
|
157
|
+
` • Reset with KODELYTH_TOKEN_BUDGET_RESET=1.\n` +
|
|
158
|
+
` • Raise budget via KODELYTH_TOKEN_BUDGET=<larger number>.\n` +
|
|
159
|
+
` • Disable entirely via KODELYTH_TOKEN_BUDGET=off.\n\n`
|
|
160
|
+
);
|
|
161
|
+
return safeExit(2);
|
|
162
|
+
}
|
|
163
|
+
if (cfg.mode === 'warn' || cfg.mode === 'block') {
|
|
164
|
+
process.stderr.write(
|
|
165
|
+
`[Kodelyth Safety] token-budget — session=${sessionId} ` +
|
|
166
|
+
`used=${state.tokens.toLocaleString()} ` +
|
|
167
|
+
(cfg.mode === 'block' ? `budget=${cfg.limit.toLocaleString()}` : '(warn-only)') +
|
|
168
|
+
`\n`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return safeExit(0);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ── Stop: accumulate usage from transcript path ────────────────────────────
|
|
175
|
+
if (/Stop/i.test(event) || event === 'PostToolUse' || event === 'UserPromptSubmit' || event === '') {
|
|
176
|
+
const state = loadState(sessionId);
|
|
177
|
+
let added = 0;
|
|
178
|
+
if (typeof payload.prompt === 'string') added += estimateTokensFromChars(payload.prompt);
|
|
179
|
+
if (typeof payload.user_message === 'string') added += estimateTokensFromChars(payload.user_message);
|
|
180
|
+
if (typeof payload.message === 'string') added += estimateTokensFromChars(payload.message);
|
|
181
|
+
if (payload.transcript_path) added = Math.max(added, estimateTokensFromTranscript(payload.transcript_path));
|
|
182
|
+
if (payload.tool_response) {
|
|
183
|
+
try { added += estimateTokensFromChars(JSON.stringify(payload.tool_response)); } catch {}
|
|
184
|
+
}
|
|
185
|
+
if (added > 0) {
|
|
186
|
+
state.tokens = (state.tokens || 0) + added;
|
|
187
|
+
state.turns = (state.turns || 0) + 1;
|
|
188
|
+
state.last_updated = new Date().toISOString();
|
|
189
|
+
saveState(sessionId, state);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (cfg.mode === 'block') {
|
|
193
|
+
const pct = state.tokens / cfg.limit;
|
|
194
|
+
if (pct >= 1) {
|
|
195
|
+
process.stderr.write(
|
|
196
|
+
`\n[Kodelyth Safety] token-budget EXCEEDED — ` +
|
|
197
|
+
`used=${state.tokens.toLocaleString()} budget=${cfg.limit.toLocaleString()}. ` +
|
|
198
|
+
`Next SessionStart will be blocked. Use KODELYTH_TOKEN_BUDGET_RESET=1 to clear.\n`
|
|
199
|
+
);
|
|
200
|
+
} else if (pct >= WARN_PCT) {
|
|
201
|
+
process.stderr.write(
|
|
202
|
+
`[Kodelyth Safety] token-budget at ${(pct * 100).toFixed(0)}% — ` +
|
|
203
|
+
`used=${state.tokens.toLocaleString()} budget=${cfg.limit.toLocaleString()}\n`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
process.stderr.write(
|
|
208
|
+
`[Kodelyth Safety] token-budget (warn) — session=${sessionId} ` +
|
|
209
|
+
`used=${state.tokens.toLocaleString()} added=${added.toLocaleString()}\n`
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return safeExit(0);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (require.main === module) {
|
|
218
|
+
try { main(); } catch { safeExit(0); }
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
module.exports = {
|
|
222
|
+
// Exposed for tests
|
|
223
|
+
estimateTokensFromChars,
|
|
224
|
+
estimateTokensFromTranscript,
|
|
225
|
+
parseBudget,
|
|
226
|
+
loadState,
|
|
227
|
+
saveState,
|
|
228
|
+
resetState,
|
|
229
|
+
};
|
package/install.ps1
CHANGED
|
@@ -13,15 +13,42 @@
|
|
|
13
13
|
|
|
14
14
|
param(
|
|
15
15
|
[string]$Target = "claude-home",
|
|
16
|
+
[string]$Bundle = "",
|
|
16
17
|
[string[]]$Languages = @()
|
|
17
18
|
)
|
|
18
19
|
|
|
19
20
|
$ErrorActionPreference = "Stop"
|
|
20
21
|
|
|
22
|
+
# ── Bundle handling (audience-tailored cheat sheets) ─────────────────────────
|
|
23
|
+
if ($Bundle) {
|
|
24
|
+
switch ($Bundle.ToLower()) {
|
|
25
|
+
{ $_ -in "indie-hacker","indie" } {
|
|
26
|
+
$Bundle = "indie-hacker"
|
|
27
|
+
$Languages += @("typescript","python")
|
|
28
|
+
Write-Host "Bundle: Indie Hacker -> ship-fast workflow + TS/Python" -ForegroundColor Cyan
|
|
29
|
+
}
|
|
30
|
+
{ $_ -in "red-team","redteam","security" } {
|
|
31
|
+
$Bundle = "red-team"
|
|
32
|
+
$Languages += @("typescript","python")
|
|
33
|
+
Write-Host "Bundle: Red Team -> adversarial mindset + devil-mode crew" -ForegroundColor Cyan
|
|
34
|
+
}
|
|
35
|
+
{ $_ -in "enterprise","compliance" } {
|
|
36
|
+
$Bundle = "enterprise"
|
|
37
|
+
$Languages += @("typescript","java","python")
|
|
38
|
+
Write-Host "Bundle: Enterprise -> compliance + audit + supply chain" -ForegroundColor Cyan
|
|
39
|
+
}
|
|
40
|
+
default {
|
|
41
|
+
Write-Host "Unknown bundle: $Bundle" -ForegroundColor Red
|
|
42
|
+
Write-Host "Available bundles: indie-hacker, red-team, enterprise"
|
|
43
|
+
exit 1
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
21
48
|
# ── Banner ────────────────────────────────────────────────────────────────────
|
|
22
49
|
Write-Host ""
|
|
23
50
|
Write-Host " Kodelyth ECC — Production-grade AI coding agent toolkit" -ForegroundColor Cyan
|
|
24
|
-
Write-Host "
|
|
51
|
+
Write-Host " 70 agents (8 devil-mode) · 194 skills · 97 commands · 22+ hooks · intent routing · local memory" -ForegroundColor Gray
|
|
25
52
|
Write-Host ""
|
|
26
53
|
|
|
27
54
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
@@ -86,9 +113,57 @@ switch ($Target) {
|
|
|
86
113
|
$HooksDest = ""
|
|
87
114
|
$RulesDest = "$Dest\rules"
|
|
88
115
|
}
|
|
116
|
+
"cline" {
|
|
117
|
+
$Dest = "$(Get-Location)\.clinerules"
|
|
118
|
+
$AgentsDest = ""
|
|
119
|
+
$SkillsDest = ""
|
|
120
|
+
$CommandsDest = ""
|
|
121
|
+
$HooksDest = ""
|
|
122
|
+
$RulesDest = $Dest
|
|
123
|
+
}
|
|
124
|
+
"roocode" {
|
|
125
|
+
$Dest = "$(Get-Location)\.roo"
|
|
126
|
+
$AgentsDest = "$Dest\agents"
|
|
127
|
+
$SkillsDest = "$Dest\skills"
|
|
128
|
+
$CommandsDest = "$Dest\commands"
|
|
129
|
+
$HooksDest = ""
|
|
130
|
+
$RulesDest = "$Dest\rules"
|
|
131
|
+
}
|
|
132
|
+
"aider" {
|
|
133
|
+
$Dest = "$(Get-Location)\.aider-ecc"
|
|
134
|
+
$AgentsDest = "$Dest\agents"
|
|
135
|
+
$SkillsDest = "$Dest\skills"
|
|
136
|
+
$CommandsDest = "$Dest\commands"
|
|
137
|
+
$HooksDest = ""
|
|
138
|
+
$RulesDest = "$Dest\rules"
|
|
139
|
+
}
|
|
140
|
+
"kimi" {
|
|
141
|
+
$Dest = "$(Get-Location)\.kimi"
|
|
142
|
+
$AgentsDest = "$Dest\agents"
|
|
143
|
+
$SkillsDest = "$Dest\skills"
|
|
144
|
+
$CommandsDest = "$Dest\commands"
|
|
145
|
+
$HooksDest = ""
|
|
146
|
+
$RulesDest = "$Dest\rules"
|
|
147
|
+
}
|
|
148
|
+
"gemini-project" {
|
|
149
|
+
$Dest = "$(Get-Location)\.gemini"
|
|
150
|
+
$AgentsDest = "$Dest\agents"
|
|
151
|
+
$SkillsDest = "$Dest\skills"
|
|
152
|
+
$CommandsDest = ""
|
|
153
|
+
$HooksDest = ""
|
|
154
|
+
$RulesDest = "$Dest\rules"
|
|
155
|
+
}
|
|
156
|
+
"gemini-home" {
|
|
157
|
+
$Dest = "$HomeDir\.gemini"
|
|
158
|
+
$AgentsDest = "$Dest\agents"
|
|
159
|
+
$SkillsDest = "$Dest\skills"
|
|
160
|
+
$CommandsDest = ""
|
|
161
|
+
$HooksDest = ""
|
|
162
|
+
$RulesDest = "$Dest\rules"
|
|
163
|
+
}
|
|
89
164
|
default {
|
|
90
165
|
Write-Host "Unknown target: $Target" -ForegroundColor Red
|
|
91
|
-
Write-Host "Valid targets: claude-home, windsurf-project, windsurf-home, antigravity, cursor-project, codex-home, opencode"
|
|
166
|
+
Write-Host "Valid targets: claude-home, windsurf-project, windsurf-home, antigravity, cursor-project, codex-home, opencode, cline, roocode, aider, kimi, gemini-project, gemini-home"
|
|
92
167
|
exit 1
|
|
93
168
|
}
|
|
94
169
|
}
|
|
@@ -198,6 +273,80 @@ switch ($Target) {
|
|
|
198
273
|
"opencode" {
|
|
199
274
|
Install-Flat "$ScriptDir\rules" $RulesDest "Rules"
|
|
200
275
|
}
|
|
276
|
+
"cline" {
|
|
277
|
+
Install-Flat "$ScriptDir\rules" $RulesDest "Rules"
|
|
278
|
+
Install-Flat "$ScriptDir\agents" $RulesDest "Agents (flattened)"
|
|
279
|
+
Install-Flat "$ScriptDir\commands" $RulesDest "Commands (flattened)"
|
|
280
|
+
}
|
|
281
|
+
"roocode" {
|
|
282
|
+
Install-Dir "$ScriptDir\agents" $AgentsDest "Agents ($AgentCount)"
|
|
283
|
+
Install-Dir "$ScriptDir\skills" $SkillsDest "Skills ($SkillCount)"
|
|
284
|
+
Install-Dir "$ScriptDir\commands" $CommandsDest "Commands ($CmdCount)"
|
|
285
|
+
Install-Flat "$ScriptDir\rules" $RulesDest "Rules"
|
|
286
|
+
}
|
|
287
|
+
"aider" {
|
|
288
|
+
Install-Dir "$ScriptDir\agents" $AgentsDest "Agents ($AgentCount)"
|
|
289
|
+
Install-Dir "$ScriptDir\skills" $SkillsDest "Skills ($SkillCount)"
|
|
290
|
+
Install-Dir "$ScriptDir\commands" $CommandsDest "Commands ($CmdCount)"
|
|
291
|
+
Install-Flat "$ScriptDir\rules" $RulesDest "Rules"
|
|
292
|
+
$ConventionsFile = "$(Get-Location)\CONVENTIONS.md"
|
|
293
|
+
if (-not (Test-Path $ConventionsFile)) {
|
|
294
|
+
$aiderText = @'
|
|
295
|
+
# Project Conventions (Aider)
|
|
296
|
+
|
|
297
|
+
This project uses **Kodelyth ECC** for AI agent guidance.
|
|
298
|
+
|
|
299
|
+
Aider auto-loads this file. To bring full ECC context, run Aider with:
|
|
300
|
+
|
|
301
|
+
aider --read .aider-ecc/rules/agent-intent-routing.md
|
|
302
|
+
aider --read .aider-ecc/rules/coding-standards.md
|
|
303
|
+
aider --read .aider-ecc/agents/debug-detective.md
|
|
304
|
+
|
|
305
|
+
Full catalog: `.aider-ecc/agents/`, `.aider-ecc/skills/`, `.aider-ecc/commands/`, `.aider-ecc/rules/`.
|
|
306
|
+
|
|
307
|
+
Powered by Kodelyth ECC — github.com/sifxprime/kodelyth-ecc
|
|
308
|
+
'@
|
|
309
|
+
$aiderText | Out-File -FilePath $ConventionsFile -Encoding UTF8
|
|
310
|
+
Write-Host " [OK] CONVENTIONS.md -> $ConventionsFile" -ForegroundColor Green
|
|
311
|
+
} else {
|
|
312
|
+
Write-Host " [skip] CONVENTIONS.md exists — not overwriting" -ForegroundColor Yellow
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
"kimi" {
|
|
316
|
+
Install-Dir "$ScriptDir\agents" $AgentsDest "Agents ($AgentCount)"
|
|
317
|
+
Install-Dir "$ScriptDir\skills" $SkillsDest "Skills ($SkillCount)"
|
|
318
|
+
Install-Dir "$ScriptDir\commands" $CommandsDest "Commands ($CmdCount)"
|
|
319
|
+
Install-Flat "$ScriptDir\rules" $RulesDest "Rules"
|
|
320
|
+
}
|
|
321
|
+
{ $_ -in "gemini-project","gemini-home" } {
|
|
322
|
+
Install-Dir "$ScriptDir\agents" $AgentsDest "Agents ($AgentCount)"
|
|
323
|
+
Install-Dir "$ScriptDir\skills" $SkillsDest "Skills ($SkillCount)"
|
|
324
|
+
Install-Flat "$ScriptDir\rules" $RulesDest "Rules"
|
|
325
|
+
$GeminiFile = "$Dest\GEMINI.md"
|
|
326
|
+
if (-not (Test-Path $GeminiFile)) {
|
|
327
|
+
$geminiText = @'
|
|
328
|
+
# Kodelyth ECC — Gemini CLI context
|
|
329
|
+
|
|
330
|
+
This project uses Kodelyth ECC — 70 specialist agents, 194 skills, 97 commands, intent routing, and self-learning memory.
|
|
331
|
+
|
|
332
|
+
The full toolkit is installed under this directory:
|
|
333
|
+
|
|
334
|
+
- agents/ — specialist subagents (debug-detective, security-reviewer, devil-mode crew)
|
|
335
|
+
- skills/ — domain knowledge files
|
|
336
|
+
- rules/ — always-on coding standards + intent routing rule
|
|
337
|
+
|
|
338
|
+
For more: github.com/sifxprime/kodelyth-ecc
|
|
339
|
+
'@
|
|
340
|
+
$geminiText | Out-File -FilePath $GeminiFile -Encoding UTF8
|
|
341
|
+
Write-Host " [OK] GEMINI.md -> $GeminiFile" -ForegroundColor Green
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
# ── Install bundle cheat sheet (if -Bundle was set) ───────────────────────────
|
|
347
|
+
if ($Bundle -and (Test-Path "$ScriptDir\bundles\$Bundle.md")) {
|
|
348
|
+
Copy-Item -Path "$ScriptDir\bundles\$Bundle.md" -Destination "$Dest\BUNDLE.md" -Force
|
|
349
|
+
Write-Host " [OK] Bundle cheat sheet ($Bundle) -> $Dest\BUNDLE.md" -ForegroundColor Green
|
|
201
350
|
}
|
|
202
351
|
|
|
203
352
|
# ── Write install state ───────────────────────────────────────────────────────
|
|
@@ -207,12 +356,35 @@ $State = @{
|
|
|
207
356
|
installed_by = "kodelyth-ecc"
|
|
208
357
|
version = $Version.Trim()
|
|
209
358
|
target = $Target
|
|
359
|
+
bundle = $Bundle
|
|
210
360
|
installed_at = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
|
|
211
361
|
languages = $Languages
|
|
212
362
|
} | ConvertTo-Json
|
|
213
363
|
$State | Out-File -FilePath $StateFile -Encoding UTF8
|
|
214
364
|
Write-Host " [OK] Install state -> $StateFile" -ForegroundColor Green
|
|
215
365
|
|
|
366
|
+
# ── Bundle-specific reminder ──────────────────────────────────────────────────
|
|
367
|
+
if ($Bundle) {
|
|
368
|
+
Write-Host ""
|
|
369
|
+
switch ($Bundle) {
|
|
370
|
+
"indie-hacker" {
|
|
371
|
+
Write-Host " Bundle: Indie Hacker is active." -ForegroundColor Cyan
|
|
372
|
+
Write-Host " Lead with: /project-launch (new) | /tdd | /devil-mode --pre-public (before going public)"
|
|
373
|
+
Write-Host " Read: $Dest\BUNDLE.md for the full ship-fast playbook."
|
|
374
|
+
}
|
|
375
|
+
"red-team" {
|
|
376
|
+
Write-Host " Bundle: Red Team is active." -ForegroundColor Red
|
|
377
|
+
Write-Host " Lead with: /devil-mode (4-agent sweep) | /devil-mode --all (full 8-agent crew)"
|
|
378
|
+
Write-Host " Read: $Dest\BUNDLE.md for the adversarial workflow playbook."
|
|
379
|
+
}
|
|
380
|
+
"enterprise" {
|
|
381
|
+
Write-Host " Bundle: Enterprise is active." -ForegroundColor Cyan
|
|
382
|
+
Write-Host " Lead with: /team-review (per-PR) | /pre-release (per-tag) | /devil-mode --pre-launch"
|
|
383
|
+
Write-Host " Read: $Dest\BUNDLE.md for the compliance + audit playbook."
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
216
388
|
# ── Done ──────────────────────────────────────────────────────────────────────
|
|
217
389
|
Write-Host ""
|
|
218
390
|
Write-Host "Kodelyth ECC installed successfully!" -ForegroundColor Green
|
|
@@ -248,6 +420,31 @@ switch ($Target) {
|
|
|
248
420
|
Write-Host " 1. Open the project in OpenCode"
|
|
249
421
|
Write-Host " 2. Rules in .opencode/rules/ are now loaded"
|
|
250
422
|
}
|
|
423
|
+
"cline" {
|
|
424
|
+
Write-Host " 1. Open the project in VS Code with Cline"
|
|
425
|
+
Write-Host " 2. .clinerules/ auto-loaded by Cline"
|
|
426
|
+
Write-Host " 3. Ask: 'use debug-detective' or 'devil mode the codebase'"
|
|
427
|
+
}
|
|
428
|
+
"roocode" {
|
|
429
|
+
Write-Host " 1. Open the project in VS Code with Roo Code"
|
|
430
|
+
Write-Host " 2. Rules + agents auto-loaded from .roo/"
|
|
431
|
+
Write-Host " 3. Ask: 'use kodelyth-advisor'"
|
|
432
|
+
}
|
|
433
|
+
"aider" {
|
|
434
|
+
Write-Host " 1. CONVENTIONS.md created at project root"
|
|
435
|
+
Write-Host " 2. Run: aider --read .aider-ecc/rules/agent-intent-routing.md"
|
|
436
|
+
Write-Host " 3. Then describe your problem in plain words"
|
|
437
|
+
}
|
|
438
|
+
"kimi" {
|
|
439
|
+
Write-Host " 1. Open the project with Kimi CLI"
|
|
440
|
+
Write-Host " 2. Agents/skills/rules in .kimi/"
|
|
441
|
+
Write-Host " 3. Ask: 'use kodelyth-advisor'"
|
|
442
|
+
}
|
|
443
|
+
{ $_ -in "gemini-project","gemini-home" } {
|
|
444
|
+
Write-Host " 1. Run Gemini CLI"
|
|
445
|
+
Write-Host " 2. GEMINI.md auto-loaded from $Dest"
|
|
446
|
+
Write-Host " 3. Ask: 'use debug-detective'"
|
|
447
|
+
}
|
|
251
448
|
default {
|
|
252
449
|
Write-Host " 1. Restart your AI coding agent"
|
|
253
450
|
Write-Host " 2. Agents, skills, and rules are now active"
|