@ekkos/cli 1.2.18 → 1.3.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 (47) hide show
  1. package/dist/cache/capture.js +0 -0
  2. package/dist/commands/dashboard.js +57 -49
  3. package/dist/commands/hooks.d.ts +25 -36
  4. package/dist/commands/hooks.js +43 -615
  5. package/dist/commands/init.js +7 -23
  6. package/dist/commands/run.js +90 -3
  7. package/dist/commands/setup.js +10 -352
  8. package/dist/deploy/hooks.d.ts +8 -5
  9. package/dist/deploy/hooks.js +12 -105
  10. package/dist/deploy/settings.d.ts +8 -2
  11. package/dist/deploy/settings.js +22 -51
  12. package/dist/index.js +17 -39
  13. package/dist/utils/state.js +7 -2
  14. package/package.json +1 -1
  15. package/templates/CLAUDE.md +82 -292
  16. package/templates/cursor-rules/ekkos-memory.md +48 -108
  17. package/templates/windsurf-rules/ekkos-memory.md +62 -64
  18. package/templates/cursor-hooks/after-agent-response.sh +0 -117
  19. package/templates/cursor-hooks/before-submit-prompt.sh +0 -419
  20. package/templates/cursor-hooks/hooks.json +0 -20
  21. package/templates/cursor-hooks/lib/contract.sh +0 -320
  22. package/templates/cursor-hooks/stop.sh +0 -75
  23. package/templates/hooks/assistant-response.ps1 +0 -256
  24. package/templates/hooks/assistant-response.sh +0 -160
  25. package/templates/hooks/hooks.json +0 -40
  26. package/templates/hooks/lib/contract.sh +0 -332
  27. package/templates/hooks/lib/count-tokens.cjs +0 -86
  28. package/templates/hooks/lib/ekkos-reminders.sh +0 -98
  29. package/templates/hooks/lib/state.sh +0 -210
  30. package/templates/hooks/session-start.ps1 +0 -146
  31. package/templates/hooks/session-start.sh +0 -353
  32. package/templates/hooks/stop.ps1 +0 -349
  33. package/templates/hooks/stop.sh +0 -382
  34. package/templates/hooks/user-prompt-submit.ps1 +0 -419
  35. package/templates/hooks/user-prompt-submit.sh +0 -516
  36. package/templates/project-stubs/session-start.ps1 +0 -63
  37. package/templates/project-stubs/session-start.sh +0 -55
  38. package/templates/project-stubs/stop.ps1 +0 -63
  39. package/templates/project-stubs/stop.sh +0 -55
  40. package/templates/project-stubs/user-prompt-submit.ps1 +0 -63
  41. package/templates/project-stubs/user-prompt-submit.sh +0 -55
  42. package/templates/windsurf-hooks/README.md +0 -212
  43. package/templates/windsurf-hooks/hooks.json +0 -17
  44. package/templates/windsurf-hooks/install.sh +0 -148
  45. package/templates/windsurf-hooks/lib/contract.sh +0 -322
  46. package/templates/windsurf-hooks/post-cascade-response.sh +0 -251
  47. package/templates/windsurf-hooks/pre-user-prompt.sh +0 -435
@@ -1,121 +1,28 @@
1
1
  "use strict";
2
+ /**
3
+ * DEPRECATED: Hook deployment removed in hookless architecture migration.
4
+ * The CLI + proxy handle everything — hooks are no longer needed.
5
+ */
2
6
  Object.defineProperty(exports, "__esModule", { value: true });
3
7
  exports.deployHooks = deployHooks;
4
8
  exports.areHooksDeployed = areHooksDeployed;
5
9
  exports.countDeployedHooks = countDeployedHooks;
6
- const fs_1 = require("fs");
7
- const path_1 = require("path");
8
- const platform_1 = require("../utils/platform");
9
- const templates_1 = require("../utils/templates");
10
10
  /**
11
- * Deploy all hook scripts to ~/.claude/hooks/
12
- * Deploys .sh scripts on Unix, .ps1 scripts on Windows
11
+ * @deprecated Hooks are no longer deployed. This is a no-op.
13
12
  */
