@ekkos/cli 1.2.0 → 1.2.2

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.
@@ -251,28 +251,18 @@ async function deployForClaude(apiKey, userId, options) {
251
251
  catch (error) {
252
252
  spinner.fail('MCP server configuration failed');
253
253
  }
254
- // Settings.json (hook registration) — skipped on Windows (proxy-only mode)
255
- if (platform_1.isWindows) {
256
- spinner = (0, ora_1.default)('Hooks skipped (Windows proxy-only mode)').start();
257
- spinner.info('Hooks skipped (Windows uses proxy-only mode)');
254
+ // Settings.json (hook registration)
255
+ spinner = (0, ora_1.default)('Deploying hooks configuration...').start();
256
+ try {
257
+ (0, settings_1.deployClaudeSettings)();
258
258
  result.settings = true;
259
+ spinner.succeed('Hooks configuration');
259
260
  }
260
- else {
261
- spinner = (0, ora_1.default)('Deploying hooks configuration...').start();
262
- try {
263
- (0, settings_1.deployClaudeSettings)();
264
- result.settings = true;
265
- spinner.succeed('Hooks configuration');
266
- }
267
- catch (error) {
268
- spinner.fail('Hooks configuration failed');
269
- }
270
- }
271
- // Hook scripts — skipped on Windows
272
- if (platform_1.isWindows) {
273
- // Skip hook scripts on Windows
261
+ catch (error) {
262
+ spinner.fail('Hooks configuration failed');
274
263
  }
275
- else if (!options.skipHooks) {
264
+ // Hook scripts
265
+ if (!options.skipHooks) {
276
266
  spinner = (0, ora_1.default)('Deploying hook scripts...').start();
277
267
  try {
278
268
  result.hooks = (0, hooks_1.deployHooks)(apiKey);
@@ -876,6 +876,57 @@ function launchWithDashboard(options) {
876
876
  console.log(chalk_1.default.gray('Falling back to normal mode. Run "ekkos dashboard --latest" in another terminal.'));
877
877
  }
878
878
  }
879
+ /**
880
+ * Launch Claude Code in a new Windows Terminal pane, dashboard stays in current terminal.
881
+ * Dashboard runs where the user typed the command; Claude opens alongside it.
882
+ */
883
+ function launchWithWindowsTerminal(options) {
884
+ const ekkosCmd = process.argv[1];
885
+ const cwd = process.cwd();
886
+ const launchTime = Date.now();
887
+ // Write marker file so dashboard knows to wait for a NEW session
888
+ const markerPath = path.join(state_1.EKKOS_DIR, '.dashboard-launch-ts');
889
+ try {
890
+ fs.writeFileSync(markerPath, `${launchTime}\n${cwd}`);
891
+ }
892
+ catch { }
893
+ // Build the ekkos run command WITHOUT --dashboard (prevent recursion)
894
+ const runArgs = ['run'];
895
+ if (options.session)
896
+ runArgs.push('-s', options.session);
897
+ if (options.bypass)
898
+ runArgs.push('-b');
899
+ if (options.verbose)
900
+ runArgs.push('-v');
901
+ if (options.doctor)
902
+ runArgs.push('-d');
903
+ if (options.research)
904
+ runArgs.push('-r');
905
+ if (options.noInject)
906
+ runArgs.push('--skip-inject');
907
+ if (options.noDna)
908
+ runArgs.push('--skip-dna');
909
+ if (options.noProxy)
910
+ runArgs.push('--skip-proxy');
911
+ const runCommand = `node "${ekkosCmd}" ${runArgs.join(' ')}`;
912
+ try {
913
+ // Launch Claude Code in a new pane (60% width), dashboard stays in current pane
914
+ // -V = vertical split, -s 0.6 = 60% width for Claude
915
+ (0, child_process_1.execSync)(`wt.exe -w 0 split-pane -V -s 0.6 -d "${cwd}" cmd /c "${runCommand}"`, { stdio: 'pipe' });
916
+ console.log(chalk_1.default.cyan('\n Claude Code launched in right pane (60%)'));
917
+ console.log(chalk_1.default.gray(' Switch panes: Alt+Arrow keys\n'));
918
+ }
919
+ catch (err) {
920
+ console.log(chalk_1.default.yellow(` Windows Terminal split failed: ${err.message}`));
921
+ console.log(chalk_1.default.gray(' Run "ekkos dashboard --latest" in a separate terminal'));
922
+ return;
923
+ }
924
+ // Dashboard runs in THIS terminal (the pane user launched from)
925
+ // Use dynamic import to avoid circular dependency
926
+ Promise.resolve().then(() => __importStar(require('./dashboard'))).then(({ dashboardCommand }) => {
927
+ dashboardCommand.parseAsync(['--wait-for-new', '--refresh', '2000'], { from: 'user' });
928
+ });
929
+ }
879
930
  async function run(options) {
880
931
  // ══════════════════════════════════════════════════════════════════════════
881
932
  // FIRST-RUN CHECK: If no config exists, run init first
@@ -906,43 +957,34 @@ async function run(options) {
906
957
  console.log(chalk_1.default.yellow(' ⏭️ API proxy disabled (--no-proxy)'));
907
958
  }
908
959
  // ══════════════════════════════════════════════════════════════════════════
909
- // WINDOWS: Disable hooks for reliability proxy-only mode
910
- // Hooks can cause PowerShell execution policy issues and hangs on Windows.
911
- // The proxy handles context management; hooks aren't strictly required.
912
- // ══════════════════════════════════════════════════════════════════════════
913
- if (isWindows) {
914
- try {
915
- const settingsPath = path.join(os.homedir(), '.claude', 'settings.json');
916
- if (fs.existsSync(settingsPath)) {
917
- const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
918
- if (settings.hooks) {
919
- delete settings.hooks;
920
- fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
921
- console.log(chalk_1.default.gray(' ⏭️ Hooks disabled (Windows proxy-only mode)'));
922
- }
923
- }
924
- }
925
- catch {
926
- // Non-fatal — continue without hook cleanup
927
- }
928
- }
929
- // ══════════════════════════════════════════════════════════════════════════
930
- // DASHBOARD MODE: Launch via tmux with isolated dashboard pane (60/40)
960
+ // DASHBOARD MODE: Launch via tmux (Unix) or Windows Terminal split pane
931
961
  // ══════════════════════════════════════════════════════════════════════════
932
962
  if (options.dashboard) {
933
- try {
934
- const tmuxCheck = isWindows ? 'where tmux' : 'command -v tmux';
935
- (0, child_process_1.execSync)(tmuxCheck, { encoding: 'utf-8', stdio: 'pipe' }).trim();
936
- launchWithDashboard(options);
937
- return;
963
+ if (isWindows) {
964
+ // Windows: Claude opens in new pane, dashboard stays in this terminal
965
+ try {
966
+ (0, child_process_1.execSync)('where wt.exe', { encoding: 'utf-8', stdio: 'pipe' });
967
+ launchWithWindowsTerminal(options);
968
+ return; // Dashboard runs in this terminal, Claude is in the new pane
969
+ }
970
+ catch {
971
+ console.log(chalk_1.default.yellow(' Windows Terminal (wt.exe) not found.'));
972
+ console.log(chalk_1.default.gray(' Alternative: run "ekkos dashboard --latest" in a separate terminal'));
973
+ console.log(chalk_1.default.gray(' Continuing without dashboard...\n'));
974
+ }
938
975
  }
939
- catch {
940
- const installHint = isWindows
941
- ? 'Install: scoop install tmux (or use WSL)'
942
- : 'Install: brew install tmux';
943
- console.log(chalk_1.default.yellow(` tmux not found. ${installHint}`));
944
- console.log(chalk_1.default.gray(' Alternative: run "ekkos dashboard --latest" in a separate terminal'));
945
- console.log(chalk_1.default.gray(' Continuing without dashboard...\n'));
976
+ else {
977
+ // Unix: launch via tmux split pane
978
+ try {
979
+ (0, child_process_1.execSync)('command -v tmux', { encoding: 'utf-8', stdio: 'pipe' });
980
+ launchWithDashboard(options);
981
+ return;
982
+ }
983
+ catch {
984
+ console.log(chalk_1.default.yellow(' tmux not found. Install: brew install tmux'));
985
+ console.log(chalk_1.default.gray(' Alternative: run "ekkos dashboard --latest" in a separate terminal'));
986
+ console.log(chalk_1.default.gray(' Continuing without dashboard...\n'));
987
+ }
946
988
  }
947
989
  }
948
990
  // Generate instance ID for this run
package/dist/index.js CHANGED
@@ -51,9 +51,6 @@ const agent_1 = require("./commands/agent");
51
51
  const state_1 = require("./utils/state");
52
52
  const index_1 = require("./commands/usage/index");
53
53
  const dashboard_1 = require("./commands/dashboard");
54
- const swarm_1 = require("./commands/swarm");
55
- const swarm_dashboard_1 = require("./commands/swarm-dashboard");
56
- const swarm_setup_1 = require("./commands/swarm-setup");
57
54
  const chalk_1 = __importDefault(require("chalk"));
58
55
  const fs = __importStar(require("fs"));
59
56
  const path = __importStar(require("path"));
@@ -79,7 +76,7 @@ commander_1.program
79
76
  ` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos run -b')} ${chalk_1.default.gray('Launch with bypass permissions mode')}`,
80
77
  ` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos doctor --fix')} ${chalk_1.default.gray('Check and auto-fix system prerequisites')}`,
81
78
  ` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos usage daily')} ${chalk_1.default.gray("View today's token usage and costs")}`,
82
- ` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos swarm launch -t "build X"')} ${chalk_1.default.gray('Launch parallel workers on a task')}`,
79
+ ` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos sessions')} ${chalk_1.default.gray('List active Claude Code sessions')}`,
83
80
  '',
84
81
  chalk_1.default.gray(' Run ') + chalk_1.default.white('ekkos <command> --help') + chalk_1.default.gray(' for detailed options on any command.'),
85
82
  '',
@@ -180,13 +177,6 @@ commander_1.program
180
177
  { name: 'agent', desc: 'Manage the remote terminal agent (start, stop, status, logs)' },
181
178
  ],
182
179
  },
183
- {
184
- title: 'Swarm (Multi-Agent)',
185
- icon: '▸',
186
- commands: [
187
- { name: 'swarm', desc: 'Parallel workers, Q-learning routing, swarm dashboard' },
188
- ],
189
- },
190
180
  ];
191
181
  const padCmd = 18;
192
182
  let output = '';
@@ -352,10 +342,10 @@ hooksCmd
352
342
  (0, index_1.registerUsageCommand)(commander_1.program);
353
343
  // Dashboard command - live TUI for monitoring session usage
354
344
  commander_1.program.addCommand(dashboard_1.dashboardCommand);
355
- // Sessions command - list active Claude Code sessions (swarm support)
345
+ // Sessions command - list active Claude Code sessions
356
346
  commander_1.program
357
347
  .command('sessions')
358
- .description('List active Claude Code sessions (for swarm/multi-session support)')
348
+ .description('List active Claude Code sessions')
359
349
  .option('-j, --json', 'Output machine-readable JSON')
360
350
  .action((options) => {
361
351
  const sessions = (0, state_1.getActiveSessions)();
@@ -480,59 +470,6 @@ agentCmd
480
470
  .action((options) => {
481
471
  (0, agent_1.agentHealth)({ json: options.json });
482
472
  });
483
- // Swarm command - manage Q-learning routing
484
- const swarmCmd = commander_1.program
485
- .command('swarm')
486
- .description('Manage Swarm Q-learning model routing');
487
- swarmCmd
488
- .command('status')
489
- .description('Show Q-table stats (states, visits, epsilon, top actions)')
490
- .action(swarm_1.swarmStatus);
491
- swarmCmd
492
- .command('reset')
493
- .description('Clear Q-table from Redis (routing reverts to static rules)')
494
- .action(swarm_1.swarmReset);
495
- swarmCmd
496
- .command('export')
497
- .description('Export Q-table to .swarm/q-learning-model.json')
498
- .action(swarm_1.swarmExport);
499
- swarmCmd
500
- .command('import')
501
- .description('Import Q-table from .swarm/q-learning-model.json into Redis')
502
- .action(swarm_1.swarmImport);
503
- swarmCmd
504
- .command('launch')
505
- .description('Launch parallel workers on a decomposed task (opens wizard if --task is omitted)')
506
- .option('-w, --workers <count>', 'Number of parallel workers (2-8)', parseInt)
507
- .option('-t, --task <task>', 'Task description to decompose and execute')
508
- .option('--no-bypass', 'Disable bypass permissions mode')
509
- .option('--no-decompose', 'Skip AI decomposition (send same task to all workers)')
510
- .option('--no-queen', 'Skip launching the Python Queen coordinator')
511
- .option('--queen-strategy <strategy>', 'Queen strategy (adaptive-default, hierarchical-cascade, mesh-consensus)')
512
- .option('-v, --verbose', 'Show debug output')
513
- .action((options) => {
514
- // Auto-open wizard when --task is missing
515
- if (!options.task) {
516
- (0, swarm_setup_1.swarmSetup)();
517
- return;
518
- }
519
- (0, swarm_1.swarmLaunch)({
520
- workers: options.workers || 4,
521
- task: options.task,
522
- bypass: options.bypass !== false,
523
- noDecompose: options.decompose === false,
524
- noQueen: options.queen === false,
525
- queenStrategy: options.queenStrategy,
526
- verbose: options.verbose,
527
- });
528
- });
529
- swarmCmd
530
- .command('setup')
531
- .description('Interactive TUI wizard for configuring and launching a swarm')
532
- .action(() => {
533
- (0, swarm_setup_1.swarmSetup)();
534
- });
535
- swarmCmd.addCommand(swarm_dashboard_1.swarmDashboardCommand);
536
473
  // Handle `-help` (single dash) — rewrite to `--help` for Commander compatibility
537
474
  const helpIdx = process.argv.indexOf('-help');
538
475
  if (helpIdx !== -1) {
@@ -80,7 +80,7 @@ export declare function getMostRecentSession(): {
80
80
  */
81
81
  export declare function getActiveSessions(): ActiveSession[];
82
82
  /**
83
- * Register a new active session (for swarm tracking)
83
+ * Register a new active session
84
84
  */
85
85
  export declare function registerActiveSession(sessionId: string, sessionName: string, projectPath: string): ActiveSession;
86
86
  /**
@@ -244,7 +244,7 @@ function getMostRecentSession() {
244
244
  }
245
245
  }
246
246
  // ═══════════════════════════════════════════════════════════════════════════
247
- // MULTI-SESSION/SWARM SUPPORT
247
+ // MULTI-SESSION SUPPORT
248
248
  // Track multiple concurrent Claude Code sessions without state collision
249
249
  // ═══════════════════════════════════════════════════════════════════════════
250
250
  /**
@@ -271,7 +271,7 @@ function getActiveSessions() {
271
271
  }
272
272
  }
273
273
  /**
274
- * Register a new active session (for swarm tracking)
274
+ * Register a new active session
275
275
  */
276
276
  function registerActiveSession(sessionId, sessionName, projectPath) {
277
277
  ensureEkkosDir();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekkos/cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Setup ekkOS memory for AI coding assistants (Claude Code, Cursor, Windsurf)",
5
5
  "main": "dist/index.js",
6
6
  "bin": {