@ekkos/cli 1.3.2 → 1.3.6

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 (123) hide show
  1. package/dist/capture/jsonl-rewriter.d.ts +1 -1
  2. package/dist/capture/jsonl-rewriter.js +3 -3
  3. package/dist/capture/transcript-repair.d.ts +2 -2
  4. package/dist/capture/transcript-repair.js +2 -2
  5. package/dist/commands/claw.d.ts +13 -0
  6. package/dist/commands/claw.js +253 -0
  7. package/dist/commands/dashboard.js +617 -83
  8. package/dist/commands/doctor.d.ts +3 -3
  9. package/dist/commands/doctor.js +6 -79
  10. package/dist/commands/gemini.d.ts +19 -0
  11. package/dist/commands/gemini.js +193 -0
  12. package/dist/commands/init.js +2 -25
  13. package/dist/commands/run.d.ts +0 -1
  14. package/dist/commands/run.js +147 -241
  15. package/dist/commands/scan.d.ts +21 -0
  16. package/dist/commands/scan.js +386 -0
  17. package/dist/commands/swarm-dashboard.js +156 -28
  18. package/dist/commands/swarm.d.ts +1 -1
  19. package/dist/commands/swarm.js +1 -1
  20. package/dist/commands/test-claude.d.ts +2 -2
  21. package/dist/commands/test-claude.js +3 -3
  22. package/dist/deploy/index.d.ts +0 -2
  23. package/dist/deploy/index.js +0 -2
  24. package/dist/deploy/settings.d.ts +2 -2
  25. package/dist/deploy/settings.js +42 -4
  26. package/dist/deploy/skills.js +1 -2
  27. package/dist/index.js +79 -19
  28. package/dist/lib/usage-parser.js +5 -4
  29. package/dist/utils/proxy-url.d.ts +12 -1
  30. package/dist/utils/proxy-url.js +16 -1
  31. package/dist/utils/templates.js +1 -1
  32. package/package.json +4 -6
  33. package/templates/CLAUDE.md +49 -107
  34. package/dist/agent/daemon.d.ts +0 -130
  35. package/dist/agent/daemon.js +0 -606
  36. package/dist/agent/health-check.d.ts +0 -35
  37. package/dist/agent/health-check.js +0 -243
  38. package/dist/agent/pty-runner.d.ts +0 -53
  39. package/dist/agent/pty-runner.js +0 -190
  40. package/dist/commands/agent.d.ts +0 -50
  41. package/dist/commands/agent.js +0 -544
  42. package/dist/commands/setup-remote.d.ts +0 -20
  43. package/dist/commands/setup-remote.js +0 -582
  44. package/dist/commands/synk.d.ts +0 -7
  45. package/dist/commands/synk.js +0 -339
  46. package/dist/cron/index.d.ts +0 -7
  47. package/dist/cron/index.js +0 -13
  48. package/dist/cron/promoter.d.ts +0 -70
  49. package/dist/cron/promoter.js +0 -403
  50. package/dist/synk/api.d.ts +0 -22
  51. package/dist/synk/api.js +0 -133
  52. package/dist/synk/auth.d.ts +0 -7
  53. package/dist/synk/auth.js +0 -30
  54. package/dist/synk/config.d.ts +0 -18
  55. package/dist/synk/config.js +0 -37
  56. package/dist/synk/daemon/control-client.d.ts +0 -11
  57. package/dist/synk/daemon/control-client.js +0 -101
  58. package/dist/synk/daemon/control-server.d.ts +0 -24
  59. package/dist/synk/daemon/control-server.js +0 -91
  60. package/dist/synk/daemon/run.d.ts +0 -14
  61. package/dist/synk/daemon/run.js +0 -338
  62. package/dist/synk/encryption.d.ts +0 -17
  63. package/dist/synk/encryption.js +0 -133
  64. package/dist/synk/index.d.ts +0 -13
  65. package/dist/synk/index.js +0 -36
  66. package/dist/synk/machine-client.d.ts +0 -42
  67. package/dist/synk/machine-client.js +0 -218
  68. package/dist/synk/persistence.d.ts +0 -51
  69. package/dist/synk/persistence.js +0 -211
  70. package/dist/synk/qr.d.ts +0 -5
  71. package/dist/synk/qr.js +0 -33
  72. package/dist/synk/session-bridge.d.ts +0 -58
  73. package/dist/synk/session-bridge.js +0 -171
  74. package/dist/synk/session-client.d.ts +0 -46
  75. package/dist/synk/session-client.js +0 -240
  76. package/dist/synk/types.d.ts +0 -574
  77. package/dist/synk/types.js +0 -74
  78. package/dist/utils/verify-remote-terminal.d.ts +0 -10
  79. package/dist/utils/verify-remote-terminal.js +0 -415
  80. package/templates/README.md +0 -378
  81. package/templates/claude-plugins/PHASE2_COMPLETION.md +0 -346
  82. package/templates/claude-plugins/PLUGIN_PROPOSALS.md +0 -1776
  83. package/templates/claude-plugins/README.md +0 -587
  84. package/templates/claude-plugins/agents/code-reviewer.json +0 -14
  85. package/templates/claude-plugins/agents/debug-detective.json +0 -15
  86. package/templates/claude-plugins/agents/git-companion.json +0 -14
  87. package/templates/claude-plugins/blog-manager/.claude-plugin/plugin.json +0 -8
  88. package/templates/claude-plugins/blog-manager/commands/blog.md +0 -691
  89. package/templates/claude-plugins/golden-loop-monitor/.claude-plugin/plugin.json +0 -8
  90. package/templates/claude-plugins/golden-loop-monitor/commands/loop-status.md +0 -434
  91. package/templates/claude-plugins/learning-tracker/.claude-plugin/plugin.json +0 -8
  92. package/templates/claude-plugins/learning-tracker/commands/my-patterns.md +0 -282
  93. package/templates/claude-plugins/memory-lens/.claude-plugin/plugin.json +0 -8
  94. package/templates/claude-plugins/memory-lens/commands/memory-search.md +0 -181
  95. package/templates/claude-plugins/pattern-coach/.claude-plugin/plugin.json +0 -8
  96. package/templates/claude-plugins/pattern-coach/commands/forge.md +0 -365
  97. package/templates/claude-plugins/project-schema-validator/.claude-plugin/plugin.json +0 -8
  98. package/templates/claude-plugins/project-schema-validator/commands/validate-schema.md +0 -582
  99. package/templates/commands/continue.md +0 -47
  100. package/templates/cursor-rules/ekkos-memory.md +0 -127
  101. package/templates/ekkos-manifest.json +0 -223
  102. package/templates/helpers/json-parse.cjs +0 -101
  103. package/templates/plan-template.md +0 -306
  104. package/templates/shared/hooks-enabled.json +0 -22
  105. package/templates/shared/session-words.json +0 -45
  106. package/templates/skills/ekkOS_Deep_Recall/Skill.md +0 -282
  107. package/templates/skills/ekkOS_Learn/Skill.md +0 -265
  108. package/templates/skills/ekkOS_Memory_First/Skill.md +0 -206
  109. package/templates/skills/ekkOS_Plan_Assist/Skill.md +0 -302
  110. package/templates/skills/ekkOS_Preferences/Skill.md +0 -247
  111. package/templates/skills/ekkOS_Reflect/Skill.md +0 -257
  112. package/templates/skills/ekkOS_Safety/Skill.md +0 -265
  113. package/templates/skills/ekkOS_Schema/Skill.md +0 -251
  114. package/templates/skills/ekkOS_Summary/Skill.md +0 -257
  115. package/templates/spec-template.md +0 -159
  116. package/templates/windsurf-rules/ekkos-memory.md +0 -127
  117. package/templates/windsurf-skills/README.md +0 -58
  118. package/templates/windsurf-skills/ekkos-continue/SKILL.md +0 -81
  119. package/templates/windsurf-skills/ekkos-golden-loop/SKILL.md +0 -225
  120. package/templates/windsurf-skills/ekkos-insights/SKILL.md +0 -138
  121. package/templates/windsurf-skills/ekkos-recall/SKILL.md +0 -96
  122. package/templates/windsurf-skills/ekkos-safety/SKILL.md +0 -89
  123. package/templates/windsurf-skills/ekkos-vault/SKILL.md +0 -86
