@ekkos/cli 1.2.0 → 1.2.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.
@@ -876,6 +876,34 @@ 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 dashboard in a separate Windows Terminal pane.
881
+ * Unlike tmux, wt.exe opens a new split pane but doesn't manage the session —
882
+ * Claude runs in the original terminal, dashboard runs in the new pane.
883
+ */
884
+ function launchWithWindowsTerminal(options) {
885
+ const ekkosCmd = process.argv[1];
886
+ const cwd = process.cwd();
887
+ const launchTime = Date.now();
888
+ // Write marker file so dashboard knows to wait for a NEW session
889
+ const markerPath = path.join(state_1.EKKOS_DIR, '.dashboard-launch-ts');
890
+ try {
891
+ fs.writeFileSync(markerPath, `${launchTime}\n${cwd}`);
892
+ }
893
+ catch { }
894
+ const dashCommand = `node "${ekkosCmd}" dashboard --wait-for-new --refresh 2000`;
895
+ try {
896
+ // wt.exe split-pane launches a new pane in the current Windows Terminal window
897
+ // -V = vertical split, -s 0.4 = 40% width for dashboard, -d = working directory
898
+ (0, child_process_1.execSync)(`wt.exe -w 0 split-pane -V -s 0.4 -d "${cwd}" cmd /c "${dashCommand}"`, { stdio: 'pipe' });
899
+ console.log(chalk_1.default.cyan('\n Dashboard launched in right pane (40%)'));
900
+ console.log(chalk_1.default.gray(' Switch panes: Alt+Arrow keys'));
901
+ }
902
+ catch (err) {
903
+ console.log(chalk_1.default.yellow(` Windows Terminal split failed: ${err.message}`));
904
+ console.log(chalk_1.default.gray(' Run "ekkos dashboard --latest" in a separate terminal'));
905
+ }
906
+ }
879
907
  async function run(options) {
880
908
  // ══════════════════════════════════════════════════════════════════════════
881
909
  // FIRST-RUN CHECK: If no config exists, run init first
@@ -906,43 +934,34 @@ async function run(options) {
906
934
  console.log(chalk_1.default.yellow(' ⏭️ API proxy disabled (--no-proxy)'));
907
935
  }
908
936
  // ══════════════════════════════════════════════════════════════════════════
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)
937
+ // DASHBOARD MODE: Launch via tmux (Unix) or Windows Terminal split pane
931
938
  // ══════════════════════════════════════════════════════════════════════════
932
939
  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;
940
+ if (isWindows) {
941
+ // Windows: launch dashboard in a separate Windows Terminal pane
942
+ try {
943
+ (0, child_process_1.execSync)('where wt.exe', { encoding: 'utf-8', stdio: 'pipe' });
944
+ launchWithWindowsTerminal(options);
945
+ // Don't return — continue to launch Claude in this terminal
946
+ }
947
+ catch {
948
+ console.log(chalk_1.default.yellow(' Windows Terminal (wt.exe) not found.'));
949
+ console.log(chalk_1.default.gray(' Alternative: run "ekkos dashboard --latest" in a separate terminal'));
950
+ console.log(chalk_1.default.gray(' Continuing without dashboard...\n'));
951
+ }
938
952
  }
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'));
953
+ else {
954
+ // Unix: launch via tmux split pane
955
+ try {
956
+ (0, child_process_1.execSync)('command -v tmux', { encoding: 'utf-8', stdio: 'pipe' });
957
+ launchWithDashboard(options);
958
+ return;
959
+ }
960
+ catch {
961
+ console.log(chalk_1.default.yellow(' tmux not found. Install: brew install tmux'));
962
+ console.log(chalk_1.default.gray(' Alternative: run "ekkos dashboard --latest" in a separate terminal'));
963
+ console.log(chalk_1.default.gray(' Continuing without dashboard...\n'));
964
+ }
946
965
  }
947
966
  }
948
967
  // 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.1",
4
4
  "description": "Setup ekkOS memory for AI coding assistants (Claude Code, Cursor, Windsurf)",
5
5
  "main": "dist/index.js",
6
6
  "bin": {