@ekkos/cli 1.2.18 → 1.3.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/dist/cache/capture.js +0 -0
- package/dist/commands/dashboard.js +121 -66
- package/dist/commands/hooks.d.ts +25 -36
- package/dist/commands/hooks.js +43 -615
- package/dist/commands/init.js +7 -23
- package/dist/commands/run.js +90 -3
- package/dist/commands/setup.js +10 -352
- package/dist/deploy/hooks.d.ts +8 -5
- package/dist/deploy/hooks.js +12 -105
- package/dist/deploy/settings.d.ts +8 -2
- package/dist/deploy/settings.js +22 -51
- package/dist/index.js +17 -39
- package/dist/utils/state.js +7 -2
- package/package.json +1 -1
- package/templates/CLAUDE.md +82 -292
- package/templates/cursor-rules/ekkos-memory.md +48 -108
- package/templates/windsurf-rules/ekkos-memory.md +62 -64
- package/templates/cursor-hooks/after-agent-response.sh +0 -117
- package/templates/cursor-hooks/before-submit-prompt.sh +0 -419
- package/templates/cursor-hooks/hooks.json +0 -20
- package/templates/cursor-hooks/lib/contract.sh +0 -320
- package/templates/cursor-hooks/stop.sh +0 -75
- package/templates/hooks/assistant-response.ps1 +0 -256
- package/templates/hooks/assistant-response.sh +0 -160
- package/templates/hooks/hooks.json +0 -40
- package/templates/hooks/lib/contract.sh +0 -332
- package/templates/hooks/lib/count-tokens.cjs +0 -86
- package/templates/hooks/lib/ekkos-reminders.sh +0 -98
- package/templates/hooks/lib/state.sh +0 -210
- package/templates/hooks/session-start.ps1 +0 -146
- package/templates/hooks/session-start.sh +0 -353
- package/templates/hooks/stop.ps1 +0 -349
- package/templates/hooks/stop.sh +0 -382
- package/templates/hooks/user-prompt-submit.ps1 +0 -419
- package/templates/hooks/user-prompt-submit.sh +0 -516
- package/templates/project-stubs/session-start.ps1 +0 -63
- package/templates/project-stubs/session-start.sh +0 -55
- package/templates/project-stubs/stop.ps1 +0 -63
- package/templates/project-stubs/stop.sh +0 -55
- package/templates/project-stubs/user-prompt-submit.ps1 +0 -63
- package/templates/project-stubs/user-prompt-submit.sh +0 -55
- package/templates/windsurf-hooks/README.md +0 -212
- package/templates/windsurf-hooks/hooks.json +0 -17
- package/templates/windsurf-hooks/install.sh +0 -148
- package/templates/windsurf-hooks/lib/contract.sh +0 -322
- package/templates/windsurf-hooks/post-cascade-response.sh +0 -251
- package/templates/windsurf-hooks/pre-user-prompt.sh +0 -435
package/dist/deploy/hooks.js
CHANGED
|
@@ -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
|
-
*
|
|
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(
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
*
|
|
18
|
+
* @deprecated Hooks are no longer deployed. Always returns false.
|
|
97
19
|
*/
|
|
98
20
|
function areHooksDeployed() {
|
|
99
|
-
|
|
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
|
-
*
|
|
24
|
+
* @deprecated Hooks are no longer deployed. Always returns 0.
|
|
114
25
|
*/
|
|
115
26
|
function countDeployedHooks() {
|
|
116
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
12
|
+
* @deprecated Hooks are no longer configured. Always returns false.
|
|
7
13
|
*/
|
|
8
14
|
export declare function areHooksConfigured(): boolean;
|
package/dist/deploy/settings.js
CHANGED
|
@@ -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
|
-
*
|
|
12
|
-
*
|
|
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
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
hooks
|
|
66
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: '
|
|
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', '
|
|
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
|
|
314
|
-
|
|
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('
|
|
317
|
-
|
|
318
|
-
.
|
|
319
|
-
.
|
|
320
|
-
.
|
|
321
|
-
.
|
|
322
|
-
.
|
|
323
|
-
.
|
|
324
|
-
(
|
|
325
|
-
|
|
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);
|
package/dist/utils/state.js
CHANGED
|
@@ -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
|
-
|
|
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
|