@@ -43,140 +43,6 @@ const fs = __importStar(require("fs"));
43
43
  const path = __importStar(require("path"));
44
44
  const os = __importStar(require("os"));
45
45
  const child_process_1 = require("child_process");
46
- const session_bridge_1 = require("../synk/session-bridge");
47
- // ═══════════════════════════════════════════════════════════════════════════
48
- // ccDNA AUTO-LOAD: Apply Claude Code patches before spawning
49
- // ═══════════════════════════════════════════════════════════════════════════
50
- const CCDNA_PATHS = [
51
- // Development path (DEV sibling directory)
52
- // From: EKKOS/packages/ekkos-cli/dist/commands/ → DEV/ekkos-ccdna/
53
- path.join(__dirname, '..', '..', '..', '..', '..', 'ekkos-ccdna', 'dist', 'index.mjs'),
54
- // User install path
55
- path.join(os.homedir(), '.ekkos', 'ccdna', 'dist', 'index.mjs'),
56
- // npm global (homebrew)
57
- '/opt/homebrew/lib/node_modules/ekkos-ccdna/dist/index.mjs',
58
- // npm global (standard)
59
- path.join(os.homedir(), '.npm-global', 'lib', 'node_modules', 'ekkos-ccdna', 'dist', 'index.mjs'),
60
- ];
61
- /**
62
- * Find ccDNA installation path
63
- */
64
- function findCcdnaPath() {
65
- for (const p of CCDNA_PATHS) {
66
- if (fs.existsSync(p)) {
67
- return p;
68
- }
69
- }
70
- return null;
71
- }
72
- /**
73
- * Apply ccDNA patches silently before Claude spawns
74
- * Returns version string if patches were applied, null otherwise
75
- *
76
- * @param verbose - Show detailed output
77
- * @param claudePath - Path to Claude Code to patch (if different from default)
78
- */
79
- function applyCcdnaPatches(verbose, claudePath) {
80
- // DISABLED: ccDNA patching is currently corrupting cli.js (JSON parse error at position 7945)
81
- // See: https://github.com/anthropics/ekkos/issues/2856
82
- // The patching process is injecting code that breaks the minified cli.js
83
- // Temporarily disabled until ccDNA is fixed upstream
84
- if (verbose) {
85
- console.log(chalk_1.default.gray(' ccDNA patching disabled (see issue #2856)'));
86
- }
87
- return null;
88
- // Original implementation (disabled):
89
- /*
90
- const ccdnaPath = findCcdnaPath();
91
- if (!ccdnaPath) {
92
- if (verbose) {
93
- console.log(chalk.gray(' ccDNA not found - skipping patches'));
94
- }
95
- return null;
96
- }
97
-
98
- // Read ccDNA version from package.json FIRST
99
- let ccdnaVersion = 'unknown';
100
- try {
101
- const pkgPath = path.join(path.dirname(ccdnaPath), '..', 'package.json');
102
- if (fs.existsSync(pkgPath)) {
103
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
104
- ccdnaVersion = pkg.version || 'unknown';
105
- }
106
- } catch {
107
- // Ignore version detection errors
108
- }
109
-
110
- try {
111
- // Set env var to tell ccDNA which Claude to patch
112
- // eslint-disable-next-line no-restricted-syntax
113
- const env = { ...process.env };
114
- if (claudePath) {
115
- // ccDNA checks CCDNA_CC_INSTALLATION_PATH to override default detection
116
- env.CCDNA_CC_INSTALLATION_PATH = claudePath;
117
- }
118
-
119
- // Run ccDNA in apply mode (non-interactive)
120
- execSync(`node "${ccdnaPath}" -a`, {
121
- stdio: verbose ? 'inherit' : 'pipe',
122
- timeout: 30000, // 30 second timeout
123
- env,
124
- });
125
-
126
- if (verbose) {
127
- console.log(chalk.green(` ✓ ccDNA v${ccdnaVersion} patches applied`));
128
- }
129
- return ccdnaVersion;
130
- } catch (err) {
131
- if (verbose) {
132
- console.log(chalk.yellow(` ⚠ ccDNA patch failed: ${(err as Error).message}`));
133
- }
134
- return null;
135
- }
136
- */
137
- }
138
- /**
139
- * Restore original Claude Code (remove ccDNA patches) on exit
140
- * This restores the ekkOS-managed installation (~/.ekkos/claude-code/) to its base state
141
- *
142
- * NOTE: We intentionally DON'T restore on exit anymore because:
143
- * 1. ekkOS uses a SEPARATE installation (~/.ekkos/claude-code/) from homebrew
144
- * 2. The homebrew `claude` command should always be vanilla (untouched)
145
- * 3. The ekkOS installation can stay patched - it's only used by `ekkos run`
146
- *
147
- * This function is kept for manual/explicit restore scenarios.
148
- */
149
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
150
- function restoreCcdnaPatches(verbose, claudePath) {
151
- const ccdnaPath = findCcdnaPath();
152
- if (!ccdnaPath) {
153
- return false;
154
- }
155
- try {
156
- // Set env var to tell ccDNA which Claude to restore
157
- // eslint-disable-next-line no-restricted-syntax
158
- const env = { ...process.env };
159
- if (claudePath) {
160
- env.CCDNA_CC_INSTALLATION_PATH = claudePath;
161
- }
162
- // Run ccDNA in restore mode (non-interactive)
163
- (0, child_process_1.execSync)(`node "${ccdnaPath}" -r`, {
164
- stdio: verbose ? 'inherit' : 'pipe',
165
- timeout: 30000, // 30 second timeout
166
- env,
167
- });
168
- if (verbose) {
169
- console.log(chalk_1.default.green(' ✓ ccDNA patches removed (vanilla restored)'));
170
- }
171
- return true;
172
- }
173
- catch (err) {
174
- if (verbose) {
175
- console.log(chalk_1.default.yellow(` ⚠ ccDNA restore failed: ${err.message}`));
176
- }
177
- return false;
178
- }
179
- }
180
46
  const state_1 = require("../utils/state");