14
- function deployHooks(apiKey) {
15
- // Create directories
16
- if (!(0, fs_1.existsSync)(platform_1.CLAUDE_HOOKS_DIR)) {
17
- (0, fs_1.mkdirSync)(platform_1.CLAUDE_HOOKS_DIR, { recursive: true });
18
- }
19
- if (!(0, fs_1.existsSync)(platform_1.CLAUDE_STATE_DIR)) {
20
- (0, fs_1.mkdirSync)(platform_1.CLAUDE_STATE_DIR, { recursive: true });
21
- }
22
- // Create lib directory
23
- const libDir = (0, path_1.join)(platform_1.CLAUDE_HOOKS_DIR, 'lib');
24
- if (!(0, fs_1.existsSync)(libDir)) {
25
- (0, fs_1.mkdirSync)(libDir, { recursive: true });
26
- }
27
- const deployedFiles = [];
28
- // Transform function to inject API key
29
- const transformHook = (content) => {
30
- // Replace placeholder API key with actual key (works for both bash and PowerShell)
31
- return content
32
- .replace(/EKKOS_API_KEY="[^"]*"/g, `EKKOS_API_KEY="${apiKey}"`)
33
- .replace(/\$env:EKKOS_API_KEY\s*=\s*"[^"]*"/g, `$env:EKKOS_API_KEY = "${apiKey}"`);
34
- };
35
- // Hook extension based on platform
36
- const hookExt = platform_1.isWindows ? '.ps1' : '.sh';
37
- // Main hook files to deploy
38
- const hookNames = [
39
- 'session-start',
40
- 'user-prompt-submit',
41
- 'stop'
42
- ];
43
- // Copy main hook files (platform-specific)
44
- for (const hookName of hookNames) {
45
- const hookFile = `${hookName}${hookExt}`;
46
- const templatePath = `hooks/${hookFile}`;
47
- const destPath = (0, path_1.join)(platform_1.CLAUDE_HOOKS_DIR, hookFile);
48
- try {
49
- (0, templates_1.copyTemplateFile)(templatePath, destPath, transformHook);
50
- deployedFiles.push(hookFile);
51
- // Make executable on Unix
52
- if (!platform_1.isWindows) {
53
- (0, fs_1.chmodSync)(destPath, '755');
54
- }
55
- }
56
- catch (error) {
57
- // Skip if template doesn't exist
58
- console.warn(`Warning: Template ${templatePath} not found`);
59
- }
60
- }
61
- // Also deploy assistant-response.sh on Unix (optional hook)
62
- if (!platform_1.isWindows) {
63
- try {
64
- const templatePath = 'hooks/assistant-response.sh';
65
- const destPath = (0, path_1.join)(platform_1.CLAUDE_HOOKS_DIR, 'assistant-response.sh');
66
- (0, templates_1.copyTemplateFile)(templatePath, destPath, transformHook);
67
- deployedFiles.push('assistant-response.sh');
68
- (0, fs_1.chmodSync)(destPath, '755');
69
- }
70
- catch (error) {
71
- // Optional hook, skip silently
72
- }
73
- }
74
- // Copy lib files (only for Unix - PowerShell doesn't need them)
75
- if (!platform_1.isWindows) {
76
- const libFiles = ['contract.sh', 'state.sh'];
77
- for (const libFile of libFiles) {
78
- const templatePath = `hooks/lib/${libFile}`;
79
- const destPath = (0, path_1.join)(libDir, libFile);
80
- try {
81
- (0, templates_1.copyTemplateFile)(templatePath, destPath);
82
- deployedFiles.push(`lib/${libFile}`);
83
- (0, fs_1.chmodSync)(destPath, '755');
84
- }
85
- catch (error) {
86
- // Skip if template doesn't exist
87
- }
88
- }
89
- }
90
- return {
91
- count: deployedFiles.length,
92
- files: deployedFiles
93
- };
13
+ function deployHooks(_apiKey) {
14
+ console.warn('[ekkOS] deployHooks() is deprecated and has no effect. Hooks are no longer needed.');
15
+ return { count: 0, files: [] };
94
16
  }
95
17
  /**
96
- * Check if hooks are deployed
18
+ * @deprecated Hooks are no longer deployed. Always returns false.
97
19
  */
98
20
  function areHooksDeployed() {
99
- const hookExt = platform_1.isWindows ? '.ps1' : '.sh';
100
- const requiredHooks = [
101
- `session-start${hookExt}`,
102
- `user-prompt-submit${hookExt}`,
103
- `stop${hookExt}`
104
- ];
105
- for (const hook of requiredHooks) {
106
- if (!(0, fs_1.existsSync)((0, path_1.join)(platform_1.CLAUDE_HOOKS_DIR, hook))) {
107
- return false;
108
- }
109
- }
110
- return true;
21
+ return false;
111
22
  }
112
23
  /**
113
- * Count deployed hook files
24
+ * @deprecated Hooks are no longer deployed. Always returns 0.
114
25
  */
115
26
  function countDeployedHooks() {
116
- if (!(0, fs_1.existsSync)(platform_1.CLAUDE_HOOKS_DIR))
117
- return 0;
118
- const hookExt = platform_1.isWindows ? '.ps1' : '.sh';
119
- const files = (0, fs_1.readdirSync)(platform_1.CLAUDE_HOOKS_DIR);
120
- return files.filter(f => f.endsWith(hookExt)).length;
27
+ return 0;
121
28
  }
@@ -1,8 +1,14 @@
1
1
  /**
2
- * Deploy Claude Code settings.json with hooks configuration
2
+ * DEPRECATED: Hook configuration removed in hookless architecture migration.
3
+ * Claude Code settings.json will NOT have any hooks entries written by ekkOS.
4
+ * The CLI + proxy handle everything — hooks are no longer needed.
5
+ */
6
+ /**
7
+ * Deploy Claude Code settings.json — no-op for hooks.
8
+ * Preserves any existing settings but does NOT write any hooks configuration.
3
9
  */
4
10
  export declare function deployClaudeSettings(): void;
5
11
  /**
6
- * Check if hooks are configured in settings.json
12
+ * @deprecated Hooks are no longer configured. Always returns false.
7
13
  */
8
14
  export declare function areHooksConfigured(): boolean;
@@ -1,71 +1,42 @@
1
1
  "use strict";
2
+ /**
3
+ * DEPRECATED: Hook configuration removed in hookless architecture migration.
4
+ * Claude Code settings.json will NOT have any hooks entries written by ekkOS.
5
+ * The CLI + proxy handle everything — hooks are no longer needed.
6
+ */
2
7
  Object.defineProperty(exports, "__esModule", { value: true });
3
8
  exports.deployClaudeSettings = deployClaudeSettings;
4
9
  exports.areHooksConfigured = areHooksConfigured;
5
10
  const fs_1 = require("fs");
6
11
  const platform_1 = require("../utils/platform");
7
- function makeHook(command) {
8
- return [{ matcher: '*', hooks: [{ type: 'command', command, timeout: 5000 }] }];
9
- }
10
12
  /**
11
- * Generate the hooks configuration for Claude Code settings.json
12
- * Uses the correct Claude Code format: [{ matcher, hooks: [{ type, command, timeout }] }]
13
- */
14
- function generateHooksConfig() {
15
- const hooksDir = platform_1.CLAUDE_HOOKS_DIR;
16
- if (platform_1.isWindows) {
17
- const ps = (name) => `powershell -ExecutionPolicy Bypass -File "${hooksDir}\\${name}.ps1"`;
18
- return {
19
- SessionStart: makeHook(ps('session-start')),
20
- UserPromptSubmit: makeHook(ps('user-prompt-submit')),
21
- Stop: makeHook(ps('stop')),
22
- };
23
- }
24
- // Unix uses bash
25
- const sh = (name) => `bash "${hooksDir}/${name}.sh"`;
26
- return {
27
- SessionStart: makeHook(sh('session-start')),
28
- UserPromptSubmit: makeHook(sh('user-prompt-submit')),
29
- Stop: makeHook(sh('stop')),
30
- };
31
- }
32
- /**
33
- * Deploy Claude Code settings.json with hooks configuration
13
+ * Deploy Claude Code settings.json no-op for hooks.
14
+ * Preserves any existing settings but does NOT write any hooks configuration.
34
15
  */
35
16
  function deployClaudeSettings() {
36
17
  // Ensure .claude directory exists
37
18
  if (!(0, fs_1.existsSync)(platform_1.CLAUDE_DIR)) {
38
19
  (0, fs_1.mkdirSync)(platform_1.CLAUDE_DIR, { recursive: true });
39
20
  }
40
- // Read existing settings or create new
41
- let settings = {};
42
- if ((0, fs_1.existsSync)(platform_1.CLAUDE_SETTINGS)) {
43
- try {
44
- settings = JSON.parse((0, fs_1.readFileSync)(platform_1.CLAUDE_SETTINGS, 'utf-8'));
45
- }
46
- catch {
47
- // Invalid JSON, start fresh
48
- }
21
+ // Read existing settings (if any) but do NOT add or modify hooks
22
+ if (!(0, fs_1.existsSync)(platform_1.CLAUDE_SETTINGS)) {
23
+ return; // Nothing to do — don't create an empty file
49
24
  }
50
- // Merge hooks config (preserving other settings)
51
- settings.hooks = generateHooksConfig();
52
- // Write settings
53
- (0, fs_1.writeFileSync)(platform_1.CLAUDE_SETTINGS, JSON.stringify(settings, null, 2));
54
- }
55
- /**
56
- * Check if hooks are configured in settings.json
57
- */
58
- function areHooksConfigured() {
59
- if (!(0, fs_1.existsSync)(platform_1.CLAUDE_SETTINGS))
60
- return false;
61
25
  try {
62
26
  const settings = JSON.parse((0, fs_1.readFileSync)(platform_1.CLAUDE_SETTINGS, 'utf-8'));
63
- const hooks = settings.hooks || {};
64
- return Boolean(hooks.SessionStart?.length &&
65
- hooks.UserPromptSubmit?.length &&
66
- hooks.Stop?.length);
27
+ // Remove any previously-installed ekkOS hooks entries
28
+ if ('hooks' in settings) {
29
+ delete settings.hooks;
30
+ (0, fs_1.writeFileSync)(platform_1.CLAUDE_SETTINGS, JSON.stringify(settings, null, 2));
31
+ }
67
32
  }
68
33
  catch {
69
- return false;
34
+ // Invalid JSON or read error — leave the file alone
70
35
  }
71
36
  }
37
+ /**
38
+ * @deprecated Hooks are no longer configured. Always returns false.
39
+ */
40
+ function areHooksConfigured() {
41
+ return false;
42
+ }
package/dist/index.js CHANGED
@@ -45,7 +45,8 @@ const run_1 = require("./commands/run");
45
45
  const test_claude_1 = require("./commands/test-claude");
46
46
  const doctor_1 = require("./commands/doctor");
47
47
  const stream_1 = require("./commands/stream");
48
- const hooks_1 = require("./commands/hooks");
48
+ // DEPRECATED: Hooks removed in hookless architecture migration
49
+ // hooksInstall, hooksVerify, hooksStatus no longer called — `hooks` command prints a deprecation notice.
49
50
  const setup_remote_1 = require("./commands/setup-remote");
50
51
  const agent_1 = require("./commands/agent");
51
52
  const state_1 = require("./utils/state");
@@ -169,7 +170,7 @@ commander_1.program
169
170
  { name: 'usage', desc: 'Token usage and cost tracking (daily, weekly, monthly, session)' },
170
171
  { name: 'dashboard', desc: 'Live TUI dashboard for session monitoring' },
171
172
  { name: 'stream', desc: 'Stream capture status and management' },
172
- { name: 'hooks', desc: 'Install, verify, and manage ekkOS hooks' },
173
+ { name: 'hooks', desc: '[DEPRECATED] Hooks no longer needed — use `ekkos run`' },
173
174
  ],
174
175
  },
