@ekkos/cli 1.0.33 → 1.0.35

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 (51) hide show
  1. package/dist/capture/jsonl-rewriter.js +72 -7
  2. package/dist/commands/dashboard.js +186 -557
  3. package/dist/commands/init.js +3 -15
  4. package/dist/commands/run.js +221 -259
  5. package/dist/commands/setup.js +0 -47
  6. package/dist/commands/swarm-dashboard.js +4 -13
  7. package/dist/deploy/instructions.d.ts +2 -5
  8. package/dist/deploy/instructions.js +8 -11
  9. package/dist/deploy/settings.js +21 -15
  10. package/dist/deploy/skills.d.ts +0 -8
  11. package/dist/deploy/skills.js +0 -26
  12. package/dist/index.js +2 -2
  13. package/dist/lib/usage-parser.js +1 -2
  14. package/dist/utils/platform.d.ts +0 -3
  15. package/dist/utils/platform.js +1 -4
  16. package/dist/utils/session-binding.d.ts +1 -1
  17. package/dist/utils/session-binding.js +2 -3
  18. package/package.json +4 -2
  19. package/templates/CLAUDE.md +23 -135
  20. package/templates/agents/README.md +182 -0
  21. package/templates/agents/code-reviewer.md +166 -0
  22. package/templates/agents/debug-detective.md +169 -0
  23. package/templates/agents/ekkOS_Vercel.md +99 -0
  24. package/templates/agents/extension-manager.md +229 -0
  25. package/templates/agents/git-companion.md +185 -0
  26. package/templates/agents/github-test-agent.md +321 -0
  27. package/templates/agents/railway-manager.md +179 -0
  28. package/templates/ekkos-manifest.json +8 -8
  29. package/templates/hooks/assistant-response.ps1 +160 -256
  30. package/templates/hooks/assistant-response.sh +66 -130
  31. package/templates/hooks/hooks.json +0 -6
  32. package/templates/hooks/lib/contract.sh +31 -43
  33. package/templates/hooks/lib/count-tokens.cjs +0 -0
  34. package/templates/hooks/lib/ekkos-reminders.sh +0 -0
  35. package/templates/hooks/lib/state.sh +1 -53
  36. package/templates/hooks/session-start.ps1 +391 -91
  37. package/templates/hooks/session-start.sh +166 -201
  38. package/templates/hooks/stop.ps1 +341 -202
  39. package/templates/hooks/stop.sh +948 -275
  40. package/templates/hooks/user-prompt-submit.ps1 +548 -224
  41. package/templates/hooks/user-prompt-submit.sh +456 -382
  42. package/templates/plan-template.md +0 -0
  43. package/templates/spec-template.md +0 -0
  44. package/templates/windsurf-hooks/before-submit-prompt.sh +238 -0
  45. package/templates/windsurf-hooks/hooks.json +2 -9
  46. package/templates/windsurf-hooks/install.sh +0 -0
  47. package/templates/windsurf-hooks/lib/contract.sh +0 -2
  48. package/templates/windsurf-hooks/post-cascade-response.sh +0 -0
  49. package/templates/windsurf-hooks/pre-user-prompt.sh +0 -0
  50. package/templates/windsurf-skills/ekkos-memory/SKILL.md +219 -0
  51. package/README.md +0 -57
@@ -1,37 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
4
  };
@@ -384,20 +351,6 @@ async function setupWindsurf(apiKey) {
384
351
  (0, fs_1.mkdirSync)(windsurfDir, { recursive: true });
385
352
  }
386
353
  (0, fs_1.writeFileSync)((0, path_1.join)(windsurfDir, 'ekkos.json'), JSON.stringify({ apiKey }, null, 2));
387
- // Deploy Windsurf skills (Agent Skills spec — 6 Golden Loop skills)
388
- const skillsDir = (0, path_1.join)(codeiumDir, 'skills');
389
- if (!(0, fs_1.existsSync)(skillsDir)) {
390
- (0, fs_1.mkdirSync)(skillsDir, { recursive: true });
391
- }
392
- try {
393
- const { deployWindsurfSkills } = await Promise.resolve().then(() => __importStar(require('../deploy/skills.js')));
394
- const result = deployWindsurfSkills();
395
- console.log(chalk_1.default.green(` ✓ Deployed ${result.count} skills: ${result.skills.join(', ')}`));
396
- }
397
- catch {
398
- // Fallback: templates might not be available in setup path
399
- console.log(chalk_1.default.yellow(' Note: Skills templates not found. Run `ekkos init --ide windsurf` to deploy skills.'));
400
- }
401
354
  // Create project rules template
402
355
  const cascadeRules = generateCascadeRules();
403
356
  const cascadeRulesPath = (0, path_1.join)(process.cwd(), '.windsurfrules');