181
47
  const session_binding_1 = require("../utils/session-binding");
182
48
  const doctor_1 = require("./doctor");
@@ -215,7 +81,7 @@ function getConfig(options) {
215
81
  maxIdleWaitMs: parseInt(process.env.EKKOS_MAX_IDLE_WAIT_MS || '2000', 10), // was 10000
216
82
  debugLogPath: options.debugLogPath ??
217
83
  process.env.EKKOS_DEBUG_LOG_PATH ??
218
- path.join(os.homedir(), '.ekkos', 'auto-continue.debug.log')
84
+ path.join(os.homedir(), '.ekkos', 'ekkos-debug.log')
219
85
  };
220
86
  /* eslint-enable no-restricted-syntax */
221
87
  }
@@ -256,7 +122,7 @@ const PALETTE_INDICATOR_REGEX = /\/(clear|continue|compact|help|bug|config)/i;
256
122
  const SESSION_NAME_IN_STATUS_REGEX = /turn\s+\d+\s*·\s*([a-z]+-[a-z]+-[a-z]+)\s*·/i;
257
123
  // Weaker signal: any 3-word slug (word-word-word pattern)
258
124
  const SESSION_NAME_REGEX = /\b([a-z]+-[a-z]+-[a-z]+)\b/i;
259
- // Orphan tool_result marker emitted by ccDNA validate mode
125
+ // Orphan tool_result marker
260
126
  // Example: [ekkOS] ORPHAN_TOOL_RESULT {"idx":0,"tool_use_id":"toolu_01...","block_idx":0}
261
127
  const ORPHAN_MARKER_REGEX = /\[ekkOS\]\s+ORPHAN_TOOL_RESULT\s+(\{.*?\})/gi;
262
128
  // Cooldown to prevent thrashing if output repeats the marker
