Skip to content

Commit ec924e6

Browse files
ozgesolidkeyclaude
andcommitted
Fix Linux terminal echo loop by wrapping shell with script (v0.7.2)
The Linux fallback path used `bash -i` with piped stdio, which caused typed characters to echo back through stdout and produce looping output. Now wraps the shell with `script -qfc` (util-linux) to provide a real PTY when node-pty isn't available. Falls back to the previous direct-bash mode if `script` isn't installed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7ab955a commit ec924e6

2 files changed

Lines changed: 17 additions & 3 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "logan",
3-
"version": "0.7.1",
3+
"version": "0.7.2",
44
"description": "AI-powered log file viewer and analyzer — handles 14M+ lines with virtual scrolling, MCP agent integration, live serial/logcat/SSH connections, pattern correlation, diff view, and built-in terminal",
55
"keywords": [
66
"log-analyzer",

src/main/index.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4971,9 +4971,23 @@ ipcMain.handle(IPC.TERMINAL_CREATE_LOCAL, async (_, sessionId: string, options?:
49714971
return { success: true, label: 'Local' };
49724972
}
49734973

4974-
// Fallback: child_process.spawn with piped stdio (Linux)
4974+
// Fallback for Linux (no node-pty): use `script` to wrap the shell
4975+
// in a real PTY. `script -qfc <cmd> /dev/null` is portable across
4976+
// util-linux and BSD `script` implementations.
49754977
const env = { ...process.env, TERM: 'xterm-256color', COLUMNS: String(cols), LINES: String(rows) };
4976-
const child = spawn(shellPath, ['-i'], { cwd, env, stdio: ['pipe', 'pipe', 'pipe'] });
4978+
let scriptCmd: string;
4979+
let scriptArgs: string[];
4980+
try {
4981+
execSync('which script', { timeout: 1000 });
4982+
// util-linux script: -q quiet, -f flush, -c command, /dev/null = no typescript file
4983+
scriptCmd = 'script';
4984+
scriptArgs = ['-qfc', shellPath, '/dev/null'];
4985+
} catch {
4986+
// No `script` available — fall back to direct bash (will have echo issues but works)
4987+
scriptCmd = shellPath;
4988+
scriptArgs = ['-i'];
4989+
}
4990+
const child = spawn(scriptCmd, scriptArgs, { cwd, env, stdio: ['pipe', 'pipe', 'pipe'] });
49774991

49784992
// Wrap child process to match pty interface used by session handlers
49794993
const procShim = {

0 commit comments

Comments
 (0)