@ekkos/cli 0.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.
Files changed (135) hide show
  1. package/dist/cache/LocalSessionStore.d.ts +129 -0
  2. package/dist/cache/LocalSessionStore.js +688 -0
  3. package/dist/cache/capture.d.ts +26 -0
  4. package/dist/cache/capture.js +461 -0
  5. package/dist/cache/index.d.ts +7 -0
  6. package/dist/cache/index.js +23 -0
  7. package/dist/cache/types.d.ts +147 -0
  8. package/dist/cache/types.js +40 -0
  9. package/dist/commands/init.d.ts +9 -0
  10. package/dist/commands/init.js +478 -0
  11. package/dist/commands/run.d.ts +12 -0
  12. package/dist/commands/run.js +829 -0
  13. package/dist/commands/setup.d.ts +6 -0
  14. package/dist/commands/setup.js +658 -0
  15. package/dist/commands/status.d.ts +1 -0
  16. package/dist/commands/status.js +109 -0
  17. package/dist/commands/test.d.ts +1 -0
  18. package/dist/commands/test.js +157 -0
  19. package/dist/deploy/agents.d.ts +15 -0
  20. package/dist/deploy/agents.js +72 -0
  21. package/dist/deploy/hooks.d.ts +16 -0
  22. package/dist/deploy/hooks.js +121 -0
  23. package/dist/deploy/index.d.ts +7 -0
  24. package/dist/deploy/index.js +24 -0
  25. package/dist/deploy/instructions.d.ts +12 -0
  26. package/dist/deploy/instructions.js +36 -0
  27. package/dist/deploy/mcp.d.ts +19 -0
  28. package/dist/deploy/mcp.js +109 -0
  29. package/dist/deploy/plugins.d.ts +19 -0
  30. package/dist/deploy/plugins.js +62 -0
  31. package/dist/deploy/settings.d.ts +8 -0
  32. package/dist/deploy/settings.js +84 -0
  33. package/dist/deploy/skills.d.ts +19 -0
  34. package/dist/deploy/skills.js +60 -0
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.js +71 -0
  37. package/dist/restore/RestoreOrchestrator.d.ts +48 -0
  38. package/dist/restore/RestoreOrchestrator.js +481 -0
  39. package/dist/restore/index.d.ts +4 -0
  40. package/dist/restore/index.js +20 -0
  41. package/dist/utils/platform.d.ts +29 -0
  42. package/dist/utils/platform.js +65 -0
  43. package/dist/utils/session-words.json +119 -0
  44. package/dist/utils/state.d.ts +57 -0
  45. package/dist/utils/state.js +186 -0
  46. package/dist/utils/templates.d.ts +24 -0
  47. package/dist/utils/templates.js +118 -0
  48. package/package.json +48 -0
  49. package/templates/CLAUDE.md +287 -0
  50. package/templates/README.md +378 -0
  51. package/templates/agents/README.md +182 -0
  52. package/templates/agents/code-reviewer.md +166 -0
  53. package/templates/agents/debug-detective.md +169 -0
  54. package/templates/agents/ekkOS_Vercel.md +99 -0
  55. package/templates/agents/extension-manager.md +229 -0
  56. package/templates/agents/git-companion.md +185 -0
  57. package/templates/agents/github-test-agent.md +321 -0
  58. package/templates/agents/railway-manager.md +179 -0
  59. package/templates/claude-plugins/PHASE2_COMPLETION.md +346 -0
  60. package/templates/claude-plugins/PLUGIN_PROPOSALS.md +1776 -0
  61. package/templates/claude-plugins/README.md +587 -0
  62. package/templates/claude-plugins/agents/code-reviewer.json +14 -0
  63. package/templates/claude-plugins/agents/debug-detective.json +15 -0
  64. package/templates/claude-plugins/agents/git-companion.json +14 -0
  65. package/templates/claude-plugins/blog-manager/.claude-plugin/plugin.json +8 -0
  66. package/templates/claude-plugins/blog-manager/commands/blog.md +691 -0
  67. package/templates/claude-plugins/golden-loop-monitor/.claude-plugin/plugin.json +8 -0
  68. package/templates/claude-plugins/golden-loop-monitor/commands/loop-status.md +434 -0
  69. package/templates/claude-plugins/learning-tracker/.claude-plugin/plugin.json +8 -0
  70. package/templates/claude-plugins/learning-tracker/commands/my-patterns.md +282 -0
  71. package/templates/claude-plugins/memory-lens/.claude-plugin/plugin.json +8 -0
  72. package/templates/claude-plugins/memory-lens/commands/memory-search.md +181 -0
  73. package/templates/claude-plugins/pattern-coach/.claude-plugin/plugin.json +8 -0
  74. package/templates/claude-plugins/pattern-coach/commands/forge.md +365 -0
  75. package/templates/claude-plugins/project-schema-validator/.claude-plugin/plugin.json +8 -0
  76. package/templates/claude-plugins/project-schema-validator/commands/validate-schema.md +582 -0
  77. package/templates/claude-plugins-admin/AGENT_TEAM_PROPOSALS.md +819 -0
  78. package/templates/claude-plugins-admin/README.md +446 -0
  79. package/templates/claude-plugins-admin/autonomous-admin-agent/.claude-plugin/plugin.json +8 -0
  80. package/templates/claude-plugins-admin/autonomous-admin-agent/commands/agent.md +595 -0
  81. package/templates/claude-plugins-admin/backend-agent/.claude-plugin/plugin.json +8 -0
  82. package/templates/claude-plugins-admin/backend-agent/commands/backend.md +798 -0
  83. package/templates/claude-plugins-admin/deploy-guardian/.claude-plugin/plugin.json +8 -0
  84. package/templates/claude-plugins-admin/deploy-guardian/commands/deploy.md +554 -0
  85. package/templates/claude-plugins-admin/frontend-agent/.claude-plugin/plugin.json +8 -0
  86. package/templates/claude-plugins-admin/frontend-agent/commands/frontend.md +881 -0
  87. package/templates/claude-plugins-admin/mcp-server-manager/.claude-plugin/plugin.json +8 -0
  88. package/templates/claude-plugins-admin/mcp-server-manager/commands/mcp.md +85 -0
  89. package/templates/claude-plugins-admin/memory-system-monitor/.claude-plugin/plugin.json +8 -0
  90. package/templates/claude-plugins-admin/memory-system-monitor/commands/memory-health.md +569 -0
  91. package/templates/claude-plugins-admin/qa-agent/.claude-plugin/plugin.json +8 -0
  92. package/templates/claude-plugins-admin/qa-agent/commands/qa.md +863 -0
  93. package/templates/claude-plugins-admin/tech-lead-agent/.claude-plugin/plugin.json +8 -0
  94. package/templates/claude-plugins-admin/tech-lead-agent/commands/lead.md +732 -0
  95. package/templates/commands/continue.md +47 -0
  96. package/templates/cursor-hooks/after-agent-response.sh +117 -0
  97. package/templates/cursor-hooks/before-submit-prompt.sh +419 -0
  98. package/templates/cursor-hooks/hooks.json +20 -0
  99. package/templates/cursor-hooks/lib/contract.sh +320 -0
  100. package/templates/cursor-hooks/stop.sh +75 -0
  101. package/templates/cursor-rules/ekkos-memory.md +187 -0
  102. package/templates/hooks/assistant-response.sh +96 -0
  103. package/templates/hooks/hooks.json +28 -0
  104. package/templates/hooks/lib/contract.sh +320 -0
  105. package/templates/hooks/lib/state.sh +158 -0
  106. package/templates/hooks/session-start.ps1 +41 -0
  107. package/templates/hooks/session-start.sh +318 -0
  108. package/templates/hooks/stop.ps1 +16 -0
  109. package/templates/hooks/stop.sh +989 -0
  110. package/templates/hooks/user-prompt-submit.ps1 +174 -0
  111. package/templates/hooks/user-prompt-submit.sh +587 -0
  112. package/templates/hooks-node/lib/state.js +187 -0
  113. package/templates/hooks-node/stop.js +416 -0
  114. package/templates/hooks-node/user-prompt-submit.js +337 -0
  115. package/templates/plan-template.md +306 -0
  116. package/templates/rules/00-hooks-contract.mdc +89 -0
  117. package/templates/rules/30-ekkos-core.mdc +188 -0
  118. package/templates/rules/31-ekkos-messages.mdc +78 -0
  119. package/templates/skills/continue/SKILL.md +169 -0
  120. package/templates/skills/ekkOS_Deep_Recall/Skill.md +282 -0
  121. package/templates/skills/ekkOS_Learn/Skill.md +265 -0
  122. package/templates/skills/ekkOS_Memory_First/Skill.md +206 -0
  123. package/templates/skills/ekkOS_Plan_Assist/Skill.md +302 -0
  124. package/templates/skills/ekkOS_Preferences/Skill.md +247 -0
  125. package/templates/skills/ekkOS_Reflect/Skill.md +257 -0
  126. package/templates/skills/ekkOS_Safety/Skill.md +265 -0
  127. package/templates/skills/ekkOS_Schema/Skill.md +251 -0
  128. package/templates/skills/ekkOS_Summary/Skill.md +257 -0
  129. package/templates/skills/ekkOS_Vault/Skill.md +287 -0
  130. package/templates/skills/permissions/Skill.md +322 -0
  131. package/templates/spec-template.md +159 -0
  132. package/templates/windsurf-hooks/before-submit-prompt.sh +238 -0
  133. package/templates/windsurf-hooks/hooks.json +10 -0
  134. package/templates/windsurf-hooks/lib/contract.sh +320 -0
  135. package/templates/windsurf-rules/ekkos-memory.md +129 -0