@@ -582,19 +582,10 @@ async function launchSwarmDashboard(launchTs, refreshMs) {
582
582
  // ── Usage window (Anthropic OAuth) ──
583
583
  async function fetchAnthropicUsage() {
584
584
  try {
585
- let token = null;
586
- if (process.platform === 'darwin') {
587
- const { execSync } = require('child_process');
588
- const credsJson = execSync('security find-generic-password -s "Claude Code-credentials" -w', { encoding: 'utf-8', timeout: 5000 }).trim();
589
- token = JSON.parse(credsJson)?.claudeAiOauth?.accessToken ?? null;
590
- }
591
- else if (process.platform === 'win32') {
592
- const credsPath = path.join(os.homedir(), '.claude', '.credentials.json');
593
- if (require('fs').existsSync(credsPath)) {
594
- const creds = JSON.parse(require('fs').readFileSync(credsPath, 'utf-8'));
595
- token = creds?.claudeAiOauth?.accessToken ?? null;
596
- }
597
- }
585
+ const { execSync } = require('child_process');
586
+ const credsJson = execSync('security find-generic-password -s "Claude Code-credentials" -w', { encoding: 'utf-8', timeout: 5000 }).trim();
587
+ const creds = JSON.parse(credsJson);
588
+ const token = creds?.claudeAiOauth?.accessToken;
598
589
  if (!token)
599
590
  return null;
600
591
  const resp = await fetch('https://api.anthropic.com/api/oauth/usage', {
@@ -1,12 +1,9 @@
1
1
  /**
2
- * Deploy ekkOS instructions to ~/.claude/rules/ekkos.md
3
- *
4
- * Uses Claude Code's user-level rules directory — auto-loaded for all projects
5
- * without touching the user's existing CLAUDE.md.
2
+ * Deploy CLAUDE.md to ~/.claude/CLAUDE.md
6
3
  */
7
4
  export declare function deployInstructions(): void;
8
5
  /**
9
- * Check if ekkOS instructions are deployed
6
+ * Check if CLAUDE.md is deployed
10
7
  */
11
8
  export declare function isInstructionsDeployed(): boolean;
12
9
  /**
@@ -7,24 +7,21 @@ const fs_1 = require("fs");
7
7
  const platform_1 = require("../utils/platform");
8
8
  const templates_1 = require("../utils/templates");
9
9
  /**
10
- * Deploy ekkOS instructions to ~/.claude/rules/ekkos.md
11
- *
12
- * Uses Claude Code's user-level rules directory — auto-loaded for all projects
13
- * without touching the user's existing CLAUDE.md.
10
+ * Deploy CLAUDE.md to ~/.claude/CLAUDE.md
14
11
  */
15
12
  function deployInstructions() {
16
- // Ensure ~/.claude/rules/ exists
17
- if (!(0, fs_1.existsSync)(platform_1.CLAUDE_RULES_DIR)) {
18
- (0, fs_1.mkdirSync)(platform_1.CLAUDE_RULES_DIR, { recursive: true });
13
+ // Ensure .claude directory exists
14
+ if (!(0, fs_1.existsSync)(platform_1.CLAUDE_DIR)) {
15
+ (0, fs_1.mkdirSync)(platform_1.CLAUDE_DIR, { recursive: true });
19
16
  }
20
- // Deploy to rules/ekkos.md (safe to overwrite — this is our file)
21
- (0, templates_1.copyTemplateFile)('CLAUDE.md', platform_1.CLAUDE_EKKOS_RULES);
17
+ // Copy CLAUDE.md template
18
+ (0, templates_1.copyTemplateFile)('CLAUDE.md', platform_1.CLAUDE_MD);
22
19
  }
23
20
  /**
24
- * Check if ekkOS instructions are deployed
21
+ * Check if CLAUDE.md is deployed
25
22
  */
26
23
  function isInstructionsDeployed() {
27
- return (0, fs_1.existsSync)(platform_1.CLAUDE_EKKOS_RULES);
24
+ return (0, fs_1.existsSync)(platform_1.CLAUDE_MD);
28
25
  }
29
26
  /**
30
27
  * Get the CLAUDE.md content (for preview)
@@ -3,38 +3,43 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deployClaudeSettings = deployClaudeSettings;
4
4
  exports.areHooksConfigured = areHooksConfigured;
5
5
  const fs_1 = require("fs");
6
- const path_1 = require("path");
7
6
  const platform_1 = require("../utils/platform");
8
7
  /**
9
8
  * Generate the hooks configuration for Claude Code settings.json
10
- * Uses the new format required by Claude Code 2.1.40+
11
9
  */
12
10
  function generateHooksConfig() {
13
- // Use path.join (via CLAUDE_HOOKS_DIR) so OS-correct separators are used.
14
- // JSON.stringify handles backslash-escaping automatically — do NOT pre-escape.
15
- //
16
- // IMPORTANT: Do NOT use `-File` on Windows — Claude Code has a known bug where
17
- // it fails to canonicalize absolute script paths, producing "system cannot find
18
- // the specified path". Use `-Command "& 'path'"` instead, which bypasses it.
19
- // See: https://github.com/anthropics/claude-code/issues/12874
11
+ const hooksDir = `${platform_1.HOME_DIR}/.claude/hooks`;
20
12
  if (platform_1.isWindows) {
13
+ // Windows uses PowerShell
21
14
  return {
15
+ SessionStart: [
16
+ { type: 'command', command: `powershell -ExecutionPolicy Bypass -File "${hooksDir}/session-start.ps1"` }
17
+ ],
22
18
  UserPromptSubmit: [
23
- { hooks: [{ type: 'command', command: `powershell -ExecutionPolicy Bypass -Command "& '${(0, path_1.join)(platform_1.CLAUDE_HOOKS_DIR, 'user-prompt-submit.ps1')}'"` }] }
19
+ { type: 'command', command: `powershell -ExecutionPolicy Bypass -File "${hooksDir}/user-prompt-submit.ps1"` }
24
20
  ],
25
21
  Stop: [
26
- { hooks: [{ type: 'command', command: `powershell -ExecutionPolicy Bypass -Command "& '${(0, path_1.join)(platform_1.CLAUDE_HOOKS_DIR, 'stop.ps1')}'"` }] }
22
+ { type: 'command', command: `powershell -ExecutionPolicy Bypass -File "${hooksDir}/stop.ps1"` }
27
23
  ],
24
+ AssistantResponse: [
25
+ { type: 'command', command: `powershell -ExecutionPolicy Bypass -File "${hooksDir}/assistant-response.ps1"` }
26
+ ]
28
27
  };
29
28
  }
30
- // Unix: forward slashes, no quoting needed
29
+ // Unix uses bash
31
30
  return {
31
+ SessionStart: [
32
+ { type: 'command', command: `bash ${hooksDir}/session-start.sh` }
33
+ ],
32
34
  UserPromptSubmit: [
33
- { hooks: [{ type: 'command', command: `bash ${(0, path_1.join)(platform_1.CLAUDE_HOOKS_DIR, 'user-prompt-submit.sh')}` }] }
35
+ { type: 'command', command: `bash ${hooksDir}/user-prompt-submit.sh` }
34
36
  ],
35
37
  Stop: [
36
- { hooks: [{ type: 'command', command: `bash ${(0, path_1.join)(platform_1.CLAUDE_HOOKS_DIR, 'stop.sh')}` }] }
38
+ { type: 'command', command: `bash ${hooksDir}/stop.sh` }
37
39
  ],
40
+ AssistantResponse: [
41
+ { type: 'command', command: `bash ${hooksDir}/assistant-response.sh` }
42
+ ]
38
43
  };
39
44
  }
40
45
  /**
@@ -69,7 +74,8 @@ function areHooksConfigured() {
69
74
  try {
70
75
  const settings = JSON.parse((0, fs_1.readFileSync)(platform_1.CLAUDE_SETTINGS, 'utf-8'));
71
76
  const hooks = settings.hooks || {};
72
- return Boolean(hooks.UserPromptSubmit?.length &&
77
+ return Boolean(hooks.SessionStart?.length &&
78
+ hooks.UserPromptSubmit?.length &&
73
79
  hooks.Stop?.length);
74
80
  }
75
81
  catch {
@@ -5,14 +5,6 @@ export declare function deploySkills(): {
5
5
  count: number;
6
6
  skills: string[];
7
7
  };
8
- /**
9
- * Deploy Windsurf skills to ~/.codeium/windsurf/skills/
10
- * Uses Agent Skills spec format (lowercase-hyphenated names, SKILL.md)
11
- */
12
- export declare function deployWindsurfSkills(): {
13
- count: number;
14
- skills: string[];
15
- };
16
8
  /**
17
9
  * Check if skills are deployed
18
10
  */
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deploySkills = deploySkills;
4
- exports.deployWindsurfSkills = deployWindsurfSkills;
5
4
  exports.areSkillsDeployed = areSkillsDeployed;
6
5
  exports.countDeployedSkills = countDeployedSkills;
7
6
  exports.listExpectedSkills = listExpectedSkills;
@@ -33,31 +32,6 @@ function deploySkills() {
33
32
  skills: deployedSkills
34
33
  };
35
34
  }
36
- /**
37
- * Deploy Windsurf skills to ~/.codeium/windsurf/skills/
38
- * Uses Agent Skills spec format (lowercase-hyphenated names, SKILL.md)
39
- */
40
- function deployWindsurfSkills() {
41
- if (!(0, fs_1.existsSync)(platform_1.WINDSURF_SKILLS_DIR)) {
42
- (0, fs_1.mkdirSync)(platform_1.WINDSURF_SKILLS_DIR, { recursive: true });
43
- }
44
- const skillNames = (0, templates_1.listTemplateDirs)('windsurf-skills');
45
- const deployedSkills = [];
46
- for (const skillName of skillNames) {
47
- try {
48
- const destPath = `${platform_1.WINDSURF_SKILLS_DIR}/${skillName}`;
49
- (0, templates_1.copyTemplateDir)(`windsurf-skills/${skillName}`, destPath);
50
- deployedSkills.push(skillName);
51
- }
52
- catch (error) {
53
- console.warn(`Warning: Could not deploy Windsurf skill ${skillName}`);
54
- }
55
- }
56
- return {
57
- count: deployedSkills.length,
58
- skills: deployedSkills
59
- };
60
- }
61
35
  /**
62
36
  * Check if skills are deployed
63
37
  */
package/dist/index.js CHANGED
@@ -246,10 +246,10 @@ commander_1.program
246
246
  .option('-d, --doctor', 'Run diagnostics before starting')
247
247
  .option('-r, --research', 'Auto-run research agent on startup (scans arXiv for new AI papers)')
248
248
  .option('--skip-inject', 'Monitor-only mode (detect context wall but print instructions instead of auto-inject)')
249
- .option('--skip-dna', 'Deprecated no-op (legacy ccDNA patching has been removed)')
249
+ .option('--skip-dna', 'Skip ccDNA injection (bypass Claude Code patching)')
250
250
  .option('--skip-proxy', 'Skip API proxy (use direct Anthropic API, disables seamless context eviction)')
251
251
  .option('--dashboard', 'Launch with live usage dashboard in an isolated 60/40 tmux split (requires tmux)')
252
- .option('--kickstart', 'Auto-send "test" on load to create session immediately (manual/debug use)')
252
+ .option('--kickstart', 'Auto-send "test" on load to create session immediately (used internally by --dashboard)')
253
253
  .option('--add-dir <dirs...>', 'Additional directories Claude Code can access (outside working directory)')
254
254
  .action((options) => {
255
255
  (0, run_1.run)({
@@ -79,8 +79,7 @@ function isEkkosSessionName(name) {
79
79
  return /^[a-z]+-[a-z]+-[a-z]+$/.test(name);
80
80
  }
81
81
  function encodeProjectPath(projectPath) {
82
- // Replace all path separators (and Windows drive colon) with '-'
83
- return projectPath.replace(/[:\\/]/g, '-');
82
+ return projectPath.replace(/\//g, '-');
84
83
  }
85
84
  /** Resolve an ekkOS session name to a JSONL UUID */
86
85
  function resolveSessionName(name) {
@@ -15,13 +15,10 @@ export declare const CLAUDE_AGENTS_DIR: string;
15
15
  export declare const CLAUDE_PLUGINS_DIR: string;
16
16
  export declare const CLAUDE_STATE_DIR: string;
17
17
  export declare const CLAUDE_MD: string;
18
- export declare const CLAUDE_RULES_DIR: string;
19
- export declare const CLAUDE_EKKOS_RULES: string;
20
18
  export declare const CURSOR_DIR: string;
21
19
  export declare const CURSOR_MCP: string;
22
20
  export declare const WINDSURF_DIR: string;
23
21
  export declare const WINDSURF_MCP: string;
24
- export declare const WINDSURF_SKILLS_DIR: string;
25
22
  /**
26
23
  * Detect which IDEs are installed on this system
27
24
  */
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WINDSURF_SKILLS_DIR = exports.WINDSURF_MCP = exports.WINDSURF_DIR = exports.CURSOR_MCP = exports.CURSOR_DIR = exports.CLAUDE_EKKOS_RULES = exports.CLAUDE_RULES_DIR = exports.CLAUDE_MD = exports.CLAUDE_STATE_DIR = exports.CLAUDE_PLUGINS_DIR = exports.CLAUDE_AGENTS_DIR = exports.CLAUDE_SKILLS_DIR = exports.CLAUDE_HOOKS_DIR = exports.CLAUDE_SETTINGS = exports.CLAUDE_CONFIG = exports.CLAUDE_DIR = exports.EKKOS_CONFIG = exports.EKKOS_DIR = exports.HOME_DIR = exports.MCP_API_URL = exports.PLATFORM_URL = exports.isLinux = exports.isMac = exports.isWindows = void 0;
3
+ exports.WINDSURF_MCP = exports.WINDSURF_DIR = exports.CURSOR_MCP = exports.CURSOR_DIR = exports.CLAUDE_MD = exports.CLAUDE_STATE_DIR = exports.CLAUDE_PLUGINS_DIR = exports.CLAUDE_AGENTS_DIR = exports.CLAUDE_SKILLS_DIR = exports.CLAUDE_HOOKS_DIR = exports.CLAUDE_SETTINGS = exports.CLAUDE_CONFIG = exports.CLAUDE_DIR = exports.EKKOS_CONFIG = exports.EKKOS_DIR = exports.HOME_DIR = exports.MCP_API_URL = exports.PLATFORM_URL = exports.isLinux = exports.isMac = exports.isWindows = void 0;
4
4
  exports.detectInstalledIDEs = detectInstalledIDEs;
5
5
  exports.detectCurrentIDE = detectCurrentIDE;
6
6
  const os_1 = require("os");
@@ -24,13 +24,10 @@ exports.CLAUDE_AGENTS_DIR = (0, path_1.join)(exports.CLAUDE_DIR, 'agents');
24
24
  exports.CLAUDE_PLUGINS_DIR = (0, path_1.join)(exports.CLAUDE_DIR, 'plugins', 'ekkos');
25
25
  exports.CLAUDE_STATE_DIR = (0, path_1.join)(exports.CLAUDE_DIR, 'state');
26
26
  exports.CLAUDE_MD = (0, path_1.join)(exports.CLAUDE_DIR, 'CLAUDE.md');
27
- exports.CLAUDE_RULES_DIR = (0, path_1.join)(exports.CLAUDE_DIR, 'rules');
28
- exports.CLAUDE_EKKOS_RULES = (0, path_1.join)(exports.CLAUDE_RULES_DIR, 'ekkos.md');
29
27
  exports.CURSOR_DIR = (0, path_1.join)(exports.HOME_DIR, '.cursor');
30
28
  exports.CURSOR_MCP = (0, path_1.join)(exports.CURSOR_DIR, 'mcp.json');
31
29
  exports.WINDSURF_DIR = (0, path_1.join)(exports.HOME_DIR, '.codeium', 'windsurf');
32
30
  exports.WINDSURF_MCP = (0, path_1.join)(exports.WINDSURF_DIR, 'mcp_config.json');
33
- exports.WINDSURF_SKILLS_DIR = (0, path_1.join)(exports.WINDSURF_DIR, 'skills');
34
31
  /**
35
32
  * Detect which IDEs are installed on this system
36
33
  */
@@ -2,4 +2,4 @@
2
2
  * Bind the real session name to the proxy
3
3
  * This replaces the '_pending' placeholder for this user, enabling proper eviction
4
4
  */
5
- export declare function bindSession(realSession: string, projectPath: string, pendingSession?: string): Promise<boolean>;
5
+ export declare function bindSession(realSession: string, projectPath: string): Promise<boolean>;
@@ -7,7 +7,7 @@ const MEMORY_API_URL = process.env.EKKOS_PROXY_URL || 'https://proxy.ekkos.dev';
7
7
  * Bind the real session name to the proxy
8
8
  * This replaces the '_pending' placeholder for this user, enabling proper eviction
9
9
  */
10
- async function bindSession(realSession, projectPath, pendingSession) {
10
+ async function bindSession(realSession, projectPath) {
11
11
  try {
12
12
  // Get userId same way as run.ts
13
13
  const config = (0, state_1.getConfig)();
@@ -33,8 +33,7 @@ async function bindSession(realSession, projectPath, pendingSession) {
33
33
  body: JSON.stringify({
34
34
  userId,
35
35
  realSession,
36
- projectPath,
37
- pendingSession: pendingSession || null,
36
+ projectPath
38
37
  })
39
38
  });
40
39
  return response.ok;
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@ekkos/cli",
3
- "version": "1.0.33",
3
+ "version": "1.0.35",
4
4
  "description": "Setup ekkOS memory for AI coding assistants (Claude Code, Cursor, Windsurf)",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "ekkos": "dist/index.js",
8
8
  "cli": "dist/index.js",
9
- "ekkos-capture": "dist/cache/capture.js"
9
+ "ekkos-capture": "dist/cache/capture.js",
10
+ "ekkos-promote": "dist/cron/promoter.js"
10
11
  },
11
12
  "scripts": {
12
13
  "build": "tsc",
@@ -28,6 +29,7 @@
28
29
  "author": "ekkOS",
29
30
  "license": "MIT",
30
31
  "dependencies": {
32
+ "@ekkos/prometheus": "*",
31
33
  "@supabase/supabase-js": "^2.39.8",
32
34
  "blessed": "^0.1.81",
33
35
  "blessed-contrib": "^4.11.0",
@@ -53,28 +53,6 @@ After `/clear`, when you see restored turns in `<system-reminder>` (pattern: `**
53
53
  ```
54
54
  This is the ONLY way users see that restoration worked. Hook output is invisible to them.
55
55
 
56
- ### RULE 6: AUTO-RESTORE AFTER COMPACTION (CONTEXT GUARDIAN)
57
- When you see `<ekkos-context-preserved>` in the conversation (appears after auto-compaction):
58
- 1. **IMMEDIATELY** call `ekkOS_RestoreContext` with the `restoration_token` from the tag
59
- 2. This restores your working memory that was preserved before compaction
60
- 3. Start your response with:
61
- ```
62
- ✓ **Context restored** - ekkOS preserved X turns before compaction
63
- ```
64
-
65
- **This is how seamless context continuity works:**
66
- - PreCompact hook fires → ekkOS_PreserveContext saves your state
67
- - Claude Code compacts → Summary includes the preservation tag
68
- - You see the tag → Call ekkOS_RestoreContext → Full context restored
69
- - User experiences zero knowledge loss despite compaction
70
-
71
- **Example restoration call:**
72
- ```
73
- ekkOS_RestoreContext({
74
- restoration_token: "<token from tag>"
75
- })
76
- ```
77
-
78
56
  ---
79
57
 
80
58
  ## SKILL TRIGGERS (MANDATORY)
@@ -101,7 +79,8 @@ Call skills using `Skill(skill: "name")` when you detect these triggers:
101
79
  | Trigger Keywords | Agent | When to Use |
102
80
  |------------------|-------|-------------|
103
81
  | extension, vsix, publish, marketplace, ekkos-connect | `extension-manager` | Version bumps, VSIX builds, publishing |
104
- | vercel, deploy, apps/*, ekkos.dev, api.ekkos.dev | `devops` | Vercel deployments ALL apps/ deploy to Vercel |
82
+ | vercel, deploy to vercel, platform.ekkos.dev, apps/web | `devops` | Vercel deployments (link + archive mode) |
83
+ | deploy, railway, workers, pm2, restart, logs, queue | `railway-manager` | Railway deployments, service management |
105
84
  | commit, push, branch, merge, git, pull request, rebase | `git-companion` | All git operations |
106
85
  | error, bug, broken, not working, failing, crash | `debug-detective` | Systematic debugging |
107
86
  | review, PR, check this code, code quality | `code-reviewer` | Code reviews |
@@ -110,25 +89,6 @@ Call skills using `Skill(skill: "name")` when you detect these triggers:
110
89
  | backend, API, database, Supabase, RLS | `backend` | API and database work |
111
90
  | test, QA, quality, coverage | `qa` | Testing and quality assurance |
112
91
  | plan, architect, design, implement feature | `tech-lead` | Complex planning and coordination |
113
- | research, papers, arXiv, cutting edge, latest AI | `research-scout` | Monitor AI research, update roadmap |
114
-
115
- **Vercel Project Mapping** (apps/ folder → Vercel project → URL):
116
-
117
- | apps/ folder | Vercel project | Production URL |
118
- |-------------|----------------|----------------|
119
- | `apps/web` | **platform** | platform.ekkos.dev |
120
- | `apps/memory` | memory | api.ekkos.dev |
121
- | `apps/proxy` | proxy | proxy.ekkos.dev |
122
- | `apps/docs` | docs | docs.ekkos.dev |
123
- | `apps/marketing` | marketing | ekkos.dev |
124
- | `apps/ekkosca` | ekkosca | ekkos.ca |
125
- | `apps/blog` | blog | blog.ekkos.dev |
126
- | `apps/support` | support | support.ekkos.dev |
127
- | `apps/labs` | labs | ekkoslabs.com |
128
- | `apps/admin` | admin | admin.ekkos.ca |
129
- | `apps/sdk` | sdk | sdk-ekkos.vercel.app |
130
-
131
- **NOTE:** `apps/web` → Vercel project name is `platform`, NOT `web`.
132
92
 
133
93
  **How it works:**
134
94
  1. Detect trigger keywords in user request
@@ -149,55 +109,39 @@ You: Task(subagent_type="extension-manager", prompt="Bump version...")
149
109
 
150
110
  ---
151
111
 
152
- ## MCP Tools (68 Total)
112
+ ## MCP Tools (31 Total)
153
113
 
154
- ### Core Memory Tools (7)
114
+ ### Core Memory Tools
155
115
  | Tool | Description |
156
116
  |------|-------------|
157
117
  | `ekkOS_Search` | 🔴 REQUIRED: Search all 11 layers before answering |
158
- | `ekkOS_ExpandPattern` | Get full details of a pattern from compact search results |
118
+ | `ekkOS_Context` | Get relevant context for a task |
159
119
  | `ekkOS_Capture` | Capture memory events |
160
120
  | `ekkOS_Forge` | 🔴 REQUIRED: Create pattern from solution |
161
- | `ekkOS_Track` | Track when pattern is applied |
121
+ | `ekkOS_Directive` | 🔴 REQUIRED: Create MUST/NEVER/PREFER/AVOID rules |
162
122
  | `ekkOS_Outcome` | Track if pattern worked or failed |
163
- | `ekkOS_Stats` | Get statistics for all layers |
164
-
165
- ### Context & Retrieval Tools (5)
166
- | Tool | Description |
167
- |------|-------------|
168
- | `ekkOS_Context` | Get relevant context for a task |
169
- | `ekkOS_Codebase` | Search project code embeddings |
170
- | `ekkOS_Recall` | Recall past conversations by time |
171
- | `ekkOS_PreserveContext` | 🔴 REQUIRED: Preserve working memory before compaction |
172
- | `ekkOS_RestoreContext` | 🔴 REQUIRED: Restore context after compaction (RULE 6) |
173
-
174
- ### Utility Tools (8)
175
- | Tool | Description |
176
- |------|-------------|
123
+ | `ekkOS_Detect` | 🔴 REQUIRED: Auto-detect which patterns were used |
177
124
  | `ekkOS_Summary` | 🔴 REQUIRED: Get summary of MCP activity |
178
125
  | `ekkOS_Conflict` | 🔴 REQUIRED: Check for conflicts before destructive actions |
126
+ | `ekkOS_Recall` | Recall past conversations by time |
127
+ | `ekkOS_Codebase` | Search project code embeddings |
128
+ | `ekkOS_Stats` | Get statistics for all layers |
129
+ | `ekkOS_Track` | Track when pattern is applied |
179
130
  | `ekkOS_Reflect` | Analyze response for improvement opportunities |
180
- | `ekkOS_Detect` | 🔴 REQUIRED: Auto-detect which patterns were used |
181
- | `ekkOS_Export` | Export your patterns, directives, plans as portable JSON backup |
182
- | `ekkOS_Import` | Import memory from backup (auto-deduplication) |
183
- | `ekkOS_Why` | Explain why a pattern or decision was made |
184
- | `ekkOS_Health` | System health check for ekkOS infrastructure |
185
131
 
186
- ### Directive Tools (4)
132
+ ### Schema Awareness Tools
187
133
  | Tool | Description |
188
134
  |------|-------------|
189
- | `ekkOS_Directive` | 🔴 REQUIRED: Create MUST/NEVER/PREFER/AVOID rules |
190
- | `ekkOS_UpdateDirective` | Update existing directive |
191
- | `ekkOS_DeleteDirective` | Remove a directive |
192
- | `ekkOS_UniversalDirectives` | Get directives that apply to all users (constitutional) |
135
+ | `ekkOS_IndexSchema` | Index database schemas (Supabase, Prisma, TypeScript) |
136
+ | `ekkOS_GetSchema` | Get schema for a specific table/type |
193
137
 
194
- ### Schema Awareness Tools (2)
138
+ ### Portability Tools
195
139
  | Tool | Description |
196
140
  |------|-------------|
197
- | `ekkOS_IndexSchema` | Index database schemas (Supabase, Prisma, TypeScript) |
198
- | `ekkOS_GetSchema` | Get schema for a specific table/type |
141
+ | `ekkOS_Export` | Export your patterns, directives, plans as portable JSON backup |
142
+ | `ekkOS_Import` | Import memory from backup (auto-deduplication) |
199
143
 
200
- ### Plan Management (8)
144
+ ### Plan Management
201
145
  | Tool | Description |
202
146
  |------|-------------|
203
147
  | `ekkOS_Plan` | Create structured task plan |
@@ -209,7 +153,7 @@ You: Task(subagent_type="extension-manager", prompt="Bump version...")
209
153
  | `ekkOS_Templates` | List available templates |
210
154
  | `ekkOS_FromTemplate` | Create plan from template |
211
155
 
212
- ### Secrets Management (5)
156
+ ### Secrets Management (Layer 11)
213
157
  | Tool | Description |
214
158
  |------|-------------|
215
159
  | `ekkOS_StoreSecret` | Encrypt and store sensitive data (AES-256-GCM) |
@@ -218,39 +162,6 @@ You: Task(subagent_type="extension-manager", prompt="Bump version...")
218
162
  | `ekkOS_DeleteSecret` | Permanently delete a secret |
219
163
  | `ekkOS_RotateSecret` | Update secret with new value |
220
164
 
221
- ### Project/Sync Tools (4)
222
- | Tool | Description |
223
- |------|-------------|
224
- | `ekkOS_ProjectInit` | Initialize ekkOS for a new project |
225
- | `ekkOS_Ingest` | Bulk ingest data into memory layers |
226
- | `ekkOS_Snapshot` | Create point-in-time snapshot of memory state |
227
- | `ekkOS_Sync` | Sync local and cloud memory state |
228
-
229
- ### Session Management (1)
230
- | Tool | Description |
231
- |------|-------------|
232
- | `ekkOS_Session` | Manage L1 Working Memory sessions (start/resume/end) |
233
-
234
- ### Learning Tools (2)
235
- | Tool | Description |
236
- |------|-------------|
237
- | `ekkOS_Learn` | Auto-learning from corrections, successes, observations |
238
- | `ekkOS_ReviewLearning` | Review pending learning candidates, approve/reject patterns |
239
-
240
- ### Relationship Tools (2)
241
- | Tool | Description |
242
- |------|-------------|
243
- | `ekkOS_Link` | Create relationships between patterns |
244
- | `ekkOS_Playbook` | Manage ordered sequences of patterns (workflows) |
245
-
246
- ### PROMETHEUS Tools (4)
247
- | Tool | Description |
248
- |------|-------------|
249
- | `ekkOS_Delta` | Compute improvement score using Δ_prometheus formula |
250
- | `ekkOS_MetaState` | System introspection ("I know what I know") |
251
- | `ekkOS_Goal` | Manage persistent objectives and success criteria |
252
- | `ekkOS_Strategy` | Context-aware strategy selection for tasks |
253
-
254
165
  ---
255
166
 
256
167
  ## Proactive Tool Triggers (MEMORIZE THESE)
@@ -293,28 +204,6 @@ You: Task(subagent_type="extension-manager", prompt="Bump version...")
293
204
  - Need to retrieve stored credentials
294
205
  - User asks "do you have my X key?"
295
206
 
296
- ### Always Use Context Preservation When:
297
- - PreCompact hook fires (auto-triggered)
298
- - See `<ekkos-context-preserved>` tag (auto-restore)
299
- - RULE 6 activation
300
-
301
- ### Always Use Learning Tools When:
302
- - User corrects you (ekkOS_Learn mode: correction)
303
- - Solution succeeds (ekkOS_Learn mode: success)
304
- - Discover insight (ekkOS_Learn mode: observe)
305
- - Review pending patterns (ekkOS_ReviewLearning)
306
-
307
- ### Always Use Relationship Tools When:
308
- - Patterns are sequential (ekkOS_Link type: leads_to)
309
- - Creating workflows (ekkOS_Playbook)
310
- - Patterns are alternatives (ekkOS_Link type: alternative)
311
-
312
- ### Always Use PROMETHEUS Tools When:
313
- - Evaluating system improvement (ekkOS_Delta)
314
- - Self-assessment needed (ekkOS_MetaState)
315
- - Setting objectives (ekkOS_Goal)
316
- - Choosing approach (ekkOS_Strategy)
317
-
318
207
  ---
319
208
 
320
209
  ## 11-Layer Memory Architecture
@@ -364,21 +253,20 @@ Call `ekkOS_Directive` when user says:
364
253
  **EVERY response MUST end with this footer:**
365
254
  ```
366
255
  ---
367
- {IDE} ({Model}) · 🧠 **ekkOS_™** · Turn {N} · {SessionName} · 📅 {Timestamp}
256
+ {IDE} ({Model}) · 🧠 **ekkOS_™** · Turn {N} · 📅 {Timestamp}
368
257
  ```
369
258
 
370
259
  **How to detect values:**
371
260
  - **IDE**: Claude Code, Cursor, Windsurf, etc. (from environment)
372
261
  - **Model**: Sonnet 4.5, Opus 4.5, etc. (from your model name)
373
262
  - **Turn Number**: From hook header (e.g., "Turn 47") - starts at 0 for each new session
374
- - **Session Name**: From hook header (e.g., "sol-gem-dig") - human-readable session identifier
375
263
  - **Timestamp**: From hook header (accurate local time in EST)
376
264
 
377
265
  **Examples:**
378
- - `Claude Code (Sonnet 4.5) · 🧠 **ekkOS_™** · Turn 12 · cosmic-penguin-runs · 📅 2026-01-09 4:50 PM EST`
379
- - `Cursor (Claude Sonnet 4) · 🧠 **ekkOS_™** · Turn 5 · bright-falcon-soars · 📅 2026-01-09 10:15 AM EST`
266
+ - `Claude Code (Sonnet 4.5) · 🧠 **ekkOS_™** · Turn 12 · 📅 2026-01-09 4:50 PM EST`
267
+ - `Cursor (Claude Sonnet 4) · 🧠 **ekkOS_™** · Turn 5 · 📅 2026-01-09 10:15 AM EST`
380
268
 
381
- **The hook header shows:** `🧠 ekkOS Memory | Turn {N} | {Context%} | {SessionName} | {timestamp}`
269
+ **The hook header shows:** `🧠 ekkOS Memory | Turn {N} | Session: {ID} | {timestamp}`
382
270
 
383
271
  ---
384
272