175
176
  {
@@ -223,7 +224,7 @@ commander_1.program
223
224
  .option('-i, --ide <ide>', 'IDE to setup (claude, cursor, windsurf, all)')
224
225
  .option('-k, --key <key>', 'Use API key instead of device auth')
225
226
  .option('-f, --force', 'Force re-authentication and overwrite existing config')
226
- .option('--skip-hooks', 'Skip hook deployment')
227
+ .option('--skip-hooks', '[DEPRECATED] Hooks are no longer deployed; this flag is a no-op')
227
228
  .option('--skip-skills', 'Skip skills deployment')
228
229
  .action(init_1.init);
229
230
  // Status command
@@ -310,43 +311,20 @@ streamCmd
310
311
  .action(() => {
311
312
  (0, stream_1.streamList)();
312
313
  });
313
- // Hooks command - install, verify, status
314
- const hooksCmd = commander_1.program
314
+ // DEPRECATED: Hooks removed in hookless architecture migration
315
+ // The `hooks` command prints a deprecation notice directing users to `ekkos run`.
316
+ commander_1.program
315
317
  .command('hooks')
316
- .description('Manage ekkOS hooks (install, verify, status)');
317
- hooksCmd
318
- .command('install')
319
- .description('Install ekkOS hooks to ~/.claude/hooks/ (global) or project')
320
- .option('-g, --global', 'Install globally (default)')
321
- .option('-p, --project', 'Install to current project only')
322
- .option('-v, --verbose', 'Show detailed output')
323
- .action((options) => {
324
- (0, hooks_1.hooksInstall)({
325
- global: options.global !== false && !options.project,
326
- project: options.project,
327
- verbose: options.verbose
328
- });
329
- });
330
- hooksCmd
331
- .command('verify')
332
- .description('Verify hook installation and checksums')
333
- .option('-g, --global', 'Verify global installation (default)')
334
- .option('-p, --project', 'Verify project installation')
335
- .option('-v, --verbose', 'Show detailed output')
336
- .action(async (options) => {
337
- const result = await (0, hooks_1.hooksVerify)({
338
- global: options.global !== false && !options.project,
339
- project: options.project,
340
- verbose: options.verbose
341
- });
342
- process.exit(result.status === 'FAIL' ? 1 : 0);
343
- });
344
- hooksCmd
345
- .command('status')
346
- .description('Show hook installation status and enablement')
347
- .option('-v, --verbose', 'Show detailed output')
348
- .action((options) => {
349
- (0, hooks_1.hooksStatus)({ verbose: options.verbose });
318
+ .description('[DEPRECATED] Hooks are no longer needed. Use `ekkos run` instead.')
319
+ .allowUnknownOption()
320
+ .action(() => {
321
+ console.log('');
322
+ console.log(chalk_1.default.yellow(' Hooks are no longer needed.'));
323
+ console.log(chalk_1.default.white(' Use ') + chalk_1.default.cyan.bold('ekkos run') + chalk_1.default.white(' instead.'));
324
+ console.log('');
325
+ console.log(chalk_1.default.gray(' The hookless architecture routes everything through'));
326
+ console.log(chalk_1.default.gray(' the ekkOS proxy — no shell hooks required.'));
327
+ console.log('');
350
328
  });
351
329
  // Usage command - track Claude Code token usage and costs (powered by ccusage)
352
330
  (0, index_1.registerUsageCommand)(commander_1.program);
@@ -79,14 +79,19 @@ function uuidToWords(uuid) {
79
79
  if (!/^[0-9a-fA-F]+$/.test(hex)) {
80
80
  return 'unknown-session-starts';
81
81
  }
82
- // Use different 4-char segments for each word
82
+ // Use different 4-char segments for each word + 3-char segment for numeric suffix
83
83
  const adjSeed = parseInt(hex.slice(0, 4), 16);
84
84
  const nounSeed = parseInt(hex.slice(4, 8), 16);
85
85
  const verbSeed = parseInt(hex.slice(8, 12), 16);
86
86
  const adjIdx = adjSeed % ADJECTIVES.length;
87
87
  const nounIdx = nounSeed % NOUNS.length;
88
88
  const verbIdx = verbSeed % VERBS.length;
89
- return `${ADJECTIVES[adjIdx]}-${NOUNS[nounIdx]}-${VERBS[verbIdx]}`;
89
+ // Numeric suffix from additional hex chars to reduce collision risk
90
+ // 125k word combos × 1000 = 125M unique names
91
+ const fullHex = uuid.replace(/-/g, '');
92
+ const suffixHex = fullHex.slice(12, 15) || hex.slice(0, 3);
93
+ const suffix = String(parseInt(suffixHex, 16) % 1000).padStart(3, '0');
94
+ return `${ADJECTIVES[adjIdx]}-${NOUNS[nounIdx]}-${VERBS[verbIdx]}-${suffix}`;
90
95
  }
91
96
  /**
92
97
  * Ensure .ekkos directory exists and has required files
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekkos/cli",
3
- "version": "1.2.18",
3
+ "version": "1.3.0",
4
4
  "description": "Setup ekkOS memory for AI coding assistants (Claude Code, Cursor, Windsurf)",
5
5
  "main": "dist/index.js",
6
6
  "bin": {