@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.
- package/dist/commands/dashboard.js +26 -20
- package/dist/commands/run.js +7 -2
- package/package.json +1 -1
|
@@ -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
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
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
|
-
//
|
|
601
|
-
//
|
|
602
|
-
//
|
|
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
|
-
},
|
|
1417
|
+
}, animMs);
|
|
1412
1418
|
const fortuneInterval = setInterval(() => {
|
|
1413
1419
|
if (activeFortunes.length === 0)
|
|
1414
1420
|
return;
|
package/dist/commands/run.js
CHANGED
|
@@ -1134,7 +1134,10 @@ async function run(options) {
|
|
|
1134
1134
|
// ══════════════════════════════════════════════════════════════════════════
|
|
1135
1135
|
// STARTUP BANNER WITH COLOR PULSE ANIMATION
|
|
1136
1136
|
// ══════════════════════════════════════════════════════════════════════════
|
|
1137
|
-
|
|
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
|
}
|