@@ -0,0 +1,6 @@
1
+ interface SetupOptions {
2
+ ide: string;
3
+ key?: string;
4
+ }
5
+ export declare function setup(options: SetupOptions): Promise<void>;
6
+ export {};
@@ -0,0 +1,658 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setup = setup;
7
+ const os_1 = require("os");
8
+ const path_1 = require("path");
9
+ const fs_1 = require("fs");
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ const inquirer_1 = __importDefault(require("inquirer"));
12
+ const ora_1 = __importDefault(require("ora"));
13
+ const EKKOS_API_URL = 'https://mcp.ekkos.dev';
14
+ const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), '.ekkos');
15
+ const CONFIG_FILE = (0, path_1.join)(CONFIG_DIR, 'config.json');
16
+ /**
17
+ * Auto-detect which IDE the user is running in
18
+ */
19
+ function detectIDE() {
20
+ // Check TERM_PROGRAM environment variable (set by many terminals/IDEs)
21
+ const termProgram = process.env.TERM_PROGRAM?.toLowerCase() || '';
22
+ const termEmulator = process.env.TERMINAL_EMULATOR?.toLowerCase() || '';
23
+ const colorterm = process.env.COLORTERM?.toLowerCase() || '';
24
+ // Cursor sets TERM_PROGRAM
25
+ if (termProgram.includes('cursor')) {
26
+ return 'cursor';
27
+ }
28
+ // VSCode sets TERM_PROGRAM to "vscode"
29
+ if (termProgram.includes('vscode') || termEmulator.includes('vscode')) {
30
+ return 'vscode';
31
+ }
32
+ // Windsurf/Codeium detection
33
+ if (termProgram.includes('windsurf') || termProgram.includes('codeium')) {
34
+ return 'windsurf';
35
+ }
36
+ // Check for Windsurf by config directory existence (if recently used)
37
+ const windsurfConfig = (0, path_1.join)((0, os_1.homedir)(), '.codeium', 'windsurf');
38
+ if ((0, fs_1.existsSync)(windsurfConfig)) {
39
+ // Also check if there's activity (mcp_config.json exists or was modified recently)
40
+ const mcpConfig = (0, path_1.join)(windsurfConfig, 'mcp_config.json');
41
+ if ((0, fs_1.existsSync)(mcpConfig)) {
42
+ // Windsurf is installed and configured - suggest it
43
+ // But don't return it as definitive without env var
44
+ }
45
+ }
46
+ // Check for Claude Code by looking at parent process or specific env vars
47
+ // Claude Code typically runs in a terminal context
48
+ if (process.env.CLAUDE_CODE || process.env.ANTHROPIC_API_KEY) {
49
+ return 'claude-code';
50
+ }
51
+ // Check ~/.claude directory for Claude Code usage
52
+ const claudeDir = (0, path_1.join)((0, os_1.homedir)(), '.claude');
53
+ if ((0, fs_1.existsSync)(claudeDir)) {
54
+ const hooksDir = (0, path_1.join)(claudeDir, 'hooks');
55
+ if ((0, fs_1.existsSync)(hooksDir)) {
56
+ // Claude Code has been set up before
57
+ }
58
+ }
59
+ // Check for cursor config directory
60
+ const cursorDir = (0, path_1.join)((0, os_1.homedir)(), '.cursor');
61
+ if ((0, fs_1.existsSync)(cursorDir)) {
62
+ // Cursor is installed
63
+ }
64
+ return null;
65
+ }
66
+ async function setup(options) {
67
+ console.log('');
68
+ console.log(chalk_1.default.cyan.bold('🧠 ekkOS Setup'));
69
+ console.log(chalk_1.default.gray('─'.repeat(50)));
70
+ console.log('');
71
+ // Get API key
72
+ let apiKey = options.key || process.env.EKKOS_API_KEY;
73
+ if (!apiKey) {
74
+ console.log(chalk_1.default.yellow('Get your API key from: https://ekkos.dev/dashboard/keys'));
75
+ console.log('');
76
+ const answers = await inquirer_1.default.prompt([
77
+ {
78
+ type: 'password',
79
+ name: 'apiKey',
80
+ message: 'Enter your ekkOS API key:',
81
+ mask: '*',
82
+ validate: (input) => {
83
+ if (!input || input.length < 10) {
84
+ return 'Please enter a valid API key';
85
+ }
86
+ return true;
87
+ }
88
+ }
89
+ ]);
90
+ apiKey = answers.apiKey;
91
+ }
92
+ // Verify API key
93
+ const spinner = (0, ora_1.default)('Verifying API key...').start();
94
+ try {
95
+ const response = await fetch(`${EKKOS_API_URL}/api/v1/patterns/query`, {
96
+ method: 'POST',
97
+ headers: {
98
+ 'Authorization': `Bearer ${apiKey}`,
99
+ 'Content-Type': 'application/json'
100
+ },
101
+ body: JSON.stringify({ query: 'test', k: 1 })
102
+ });
103
+ if (!response.ok) {
104
+ spinner.fail('Invalid API key');
105
+ console.log(chalk_1.default.red('Please check your API key and try again.'));
106
+ process.exit(1);
107
+ }
108
+ spinner.succeed('API key verified');
109
+ }
110
+ catch (error) {
111
+ spinner.fail('Could not connect to ekkOS');
112
+ console.log(chalk_1.default.red('Check your internet connection and try again.'));
113
+ process.exit(1);
114
+ }
115
+ // Save config
116
+ if (!(0, fs_1.existsSync)(CONFIG_DIR)) {
117
+ (0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
118
+ }
119
+ const config = {
120
+ apiKey: apiKey,
121
+ installedIDEs: [],
122
+ installedAt: new Date().toISOString()
123
+ };
124
+ // Determine which IDE to setup
125
+ let ideToSetup;
126
+ if (options.ide === 'all') {
127
+ // Try to auto-detect the IDE
128
+ const detectedIDE = detectIDE();
129
+ if (detectedIDE) {
130
+ console.log(chalk_1.default.green(`✓ Detected IDE: ${detectedIDE}`));
131
+ console.log('');
132
+ }
133
+ const ideAnswers = await inquirer_1.default.prompt([
134
+ {
135
+ type: 'list',
136
+ name: 'ide',
137
+ message: 'Which IDE are you setting up?',
138
+ choices: [
139
+ { name: 'Claude Code (CLI)', value: 'claude-code' },
140
+ { name: 'Cursor', value: 'cursor' },
141
+ { name: 'Windsurf (Cascade)', value: 'windsurf' },
142
+ { name: 'VSCode (Copilot)', value: 'vscode' }
143
+ ],
144
+ default: detectedIDE || 'cursor'
145
+ }
146
+ ]);
147
+ ideToSetup = ideAnswers.ide;
148
+ }
149
+ else {
150
+ ideToSetup = options.ide;
151
+ }
152
+ console.log('');
153
+ // Setup the selected IDE
154
+ await setupIDE(ideToSetup, apiKey, config);
155
+ // Save final config
156
+ (0, fs_1.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2));
157
+ // Summary
158
+ console.log('');
159
+ console.log(chalk_1.default.green.bold('✅ Setup complete!'));
160
+ console.log('');
161
+ console.log(chalk_1.default.gray('─'.repeat(50)));
162
+ console.log('');
163
+ console.log('Configured IDEs:');
164
+ for (const ide of config.installedIDEs) {
165
+ console.log(chalk_1.default.cyan(` • ${ide}`));
166
+ }
167
+ console.log('');
168
+ console.log('Next steps:');
169
+ console.log(chalk_1.default.gray(' 1. Open your IDE'));
170
+ console.log(chalk_1.default.gray(' 2. Start coding - memory is now active'));
171
+ console.log(chalk_1.default.gray(' 3. Watch patterns form as you work'));
172
+ console.log('');
173
+ console.log(chalk_1.default.cyan('View your memory at: https://ekkos.dev/dashboard'));
174
+ console.log('');
175
+ }
176
+ async function setupIDE(ide, apiKey, config) {
177
+ const spinner = (0, ora_1.default)(`Setting up ${ide}...`).start();
178
+ try {
179
+ switch (ide) {
180
+ case 'claude-code':
181
+ await setupClaudeCode(apiKey);
182
+ break;
183
+ case 'cursor':
184
+ await setupCursor(apiKey);
185
+ break;
186
+ case 'windsurf':
187
+ await setupWindsurf(apiKey);
188
+ break;
189
+ case 'vscode':
190
+ await setupVSCode(apiKey);
191
+ break;
192
+ default:
193
+ spinner.warn(`Unknown IDE: ${ide}`);
194
+ return;
195
+ }
196
+ config.installedIDEs.push(ide);
197
+ spinner.succeed(`${ide} configured`);
198
+ }
199
+ catch (error) {
200
+ spinner.fail(`Failed to setup ${ide}: ${error}`);
201
+ }
202
+ }
203
+ async function setupClaudeCode(apiKey) {
204
+ const claudeDir = (0, path_1.join)((0, os_1.homedir)(), '.claude');
205
+ const hooksDir = (0, path_1.join)(claudeDir, 'hooks');
206
+ if (!(0, fs_1.existsSync)(hooksDir)) {
207
+ (0, fs_1.mkdirSync)(hooksDir, { recursive: true });
208
+ }
209
+ const isWindows = (0, os_1.platform)() === 'win32';
210
+ if (isWindows) {
211
+ // Windows: PowerShell hooks
212
+ const promptSubmitHook = generatePromptSubmitHookPS(apiKey);
213
+ const promptSubmitPath = (0, path_1.join)(hooksDir, 'user-prompt-submit.ps1');
214
+ (0, fs_1.writeFileSync)(promptSubmitPath, promptSubmitHook);
215
+ const stopHook = generateStopHookPS(apiKey);
216
+ const stopPath = (0, path_1.join)(hooksDir, 'stop.ps1');
217
+ (0, fs_1.writeFileSync)(stopPath, stopHook);
218
+ // Create wrapper batch files for Windows
219
+ (0, fs_1.writeFileSync)((0, path_1.join)(hooksDir, 'user-prompt-submit.cmd'), `@echo off\npowershell -ExecutionPolicy Bypass -File "%~dp0user-prompt-submit.ps1"`);
220
+ (0, fs_1.writeFileSync)((0, path_1.join)(hooksDir, 'stop.cmd'), `@echo off\npowershell -ExecutionPolicy Bypass -File "%~dp0stop.ps1"`);
221
+ }
222
+ else {
223
+ // Unix: Bash hooks
224
+ const promptSubmitHook = generatePromptSubmitHook(apiKey);
225
+ const promptSubmitPath = (0, path_1.join)(hooksDir, 'user-prompt-submit.sh');
226
+ (0, fs_1.writeFileSync)(promptSubmitPath, promptSubmitHook);
227
+ (0, fs_1.chmodSync)(promptSubmitPath, '755');
228
+ const stopHook = generateStopHook(apiKey);
229
+ const stopPath = (0, path_1.join)(hooksDir, 'stop.sh');
230
+ (0, fs_1.writeFileSync)(stopPath, stopHook);
231
+ (0, fs_1.chmodSync)(stopPath, '755');
232
+ }
233
+ // Create state directory
234
+ const stateDir = (0, path_1.join)(claudeDir, 'state');
235
+ if (!(0, fs_1.existsSync)(stateDir)) {
236
+ (0, fs_1.mkdirSync)(stateDir, { recursive: true });
237
+ }
238
+ }
239
+ async function setupCursor(apiKey) {
240
+ // Cursor uses .cursorrules for system prompt
241
+ // and MCP servers for tools
242
+ const cursorDir = (0, path_1.join)((0, os_1.homedir)(), '.cursor');
243
+ if (!(0, fs_1.existsSync)(cursorDir)) {
244
+ (0, fs_1.mkdirSync)(cursorDir, { recursive: true });
245
+ }
246
+ // Create/update MCP settings
247
+ const mcpConfigPath = (0, path_1.join)(cursorDir, 'mcp.json');
248
+ let mcpConfig = {};
249
+ if ((0, fs_1.existsSync)(mcpConfigPath)) {
250
+ try {
251
+ mcpConfig = JSON.parse((0, fs_1.readFileSync)(mcpConfigPath, 'utf-8'));
252
+ }
253
+ catch { }
254
+ }
255
+ mcpConfig.mcpServers = mcpConfig.mcpServers || {};
256
+ mcpConfig.mcpServers['ekkos-memory'] = {
257
+ command: 'npx',
258
+ args: ['@ekkos/mcp-server'],
259
+ env: {
260
+ EKKOS_API_KEY: apiKey
261
+ }
262
+ };
263
+ (0, fs_1.writeFileSync)(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
264
+ // Create .cursorrules template in current directory
265
+ const cursorRules = generateCursorRules();
266
+ const cursorRulesPath = (0, path_1.join)(process.cwd(), '.cursorrules');
267
+ if (!(0, fs_1.existsSync)(cursorRulesPath)) {
268
+ (0, fs_1.writeFileSync)(cursorRulesPath, cursorRules);
269
+ }
270
+ }
271
+ async function setupWindsurf(apiKey) {
272
+ // Windsurf (Codeium) supports MCP servers like Cursor
273
+ // Config location: ~/.codeium/windsurf/mcp_config.json
274
+ const codeiumDir = (0, path_1.join)((0, os_1.homedir)(), '.codeium', 'windsurf');
275
+ if (!(0, fs_1.existsSync)(codeiumDir)) {
276
+ (0, fs_1.mkdirSync)(codeiumDir, { recursive: true });
277
+ }
278
+ // Create/update MCP config for Windsurf
279
+ const mcpConfigPath = (0, path_1.join)(codeiumDir, 'mcp_config.json');
280
+ let mcpConfig = { mcpServers: {} };
281
+ if ((0, fs_1.existsSync)(mcpConfigPath)) {
282
+ try {
283
+ mcpConfig = JSON.parse((0, fs_1.readFileSync)(mcpConfigPath, 'utf-8'));
284
+ mcpConfig.mcpServers = mcpConfig.mcpServers || {};
285
+ }
286
+ catch { }
287
+ }
288
+ // Add ekkOS cloud MCP server (HTTP transport)
289
+ mcpConfig.mcpServers['ekkos-memory'] = {
290
+ serverUrl: 'https://mcp.ekkos.dev',
291
+ disabled: false,
292
+ alwaysAllow: [],
293
+ headers: {
294
+ 'Authorization': `Bearer ${apiKey}`
295
+ }
296
+ };
297
+ (0, fs_1.writeFileSync)(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
298
+ // Also save to legacy location for backwards compat
299
+ const windsurfDir = (0, path_1.join)((0, os_1.homedir)(), '.windsurf');
300
+ if (!(0, fs_1.existsSync)(windsurfDir)) {
301
+ (0, fs_1.mkdirSync)(windsurfDir, { recursive: true });
302
+ }
303
+ (0, fs_1.writeFileSync)((0, path_1.join)(windsurfDir, 'ekkos.json'), JSON.stringify({ apiKey }, null, 2));
304
+ // Create project rules template
305
+ const cascadeRules = generateCascadeRules();
306
+ const cascadeRulesPath = (0, path_1.join)(process.cwd(), '.windsurfrules');
307
+ if (!(0, fs_1.existsSync)(cascadeRulesPath)) {
308
+ (0, fs_1.writeFileSync)(cascadeRulesPath, cascadeRules);
309
+ }
310
+ }
311
+ async function setupVSCode(apiKey) {
312
+ // VSCode - create settings for Copilot/Continue
313
+ const vscodeDir = (0, path_1.join)((0, os_1.homedir)(), '.vscode');
314
+ if (!(0, fs_1.existsSync)(vscodeDir)) {
315
+ (0, fs_1.mkdirSync)(vscodeDir, { recursive: true });
316
+ }
317
+ // Save config
318
+ const configPath = (0, path_1.join)(vscodeDir, 'ekkos.json');
319
+ (0, fs_1.writeFileSync)(configPath, JSON.stringify({ apiKey }, null, 2));
320
+ // Note: Full VSCode integration requires extension
321
+ console.log(chalk_1.default.yellow(' Note: VSCode requires the ekkOS extension for full integration'));
322
+ }
323
+ function generatePromptSubmitHook(apiKey) {
324
+ return `#!/bin/bash
325
+ # ekkOS Hook: UserPromptSubmit
326
+ # Golden Loop: RETRIEVE → INJECT
327
+
328
+ set -e
329
+
330
+ EKKOS_API_KEY="${apiKey}"
331
+ MEMORY_API_URL="https://mcp.ekkos.dev"
332
+ STATE_DIR="$HOME/.claude/state"
333
+ mkdir -p "$STATE_DIR"
334
+
335
+ INPUT=$(cat)
336
+ USER_QUERY=$(echo "$INPUT" | jq -r '.query // .message // .prompt // ""')
337
+ SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
338
+ MODEL_INFO=$(echo "$INPUT" | jq -r '.model // "claude-sonnet-4-5"')
339
+
340
+ if [ -z "$USER_QUERY" ] || [ "$USER_QUERY" = "null" ]; then
341
+ exit 0
342
+ fi
343
+
344
+ TASK_ID="task-\${SESSION_ID}-$(date +%s)"
345
+ TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
346
+
347
+ echo ""
348
+ echo "[ekkOS_RETRIEVE] Searching memory..."
349
+
350
+ JSON_PAYLOAD=$(cat << EOF
351
+ {
352
+ "query": $(echo "$USER_QUERY" | jq -R -s .),
353
+ "k": 5,
354
+ "model_used": "$MODEL_INFO"
355
+ }
356
+ EOF
357
+ )
358
+
359
+ API_RESPONSE=$(curl -s -X POST "$MEMORY_API_URL/api/v1/patterns/query" \\
360
+ -H "Authorization: Bearer $EKKOS_API_KEY" \\
361
+ -H "Content-Type: application/json" \\
362
+ -d "$JSON_PAYLOAD" \\
363
+ --connect-timeout 3 \\
364
+ --max-time 5 2>/dev/null || echo '{"patterns":[]}')
365
+
366
+ PATTERNS=$(echo "$API_RESPONSE" | jq '.patterns // []' 2>/dev/null || echo "[]")
367
+ PATTERN_COUNT=$(echo "$PATTERNS" | jq 'length' 2>/dev/null || echo "0")
368
+
369
+ if [ "$PATTERN_COUNT" -gt 0 ]; then
370
+ echo "[ekkOS_RETRIEVE] Found $PATTERN_COUNT patterns"
371
+ else
372
+ echo "[ekkOS_RETRIEVE] No patterns found (building memory)"
373
+ fi
374
+
375
+ # Store state
376
+ PATTERN_DATA=$(cat << EOF
377
+ {
378
+ "patterns": $PATTERNS,
379
+ "model_used": "$MODEL_INFO",
380
+ "task_id": "$TASK_ID",
381
+ "retrieved_at": "$TIMESTAMP",
382
+ "query": $(echo "$USER_QUERY" | jq -R -s .)
383
+ }
384
+ EOF
385
+ )
386
+ echo "$PATTERN_DATA" > "$STATE_DIR/patterns-\${SESSION_ID}.json"
387
+
388
+ # Display patterns
389
+ if [ "$PATTERN_COUNT" -gt 0 ]; then
390
+ AVG_SUCCESS=$(echo "$PATTERNS" | jq '[.[].success_rate // 0.9] | add / length * 100 | round' 2>/dev/null || echo "90")
391
+ echo "[ekkOS_INJECT] Loading $PATTERN_COUNT patterns (\${AVG_SUCCESS}% avg success)"
392
+ echo ""
393
+
394
+ echo "$PATTERNS" | jq -c '.[:5] | .[]' 2>/dev/null | while read -r pattern; do
395
+ TITLE=$(echo "$pattern" | jq -r '.title // "Untitled"')
396
+ SUCCESS_RATE=$(echo "$pattern" | jq -r 'if .success_rate then (.success_rate * 100 | round | tostring) + "%" else "~80%" end')
397
+ APPLIED_COUNT=$(echo "$pattern" | jq -r '.applied_count // 0')
398
+ GUIDANCE=$(echo "$pattern" | jq -r '.guidance // .content // "No guidance"')
399
+
400
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
401
+ echo "🧠 PATTERN: \\"$TITLE\\""
402
+ echo " Applied \${APPLIED_COUNT}x | \${SUCCESS_RATE} success"
403
+ echo ""
404
+ echo " $GUIDANCE" | head -c 500
405
+ echo ""
406
+ done
407
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
408
+ fi
409
+
410
+ echo ""
411
+ echo "[ekkOS_LEARN] 🔥 FORGE new patterns when you solve something!"
412
+ echo ""
413
+
414
+ exit 0
415
+ `;
416
+ }
417
+ function generateStopHook(apiKey) {
418
+ return `#!/bin/bash
419
+ # ekkOS Hook: Stop
420
+ # Golden Loop: CAPTURE → MEASURE
421
+
422
+ set -e
423
+
424
+ EKKOS_API_KEY="${apiKey}"
425
+ MEMORY_API_URL="https://mcp.ekkos.dev"
426
+ STATE_DIR="$HOME/.claude/state"
427
+
428
+ INPUT=$(cat)
429
+ SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
430
+ TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
431
+
432
+ PATTERNS_FILE="$STATE_DIR/patterns-\${SESSION_ID}.json"
433
+ PATTERN_COUNT=0
434
+
435
+ if [ -f "$PATTERNS_FILE" ]; then
436
+ STORED_DATA=$(cat "$PATTERNS_FILE" 2>/dev/null || echo "{}")
437
+ PATTERNS=$(echo "$STORED_DATA" | jq '.patterns // []' 2>/dev/null || echo "[]")
438
+ PATTERN_COUNT=$(echo "$PATTERNS" | jq 'length' 2>/dev/null || echo "0")
439
+ fi
440
+
441
+ echo ""
442
+ echo "[ekkOS_CAPTURE] ✓ Session saved"
443
+
444
+ if [ "$PATTERN_COUNT" -gt 0 ]; then
445
+ echo "[ekkOS_MEASURE] ✓ Tracked $PATTERN_COUNT patterns"
446
+ fi
447
+
448
+ rm -f "$PATTERNS_FILE" 2>/dev/null
449
+
450
+ echo ""
451
+ echo "┌─────────────────────────────────────────────┐"
452
+ echo "│ ekkOS_ GOLDEN LOOP COMPLETE │"
453
+ echo "│ The system learns from every interaction. │"
454
+ echo "└─────────────────────────────────────────────┘"
455
+ echo ""
456
+
457
+ exit 0
458
+ `;
459
+ }
460
+ function generateCursorRules() {
461
+ return `# ekkOS Golden Loop Integration
462
+
463
+ ## Memory System Active
464
+
465
+ Before responding, check ekkOS memory for relevant patterns using the MCP tools:
466
+ - \`ekkOS_Search\` - Find patterns that match the current problem
467
+ - \`ekkOS_Forge\` - Save new patterns when you solve something
468
+
469
+ ## When to FORGE New Patterns
470
+
471
+ Use \`ekkOS_Forge\` when you:
472
+ - Fixed a non-obvious bug
473
+ - Found a better approach
474
+ - Discovered a pitfall
475
+ - User corrected you
476
+
477
+ ## Pattern Application
478
+
479
+ When you use a pattern from memory:
480
+ \`\`\`
481
+ [ekkOS_APPLY] Using: "Pattern Name"
482
+ \`\`\`
483
+
484
+ This is how ekkOS learns and improves over time.
485
+ `;
486
+ }
487
+ function generateCascadeRules() {
488
+ return `# ekkOS Memory Integration for Windsurf
489
+
490
+ ## Active Learning
491
+
492
+ This project uses ekkOS for persistent AI memory.
493
+
494
+ When solving problems:
495
+ 1. Check if similar patterns exist in memory
496
+ 2. Apply proven solutions when they match
497
+ 3. Create new patterns when you solve something novel
498
+
499
+ ## Creating Patterns
500
+
501
+ When you solve a problem that others might encounter:
502
+ - Document the problem clearly
503
+ - Explain the solution
504
+ - Note any anti-patterns to avoid
505
+
506
+ The system learns from every interaction.
507
+ `;
508
+ }
509
+ // ═══════════════════════════════════════════════════════════════════════════
510
+ // WINDOWS POWERSHELL HOOKS
511
+ // ═══════════════════════════════════════════════════════════════════════════
512
+ function generatePromptSubmitHookPS(apiKey) {
513
+ return `# ekkOS Hook: UserPromptSubmit (Windows PowerShell)
514
+ # Golden Loop: RETRIEVE → INJECT
515
+
516
+ $ErrorActionPreference = "Stop"
517
+
518
+ $EKKOS_API_KEY = "${apiKey}"
519
+ $MEMORY_API_URL = "https://mcp.ekkos.dev"
520
+ $STATE_DIR = "$env:USERPROFILE\\.claude\\state"
521
+
522
+ if (!(Test-Path $STATE_DIR)) {
523
+ New-Item -ItemType Directory -Path $STATE_DIR -Force | Out-Null
524
+ }
525
+
526
+ $INPUT = $input | Out-String
527
+ $jsonInput = $INPUT | ConvertFrom-Json -ErrorAction SilentlyContinue
528
+
529
+ $USER_QUERY = if ($jsonInput.query) { $jsonInput.query } elseif ($jsonInput.message) { $jsonInput.message } elseif ($jsonInput.prompt) { $jsonInput.prompt } else { "" }
530
+ $SESSION_ID = if ($jsonInput.session_id) { $jsonInput.session_id } else { "unknown" }
531
+ $MODEL_INFO = if ($jsonInput.model) { $jsonInput.model } else { "claude-sonnet-4-5" }
532
+
533
+ if ([string]::IsNullOrEmpty($USER_QUERY)) {
534
+ exit 0
535
+ }
536
+
537
+ $TASK_ID = "claude-code-task-$SESSION_ID-$([DateTimeOffset]::Now.ToUnixTimeSeconds())"
538
+ $TIMESTAMP = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
539
+
540
+ Write-Host ""
541
+ Write-Host "[ekkOS_RETRIEVE] Searching memory..."
542
+
543
+ $body = @{
544
+ query = $USER_QUERY
545
+ k = 5
546
+ model_used = $MODEL_INFO
547
+ } | ConvertTo-Json
548
+
549
+ try {
550
+ $response = Invoke-RestMethod -Uri "$MEMORY_API_URL/api/v1/patterns/query" \`
551
+ -Method Post \`
552
+ -Headers @{ "Authorization" = "Bearer $EKKOS_API_KEY"; "Content-Type" = "application/json" } \`
553
+ -Body $body \`
554
+ -TimeoutSec 5
555
+
556
+ $PATTERNS = $response.patterns
557
+ $PATTERN_COUNT = if ($PATTERNS) { $PATTERNS.Count } else { 0 }
558
+ } catch {
559
+ $PATTERNS = @()
560
+ $PATTERN_COUNT = 0
561
+ }
562
+
563
+ if ($PATTERN_COUNT -gt 0) {
564
+ Write-Host "[ekkOS_RETRIEVE] Found $PATTERN_COUNT patterns"
565
+ } else {
566
+ Write-Host "[ekkOS_RETRIEVE] No patterns found (new territory)"
567
+ }
568
+
569
+ # Store for stop hook
570
+ $PATTERN_DATA = @{
571
+ patterns = $PATTERNS
572
+ model_used = $MODEL_INFO
573
+ task_id = $TASK_ID
574
+ retrieved_at = $TIMESTAMP
575
+ query = $USER_QUERY.Substring(0, [Math]::Min($USER_QUERY.Length, 1000))
576
+ } | ConvertTo-Json -Depth 10
577
+
578
+ $PATTERN_DATA | Out-File -FilePath "$STATE_DIR\\patterns-$SESSION_ID.json" -Encoding UTF8
579
+
580
+ # Display patterns
581
+ if ($PATTERN_COUNT -gt 0) {
582
+ $rates = $PATTERNS | ForEach-Object { if ($_.success_rate) { $_.success_rate } else { 0.9 } }
583
+ $AVG_SUCCESS = [math]::Round(($rates | Measure-Object -Average).Average * 100)
584
+
585
+ Write-Host "[ekkOS_INJECT] Loading $PATTERN_COUNT patterns ($AVG_SUCCESS% avg success)"
586
+ Write-Host ""
587
+
588
+ $idx = 0
589
+ foreach ($pattern in $PATTERNS | Select-Object -First 5) {
590
+ $idx++
591
+ $TITLE = if ($pattern.title) { $pattern.title } else { "Untitled" }
592
+ $SUCCESS_RATE = if ($pattern.success_rate) { "$([math]::Round($pattern.success_rate * 100))%" } else { "~80%" }
593
+ $APPLIED_COUNT = if ($pattern.applied_count) { $pattern.applied_count } else { 0 }
594
+
595
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
596
+ Write-Host "🧠 LEARNED PATTERN #$idx: \`"$TITLE\`""
597
+ Write-Host " Applied $APPLIED_COUNT time(s) with $SUCCESS_RATE success rate"
598
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
599
+ Write-Host ""
600
+ }
601
+ }
602
+
603
+ Write-Host "[ekkOS_LEARN] 🔥 FORGE new patterns when you solve something!"
604
+ Write-Host ""
605
+
606
+ exit 0
607
+ `;
608
+ }
609
+ function generateStopHookPS(apiKey) {
610
+ return `# ekkOS Hook: Stop (Windows PowerShell)
611
+ # Golden Loop: CAPTURE → MEASURE
612
+
613
+ $ErrorActionPreference = "SilentlyContinue"
614
+
615
+ $EKKOS_API_KEY = "${apiKey}"
616
+ $MEMORY_API_URL = "https://mcp.ekkos.dev"
617
+ $STATE_DIR = "$env:USERPROFILE\\.claude\\state"
618
+
619
+ $INPUT = $input | Out-String
620
+ $jsonInput = $INPUT | ConvertFrom-Json -ErrorAction SilentlyContinue
621
+
622
+ $SESSION_ID = if ($jsonInput.session_id) { $jsonInput.session_id } else { "unknown" }
623
+ $TIMESTAMP = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
624
+
625
+ # Load patterns from RETRIEVE step
626
+ $PATTERNS_FILE = "$STATE_DIR\\patterns-$SESSION_ID.json"
627
+ $PATTERN_COUNT = 0
628
+ $PATTERNS = @()
629
+
630
+ if (Test-Path $PATTERNS_FILE) {
631
+ try {
632
+ $STORED_DATA = Get-Content $PATTERNS_FILE -Raw | ConvertFrom-Json
633
+ $PATTERNS = $STORED_DATA.patterns
634
+ $PATTERN_COUNT = if ($PATTERNS) { $PATTERNS.Count } else { 0 }
635
+ } catch {}
636
+ }
637
+
638
+ Write-Host ""
639
+ Write-Host "[ekkOS_CAPTURE] ✓ Session saved"
640
+
641
+ if ($PATTERN_COUNT -gt 0) {
642
+ Write-Host "[ekkOS_MEASURE] ✓ Tracked $PATTERN_COUNT patterns"
643
+ }
644
+
645
+ # Cleanup
646
+ Remove-Item $PATTERNS_FILE -Force -ErrorAction SilentlyContinue
647
+
648
+ Write-Host ""
649
+ Write-Host "┌─────────────────────────────────────────────────────────────────┐"
650
+ Write-Host "│ ekkOS_ GOLDEN LOOP COMPLETE │"
651
+ Write-Host "├─────────────────────────────────────────────────────────────────┤"
652
+ Write-Host "│ The system learns from every interaction. │"
653
+ Write-Host "└─────────────────────────────────────────────────────────────────┘"
654
+ Write-Host ""
655
+
656
+ exit 0
657
+ `;
658
+ }
@@ -0,0 +1 @@
1
+ export declare function status(): Promise<void>;