@@ -283,7 +149,7 @@ function isValidSessionName(name) {
283
149
  // ═══════════════════════════════════════════════════════════════════════════
284
150
  // LOGGING (FILE ONLY DURING TUI - NO TERMINAL CORRUPTION)
285
151
  // ═══════════════════════════════════════════════════════════════════════════
286
- let _debugLogPath = path.join(os.homedir(), '.ekkos', 'auto-continue.debug.log');
152
+ let _debugLogPath = path.join(os.homedir(), '.ekkos', 'ekkos-debug.log');
287
153
  /**
288
154
  * Set the debug log path (called once during init)
289
155
  */
@@ -709,6 +575,116 @@ function resolveGlobalClaudePath() {
709
575
  function sleep(ms) {
710
576
  return new Promise(resolve => setTimeout(resolve, ms));
711
577
  }
578
+ /**
579
+ * Show morning dreams with WOW factor right after sparkle animation.
580
+ * Colorful, lively, readable — real magic moment. Then pause for Enter.
581
+ * Uses ~/.ekkos/.last-dream-shown marker (once per day, zero clutter on repeat).
582
+ */
583
+ async function showMorningDreamsIfNeeded() {
584
+ const markerPath = path.join(state_1.EKKOS_DIR, '.last-dream-shown');
585
+ const today = new Date().toISOString().split('T')[0];
586
+ // Fast path: already shown today
587
+ try {
588
+ if (fs.existsSync(markerPath)) {
589
+ const lastShown = fs.readFileSync(markerPath, 'utf-8').trim();
590
+ if (lastShown === today)
591
+ return;
592
+ }
593
+ }
594
+ catch { }
595
+ // Fetch digest from memory API (2s timeout — never blocks startup)
596
+ try {
597
+ const authToken = (0, state_1.getAuthToken)();
598
+ if (!authToken)
599
+ return;
600
+ const controller = new AbortController();
601
+ const fetchTimeout = setTimeout(() => controller.abort(), 2000);
602
+ const res = await fetch(`${MEMORY_API_URL}/api/v1/dreams/digest`, {
603
+ headers: { Authorization: `Bearer ${authToken}` },
604
+ signal: controller.signal,
605
+ });
606
+ clearTimeout(fetchTimeout);
607
+ if (!res.ok)
608
+ return;
609
+ const digest = await res.json();
610
+ if (!digest.dreams || digest.dreams.length === 0)
611
+ return;
612
+ // ═══════════════════════════════════════════════════════════════════════
613
+ // WOW FACTOR RENDERING — colorful, alive, readable
614
+ // ═══════════════════════════════════════════════════════════════════════
615
+ const dreamTime = new Date(digest.dreams[0].dreamedAt);
616
+ const timeStr = dreamTime.toLocaleTimeString('en-US', {
617
+ hour: 'numeric', minute: '2-digit', hour12: true,
618
+ }).toLowerCase();
619
+ console.log('');
620
+ console.log(chalk_1.default.cyan.bold(' ' + '═'.repeat(66)));
621
+ console.log(chalk_1.default.hex('#FF69B4').bold(` 🌙 While you slept, I had ${digest.dreams.length} idea${digest.dreams.length === 1 ? '' : 's'} for you`) +
622
+ chalk_1.default.gray(` (forged at ${timeStr})`));
623
+ console.log(chalk_1.default.gray.dim(' From your personal knowledge graph — concepts you\'ve never combined'));
624
+ console.log(chalk_1.default.cyan.bold(' ' + '═'.repeat(66)));
625
+ console.log('');
626
+ digest.dreams.forEach((dream, i) => {
627
+ const filled = Math.round(dream.creativityScore * 5);
628
+ const stars = chalk_1.default.yellow('★'.repeat(filled)) + chalk_1.default.gray('☆'.repeat(5 - filled));
629
+ // Dream title line with creativity stars
630
+ console.log(chalk_1.default.hex('#7C6BFF').bold(` 💭 [Dream ${i + 1}] `) +
631
+ chalk_1.default.white.bold(`"${dream.title}"`) +
632
+ ' ' + stars);
633
+ // Solution insight (up to 140 chars, two lines max)
634
+ const solution = dream.solution.length > 140
635
+ ? dream.solution.slice(0, 137) + '...'
636
+ : dream.solution;
637
+ console.log(chalk_1.default.gray(` ${solution}`));
638
+ // Lineage: origin ↔ discovery with domain colors
639
+ const crossDomain = dream.originDomain !== dream.discoveryDomain;
640
+ const lineage = crossDomain
641
+ ? chalk_1.default.cyan(dream.originConcept) +
642
+ chalk_1.default.hex('#FFA500')(' ⚡ ') +
643
+ chalk_1.default.hex('#DA70D6')(dream.discoveryConcept) +
644
+ chalk_1.default.gray.dim(` (${dream.originDomain} × ${dream.discoveryDomain})`)
645
+ : chalk_1.default.cyan(dream.originConcept) +
646
+ chalk_1.default.gray(' ↔ ') +
647
+ chalk_1.default.cyan(dream.discoveryConcept);
648
+ console.log(` ${lineage}`);
649
+ console.log('');
650
+ });
651
+ // Action hints
652
+ console.log(chalk_1.default.gray.dim(` Reply ${chalk_1.default.white('"promote 1"')} to make it permanent, ` +
653
+ `${chalk_1.default.white('"dismiss 1"')} to kill it, or just ignore — it'll decay naturally.`));
654
+ if (digest.streak > 1) {
655
+ console.log(chalk_1.default.hex('#FF8800')(` 🔥 ${digest.streak}-night dream streak`) + chalk_1.default.gray.dim(` (${digest.totalDreamsEver} total dreams)`));
656
+ }
657
+ // Clickable link to expanded dashboard (OSC 8 hyperlink — supported by iTerm2, Warp, Ghostty, etc.)
658
+ const dashUrl = 'https://platform.ekkos.dev/dashboard/dreams';
659
+ console.log('');
660
+ console.log(chalk_1.default.gray.dim(' 📊 Full Dream Journal: ') + chalk_1.default.cyan.underline(`\x1B]8;;${dashUrl}\x07${dashUrl}\x1B]8;;\x07`));
661
+ console.log('');
662
+ console.log(chalk_1.default.hex('#FFA500').bold(' Press Enter to continue to Claude...'));
663
+ console.log('');
664
+ // Wait for any keypress — clean, non-blocking
665
+ await new Promise(resolve => {
666
+ if (process.stdin.isTTY) {
667
+ process.stdin.setRawMode(true);
668
+ process.stdin.resume();
669
+ process.stdin.once('data', () => {
670
+ process.stdin.setRawMode(false);
671
+ process.stdin.pause();
672
+ resolve();
673
+ });
674
+ }
675
+ else {
676
+ // Non-TTY (piped input) — don't block
677
+ resolve();
678
+ }
679
+ });
680
+ // Mark as shown for today
681
+ fs.writeFileSync(markerPath, today);
682
+ dlog(`🌙 Wow-factor morning dreams shown for ${today}`);
683
+ }
684
+ catch (err) {
685
+ dlog(`Morning dreams fetch failed (silent): ${err.message}`);
686
+ }
687
+ }
712
688
  /**
713
689
  * Emergency capture before clear - saves current state to ekkOS
714
690
  */
@@ -853,8 +829,6 @@ function launchWithDashboard(options) {
853
829
  runArgs.push('-r');
854
830
  if (options.noInject)
855
831
  runArgs.push('--skip-inject');
856
- if (options.noDna)
857
- runArgs.push('--skip-dna');
858
832
  if (options.noProxy)
859
833
  runArgs.push('--skip-proxy');
860
834
  const ekkosCmd = process.argv[1]; // Path to ekkos CLI
@@ -885,6 +859,10 @@ function launchWithDashboard(options) {
885
859
  applyTmuxOpt(`set-option -sa -t "${tmuxSession}" terminal-overrides ",xterm-256color:Tc:smcup@:rmcup@"`);
886
860
  // Session/window isolation and quality-of-life settings
887
861
  applyTmuxOpt(`set-option -t "${tmuxSession}" mouse on`);
862
+ // Auto-cleanup on disconnect without breaking startup:
863
+ // kill this tmux session only when the last client detaches.
864
+ const detachCleanupHook = `if-shell -F '#{==:#{session_attached},0}' 'kill-session -t ${tmuxSession}'`;
865
+ applyTmuxOpt(`set-hook -t "${tmuxSession}" client-detached "${detachCleanupHook}"`);
888
866
  applyTmuxOpt(`set-window-option -t "${tmuxSession}" history-limit 100000`);
889
867
  applyTmuxOpt(`set-window-option -t "${tmuxSession}" mode-keys vi`);
890
868
  applyTmuxOpt(`set-window-option -t "${tmuxSession}:claude" synchronize-panes off`);
@@ -936,8 +914,6 @@ function launchWithWindowsTerminal(options) {
936
914
  runArgs.push('-r');
937
915
  if (options.noInject)
938
916
  runArgs.push('--skip-inject');
939
- if (options.noDna)
940
- runArgs.push('--skip-dna');
941
917
  if (options.noProxy)
942
918
  runArgs.push('--skip-proxy');
943
919
  // Write a temp batch file to avoid all quoting issues
@@ -1067,43 +1043,9 @@ async function run(options) {
1067
1043
  // ══════════════════════════════════════════════════════════════════════════
1068
1044
  (0, state_1.ensureEkkosDir)();
1069
1045
  (0, state_1.clearAutoClearFlag)();
1070
- // Resolve Claude path FIRST so ccDNA patches the RIGHT installation
1046
+ // Resolve Claude path
1071
1047
  const rawClaudePath = resolveClaudePath();
1072
1048
  const isNpxMode = rawClaudePath.startsWith('npx:');
1073
- // Get the actual CLI path for ccDNA to patch
1074
- // CRITICAL: ONLY patch the ekkOS-managed installation, NEVER touch Homebrew/global!
1075
- let claudeCliPath;
1076
- // Always target the ekkOS-managed installation for patching
1077
- // Even if we're running from Homebrew, we only patch our own installation
1078
- if (fs.existsSync(EKKOS_CLAUDE_BIN)) {
1079
- try {
1080
- const realPath = fs.realpathSync(EKKOS_CLAUDE_BIN);
1081
- if (realPath.endsWith('.js') && fs.existsSync(realPath)) {
1082
- claudeCliPath = realPath;
1083
- }
1084
- }
1085
- catch {
1086
- // Ignore - will use default detection
1087
- }
1088
- }
1089
- // ══════════════════════════════════════════════════════════════════════════
1090
- // ccDNA AUTO-PATCH: Apply Claude Code customizations before spawn
1091
- // This patches the context warning, themes, and other ccDNA features
1092
- // Skip if --no-dna flag is set
1093
- // ══════════════════════════════════════════════════════════════════════════
1094
- const noDna = options.noDna || false;
1095
- let ccdnaVersion = null;
1096
- if (noDna) {
1097
- if (verbose) {
1098
- console.log(chalk_1.default.yellow(' ⏭️ Skipping ccDNA injection (--no-dna)'));
1099
- }
1100
- }
1101
- else {
1102
- if (verbose && claudeCliPath) {
1103
- console.log(chalk_1.default.gray(` 🔧 Patching: ${claudeCliPath}`));
1104
- }
1105
- ccdnaVersion = applyCcdnaPatches(verbose, claudeCliPath);
1106
- }
1107
1049
  const pinnedVersion = isNpxMode ? rawClaudePath.split(':')[1] : null;
1108
1050
  const claudePath = isNpxMode ? 'npx' : rawClaudePath;
1109
1051
  // Build args early
@@ -1349,9 +1291,6 @@ async function run(options) {
1349
1291
  if (bypass) {
1350
1292
  console.log(chalk_1.default.yellow(' ⚡ Bypass permissions mode enabled'));
1351
1293
  }
1352
- if (noDna) {
1353
- console.log(chalk_1.default.yellow(' ⏭️ ccDNA injection skipped (--no-dna)'));
1354
- }
1355
1294
  if (verbose) {
1356
1295
  console.log(chalk_1.default.gray(` 📁 Debug log: ${config.debugLogPath}`));
1357
1296
  console.log(chalk_1.default.gray(` ⏱ Timing: clear=${config.clearWaitMs}ms, idleMax=${config.maxIdleWaitMs}ms (~${Math.round((config.clearWaitMs + config.maxIdleWaitMs * 2 + 1700) / 1000)}s total)`));
@@ -1366,15 +1305,16 @@ async function run(options) {
1366
1305
  if (bypass) {
1367
1306
  console.log(chalk_1.default.yellow(' ⚡ Bypass permissions mode enabled'));
1368
1307
  }
1369
- if (noDna) {
1370
- console.log(chalk_1.default.yellow(' ⏭️ ccDNA injection skipped (--no-dna)'));
1371
- }
1372
1308
  if (verbose) {
1373
1309
  console.log(chalk_1.default.gray(` 📁 Debug log: ${config.debugLogPath}`));
1374
1310
  }
1375
1311
  console.log('');
1376
1312
  }
1377
1313
  // ══════════════════════════════════════════════════════════════════════════
1314
+ // MAGIC MOMENT: Morning dreams right after sparkle, before Claude appears
1315
+ // ══════════════════════════════════════════════════════════════════════════
1316
+ await showMorningDreamsIfNeeded();
1317
+ // ══════════════════════════════════════════════════════════════════════════
1378
1318
  // ANIMATION COMPLETE: Mark ready and flush buffered Claude output
1379
1319
  // ══════════════════════════════════════════════════════════════════════════
1380
1320
  animationComplete = true;
@@ -1419,8 +1359,6 @@ async function run(options) {
1419
1359
  console.log(chalk_1.default.cyan(` 📊 Active ekkOS sessions: ${activeSessions.length}`));
1420
1360
  }
1421
1361
  }
1422
- // Synk bridge — real-time session sync (null when synk not configured)
1423
- const synkBridge = await session_bridge_1.SynkSessionBridge.create({ cwd: process.cwd(), verbose });
1424
1362
  let isAutoClearInProgress = false;
1425
1363
  let transcriptPath = null;
1426
1364
  let currentSessionId = null;
@@ -1623,7 +1561,7 @@ async function run(options) {
1623
1561
  // JSONL eviction tracking - prevent rapid re-eviction
1624
1562
  let lastEvictionTime = 0;
1625
1563
  // ══════════════════════════════════════════════════════════════════════════
1626
- // ORPHAN TOOL_RESULT RECOVERY - React to ccDNA validate mode markers
1564
+ // ORPHAN TOOL_RESULT RECOVERY
1627
1565
  // ══════════════════════════════════════════════════════════════════════════
1628
1566
  let lastOrphanDetectionTime = 0;
1629
1567
  let isOrphanRecoveryInProgress = false;
@@ -1863,11 +1801,9 @@ async function run(options) {
1863
1801
  console.log(chalk_1.default.yellow(' Monitor-only mode (--no-inject)'));
1864
1802
  }
1865
1803
  if (verbose) {
1866
- // Show Claude version with ccDNA version if patched
1804
+ // Show Claude version
1867
1805
  const ccVersion = pinnedVersion || PINNED_CLAUDE_VERSION;
1868
- const versionStr = ccdnaVersion
1869
- ? `Claude Code v${ccVersion} + ekkOS_Continuum v${ccdnaVersion}`
1870
- : `Claude Code v${ccVersion}`;
1806
+ const versionStr = `Claude Code v${ccVersion}`;
1871
1807
  console.log(chalk_1.default.gray(` 🤖 ${versionStr}`));
1872
1808
  if (currentSession) {
1873
1809
  console.log(chalk_1.default.green(` 📍 Session: ${currentSession}`));
@@ -1951,7 +1887,7 @@ async function run(options) {
1951
1887
  }
1952
1888
  else {
1953
1889
  // PTY not available - use spawn with stdio inherit (clean pass-through)
1954
- // This mode doesn't support auto-continue but provides full Claude Code experience
1890
+ // PTY not available spawn with stdio inherit (clean pass-through)
1955
1891
  dlog('PTY not available, using spawn pass-through mode');
1956
1892
  const spawnedProcess = (0, child_process_1.spawn)(claudePath, args, {
1957
1893
  stdio: 'inherit',
@@ -1983,17 +1919,6 @@ async function run(options) {
1983
1919
  process.stdin.on('data', onStdinData);
1984
1920
  // Helper to get current output buffer (for readiness checks)
1985
1921
  const getOutputBuffer = () => outputBuffer;
1986
- // Synk remote message injection — receive messages from mobile/web, inject into PTY
1987
- if (synkBridge) {
1988
- synkBridge.on('remote-message', async (msg) => {
1989
- const { ready } = await waitForIdlePrompt(getOutputBuffer, config);
1990
- if (ready) {
1991
- shell.write('\x15'); // Ctrl+U clear line
1992
- await typeSlowly(shell, msg.text, config.charDelayMs);
1993
- shell.write('\r');
1994
- }
1995
- });
1996
- }
1997
1922
  // Handle context wall detection
1998
1923
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1999
1924
  async function handleContextWall() {
@@ -2144,13 +2069,13 @@ async function run(options) {
2144
2069
  }
2145
2070
  // ══════════════════════════════════════════════════════════════════════════
2146
2071
  // ORPHAN TOOL_RESULT RECOVERY
2147
- // When ccDNA validate mode detects orphan tool_results before an API call,
2072
+ // When orphan tool_results are detected in the terminal output,
2148
2073
  // it emits [ekkOS] ORPHAN_TOOL_RESULT to the terminal. We detect this marker
2149
2074
  // and repair the transcript (rollback or surgical).
2150
2075
  //
2151
2076
  // NOTE: We do NOT run /clear + /continue anymore. That was leftover from when
2152
- // ccDNA was in evict mode (filtering in-memory messages). With ccDNA in validate
2153
- // mode and the JSONL rewriter as the single disk authority, orphans indicate a
2077
+ // NOTE: We do NOT run /clear + /continue anymore. The JSONL rewriter
2078
+ // is the single disk authority; orphans indicate a bug, not a state desync.
2154
2079
  // BUG in the sliding window - not a state desync that needs rebuilding.
2155
2080
  // The in-memory state is fine; we just fix the disk and log the bug.
2156
2081
  // ══════════════════════════════════════════════════════════════════════════
@@ -2193,8 +2118,8 @@ async function run(options) {
2193
2118
  diagnosis: 'JSONL rewriter evicted tool_use without its tool_result, or vice versa',
2194
2119
  action: 'Attempting disk repair via rollback or surgical removal',
2195
2120
  });
2196
- console.log(`\n[ekkOS] 🚨 BUG: Orphan tool_result detected (${orphan.tool_use_id})`);
2197
- console.log(`[ekkOS] 🔧 Repairing disk transcript...`);
2121
+ dlog(`🚨 BUG: Orphan tool_result detected (${orphan.tool_use_id})`);
2122
+ dlog(`🔧 Repairing disk transcript...`);
2198
2123
  try {
2199
2124
  // Repair the disk transcript if we have one
2200
2125
  if (transcriptPath && validateTranscriptPath(transcriptPath)) {
@@ -2215,17 +2140,17 @@ async function run(options) {
2215
2140
  });
2216
2141
  dlog(`Orphan repair: ${repair.action} (orphans=${repair.orphansFound}, removed=${repair.removedLines ?? 0})`);
2217
2142
  if (repair.action === 'failed') {
2218
- console.log(`[ekkOS] WARNING: Orphan repair failed - session may be unstable`);
2219
- console.log(`[ekkOS] Reason: ${repair.reason}`);
2143
+ dlog(`❌ WARNING: Orphan repair failed - session may be unstable`);
2144
+ dlog(` Reason: ${repair.reason}`);
2220
2145
  }
2221
2146
  else if (repair.action === 'rollback') {
2222
- console.log(`[ekkOS] Disk repaired via ROLLBACK to backup`);
2147
+ dlog(`✅ Disk repaired via ROLLBACK to backup`);
2223
2148
  }
2224
2149
  else if (repair.action === 'surgical_repair') {
2225
- console.log(`[ekkOS] Disk repaired via SURGICAL removal (${repair.removedLines} lines removed)`);
2150
+ dlog(`✅ Disk repaired via SURGICAL removal (${repair.removedLines} lines removed)`);
2226
2151
  }
2227
2152
  else {
2228
- console.log(`[ekkOS] No repair needed - transcript is healthy`);
2153
+ dlog(`✅ No repair needed - transcript is healthy`);
2229
2154
  }
2230
2155
  // POST-REPAIR VALIDATION: Verify repair actually worked
2231
2156
  if (repair.action !== 'failed' && repair.action !== 'none') {
@@ -2239,8 +2164,8 @@ async function run(options) {
2239
2164
  postRepairOrphans,
2240
2165
  alert: 'REPAIR DID NOT FIX THE PROBLEM',
2241
2166
  });
2242
- console.log(`[ekkOS] ⚠️ Post-repair check: ${postRepairOrphans} orphan(s) still present!`);
2243
- console.log(`[ekkOS] Repair may have been incomplete - consider /clear + /continue`);
2167
+ dlog(`⚠️ Post-repair check: ${postRepairOrphans} orphan(s) still present!`);
2168
+ dlog(` Repair may have been incomplete - consider /clear + /continue`);
2244
2169
  }
2245
2170
  else {
2246
2171
  evictionDebugLog('POST_REPAIR_VALIDATION_SUCCESS', '✅ Repair verified - no orphans remaining', {
@@ -2290,7 +2215,7 @@ async function run(options) {
2290
2215
  continue;
2291
2216
  }
2292
2217
  dlog(`Detected ORPHAN_TOOL_RESULT: ${orphan.tool_use_id}`);
2293
- evictionDebugLog('ORPHAN_MARKER_DETECTED', 'ccDNA reported orphan in PTY output', {
2218
+ evictionDebugLog('ORPHAN_MARKER_DETECTED', 'Orphan detected in PTY output', {
2294
2219
  orphan,
2295
2220
  bufferLen: orphanDetectionBuffer.length,
2296
2221
  scanCursor: orphanScanCursor,
@@ -2371,8 +2296,6 @@ async function run(options) {
2371
2296
  if (outputBuffer.length > 5000) {
2372
2297
  outputBuffer = outputBuffer.slice(-2000);
2373
2298
  }
2374
- // Forward to synk real-time sync (batched internally)
2375
- synkBridge?.onAgentOutput(data);
2376
2299
  // ══════════════════════════════════════════════════════════════════════════
2377
2300
  // PER-TURN BANNER (replaces hook-based terminal header)
2378
2301
  // Prints once per turn when transitioning from idle → active (AI responding).
@@ -2388,40 +2311,26 @@ async function run(options) {
2388
2311
  !trimmed.startsWith('%'); // zsh prompt artefact
2389
2312
  if (isSubstantialOutput && Date.now() - lastBannerTime > 3000) {
2390
2313
  turnCount++;
2391
- const now = new Date();
2392
- const timeStr = now.toLocaleTimeString('en-US', {
2393
- hour: 'numeric',
2394
- minute: '2-digit',
2395
- hour12: true,
2396
- timeZone: 'America/New_York',
2397
- });
2398
- const dateStr = now.toLocaleDateString('en-US', {
2399
- year: 'numeric',
2400
- month: '2-digit',
2401
- day: '2-digit',
2402
- timeZone: 'America/New_York',
2403
- });
2404
2314
  const sessionLabel = currentSession || cliSessionName || 'initializing';
2405
- process.stderr.write(`${chalk_1.default.cyan.bold('🧠 ekkOS Memory')} ${chalk_1.default.dim(`| ${sessionLabel} | ${dateStr} ${timeStr} EST`)}\n`);
2315
+ // LOG ONLY never write to stdout/stderr during Ink's render cycle.
2316
+ // stderr shares the same terminal as stdout; injecting text here
2317
+ // corrupts Ink's cursor positioning and causes TUI rendering artifacts.
2318
+ dlog(`[TURN ${turnCount}] ${sessionLabel}`);
2406
2319
  lastBannerTime = Date.now();
2407
2320
  wasIdle = false;
2408
- synkBridge?.onIdleChange(false);
2409
2321
  }
2410
2322
  }
2411
2323
  // Track idle state for the banner (works in both proxy and local mode).
2412
2324
  // We check the raw outputBuffer (stripped) so the idle regex fires reliably.
2413
2325
  if (IDLE_PROMPT_REGEX.test(stripAnsi(outputBuffer))) {
2414
- if (!wasIdle)
2415
- synkBridge?.onIdleChange(true);
2416
2326
  wasIdle = true;
2417
2327
  }
2418
2328
  // ══════════════════════════════════════════════════════════════════════════
2419
2329
  // ORPHAN TOOL_RESULT DETECTION (LOCAL MODE ONLY)
2420
- // ccDNA validate mode emits [ekkOS] ORPHAN_TOOL_RESULT when it detects
2330
+ // [ekkOS] ORPHAN_TOOL_RESULT markers are emitted by the ekkOS memory system when it detects
2421
2331
  // tool_results without matching tool_uses. This triggers automatic repair.
2422
2332
  // DISABLED in proxy mode: proxy is sole eviction authority, CLI must not
2423
- // touch the local JSONL. Also requires ccDNA which is currently disabled.
2424
- // ══════════════════════════════════════════════════════════════════════════
2333
+ // touch the local JSONL.
2425
2334
  if (!proxyModeEnabled && !isAutoClearInProgress && !isOrphanRecoveryInProgress) {
2426
2335
  orphanDetectionBuffer += stripAnsi(data);
2427
2336
  if (orphanDetectionBuffer.length > 10000) {
@@ -2520,7 +2429,6 @@ async function run(options) {
2520
2429
  dlog(`Session detected from status line: ${currentSession} (observedSessionThisRun=true)`);
2521
2430
  bindRealSessionToProxy(currentSession, 'status-line', currentSessionId || undefined);
2522
2431
  resolveTranscriptFromSessionId('status-line');
2523
- synkBridge?.onSessionEstablished(currentSession, currentSessionId || 'unknown', { hostPid: process.pid });
2524
2432
  }
2525
2433
  }
2526
2434
  else {
@@ -2804,10 +2712,9 @@ Use Perplexity for deep research. Be thorough but efficient. Start now.`;
2804
2712
  shell.onExit(async ({ exitCode }) => {
2805
2713
  (0, state_1.clearAutoClearFlag)();
2806
2714
  stopStreamTailer(); // Stop stream capture
2807
- await synkBridge?.shutdown(); // Close synk session
2808
2715
  (0, state_1.unregisterActiveSession)(); // Remove from active sessions registry
2809
2716
  cleanupInstanceFile(instanceId); // Clean up instance file
2810
- // NOTE: No ccDNA restore needed - ekkOS uses separate installation from homebrew
2717
+ // NOTE: No restore needed - ekkOS uses separate installation from homebrew
2811
2718
  // ~/.ekkos/claude-code/ stays patched, homebrew `claude` is always vanilla
2812
2719
  // Restore terminal
2813
2720
  if (process.stdin.isTTY) {
@@ -2824,10 +2731,9 @@ Use Perplexity for deep research. Be thorough but efficient. Start now.`;
2824
2731
  const cleanup = () => {
2825
2732
  (0, state_1.clearAutoClearFlag)();
2826
2733
  stopStreamTailer(); // Stop stream capture
2827
- synkBridge?.shutdown().catch(() => { }); // Close synk session (best-effort)
2828
2734
  (0, state_1.unregisterActiveSession)(); // Remove from active sessions registry
2829
2735
  cleanupInstanceFile(instanceId); // Clean up instance file
2830
- // NOTE: No ccDNA restore needed - ekkOS uses separate installation from homebrew
2736
+ // NOTE: No restore needed - ekkOS uses separate installation from homebrew
2831
2737
  if (process.stdin.isTTY) {
2832
2738
  process.stdin.setRawMode(false);
2833
2739
  }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ekkos scan
3
+ *
4
+ * Scans the current directory's repo structure, discovers systems,
5
+ * and seeds them into ekkOS system_registry via the memory API.
6
+ *
7
+ * Usage:
8
+ * ekkos scan Scan cwd and seed registry
9
+ * ekkos scan --compile Also trigger a compile pass after seeding
10
+ * ekkos scan --dry-run Show what would be seeded without calling API
11
+ * ekkos scan --path /my/repo Scan a specific directory
12
+ *
13
+ * Reuses discovery logic from apps/memory/workers/context-compiler/registry-seed.ts
14
+ */
15
+ interface ScanOptions {
16
+ compile?: boolean;
17
+ dryRun?: boolean;
18
+ path?: string;
19
+ }
20
+ export declare function scan(options: ScanOptions): Promise<void>;
21
+ export {};