@ekkos/cli 1.2.9 → 1.2.11

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.
@@ -565,21 +565,24 @@ async function launchDashboard(initialSessionName, jsonlPath, refreshMs) {
565
565
  // 3. Claude Code pane remains fully independent
566
566
  // 4. Text selection works across panes without interference
567
567
  // ══════════════════════════════════════════════════════════════════════════
568
- // Open /dev/tty for blessed to use (gives it direct terminal access)
568
+ // Open /dev/tty for blessed to use (gives it direct terminal access).
569
+ // On macOS/Linux in tmux, this isolates the dashboard from stdout piping.
570
+ // On Windows (no /dev/tty), stdin/stdout is correct — blessed handles the
571
+ // alternate screen buffer natively for clean rendering.
569
572
  const fs = require('fs');
570
573
  let ttyInput = process.stdin;
571
574
  let ttyOutput = process.stdout;
572
- try {
573
- // Create readable/writable streams from /dev/tty file descriptors
574
- const ttyFd = fs.openSync('/dev/tty', 'r+');
575
- ttyInput = new (require('tty').ReadStream)(ttyFd);
576
- ttyOutput = new (require('tty').WriteStream)(ttyFd);
577
- }
578
- catch (e) {
579
- // Fallback: if /dev/tty unavailable (some CI/remote environments),
580
- // use stdin/stdout but disable all event handling
581
- ttyInput = process.stdin;
582
- ttyOutput = process.stdout;
575
+ if (inTmux) {
576
+ try {
577
+ const ttyFd = fs.openSync('/dev/tty', 'r+');
578
+ ttyInput = new (require('tty').ReadStream)(ttyFd);
579
+ ttyOutput = new (require('tty').WriteStream)(ttyFd);
580
+ }
581
+ catch (e) {
582
+ // Fallback: if /dev/tty unavailable, use stdin/stdout
583
+ ttyInput = process.stdin;
584
+ ttyOutput = process.stdout;
585
+ }
583
586
  }
584
587
  const screen = blessed.screen({
585
588
  smartCSR: true,
@@ -596,16 +599,17 @@ async function launchDashboard(initialSessionName, jsonlPath, refreshMs) {
596
599
  resizeTimeout: 300, // Debounce resize events
597
600
  });
598
601
  // ══════════════════════════════════════════════════════════════════════════
599
- // DISABLE TERMINAL CONTROL SEQUENCE HIJACKING
600
- // Prevent blessed from sending control sequences that might interfere with
601
- // other panes in tmux. The /dev/tty approach already isolates this, but we
602
- // also disable the raw mode entirely to be extra safe.
602
+ // DISABLE TERMINAL CONTROL SEQUENCE HIJACKING (TMUX ONLY)
603
+ // When running in a tmux split pane alongside Claude Code, prevent blessed
604
+ // from sending control sequences that would interfere with the other pane.
605
+ // In standalone mode (including Windows Terminal split), blessed needs the
606
+ // alternate buffer and raw mode for clean rendering without artifacts.
603
607
  // ══════════════════════════════════════════════════════════════════════════
604
- if (screen.program) {
605
- // Override alternateBuffer to do nothing
608
+ if (inTmux && screen.program) {
609
+ // Override alternateBuffer to do nothing (tmux pane isolation)
606
610
  screen.program.alternateBuffer = () => { };
607
611
  screen.program.normalBuffer = () => { };
608
- // Don't enter raw mode — let the OS handle it
612
+ // Don't enter raw mode — let the OS handle it (tmux pane isolation)
609
613
  if (screen.program.setRawMode) {
610
614
  screen.program.setRawMode = (enabled) => {
611
615
  // Silently ignore raw mode requests
@@ -1404,11 +1408,13 @@ async function launchDashboard(initialSessionName, jsonlPath, refreshMs) {
1404
1408
  // Delay first ccusage call — let blessed render first, then load heavy data
1405
1409
  setTimeout(() => updateWindowBox(), 2000);
1406
1410
  const pollInterval = setInterval(updateDashboard, refreshMs);
1411
+ // Animation interval — slower on Windows to reduce blessed redraw flicker
1412
+ const animMs = process.platform === 'win32' ? 1000 : 500;
1407
1413
  const headerAnimInterval = setInterval(() => {
1408
1414
  // Keep advancing across the full session label; wrap at a large value.
1409
1415
  waveOffset = (waveOffset + 1) % 1000000;
1410
1416
  renderHeader();
1411
- }, 500);
1417
+ }, animMs);
1412
1418
  const fortuneInterval = setInterval(() => {
1413
1419
  if (activeFortunes.length === 0)
1414
1420
  return;
@@ -1134,7 +1134,10 @@ async function run(options) {
1134
1134
  // ══════════════════════════════════════════════════════════════════════════
1135
1135
  // STARTUP BANNER WITH COLOR PULSE ANIMATION
1136
1136
  // ══════════════════════════════════════════════════════════════════════════
1137
- const skipFancyIntro = process.env.EKKOS_REMOTE_SESSION === '1' || process.env.EKKOS_NO_SPLASH === '1';
1137
+ // Skip cursor-manipulation animations on Windows ConPTY + cmd /c can't handle rapid
1138
+ // cursor repositioning (\x1B[6A, \b, etc.), leaving the terminal in a dirty state that
1139
+ // causes Ink rendering artifacts in Claude Code. Use a clean static banner instead.
1140
+ const skipFancyIntro = isWindows || process.env.EKKOS_REMOTE_SESSION === '1' || process.env.EKKOS_NO_SPLASH === '1';
1138
1141
  if (!skipFancyIntro) {
1139
1142
  const logoLines = [
1140
1143
  ' ▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄ ▄▄',
@@ -1320,8 +1323,10 @@ async function run(options) {
1320
1323
  console.log('');
1321
1324
  }
1322
1325
  else {
1326
+ // Static banner for Windows / remote / no-splash — no cursor manipulation
1327
+ console.log('');
1328
+ console.log(chalk_1.default.hex('#FF6B35').bold(' ekkOS_Pulse') + chalk_1.default.gray(' — Context is finite. Intelligence isn\'t.'));
1323
1329
  console.log('');
1324
- console.log(chalk_1.default.cyan(' ekkOS remote session ready'));
1325
1330
  if (bypass) {
1326
1331
  console.log(chalk_1.default.yellow(' ⚡ Bypass permissions mode enabled'));
1327
1332
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekkos/cli",
3
- "version": "1.2.9",
3
+ "version": "1.2.11",
4
4
  "description": "Setup ekkOS memory for AI coding assistants (Claude Code, Cursor, Windsurf)",
5
5
  "main": "dist/index.js",
6
6
  "bin": {