From 3be35959071222ac22b79796c37901462e7fa2fc Mon Sep 17 00:00:00 2001 From: arkon Date: Mon, 19 Jan 2026 02:04:30 +0100 Subject: [PATCH] fix: filter terminal focus escape sequences Filter out ^[[I (focus in) and ^[[O (focus out) ANSI codes that appear when clicking in/out of the Claude terminal. Also filters the enable/ disable sequences (\x1b[?1004h and \x1b[?1004l). Co-Authored-By: Claude Opus 4.5 --- src/session.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/session.ts b/src/session.ts index c26a22cd..b175a51d 100644 --- a/src/session.ts +++ b/src/session.ts @@ -16,6 +16,10 @@ const TEXT_OUTPUT_TRIM_SIZE = 1.5 * 1024 * 1024; // Maximum number of Claude messages to keep in memory const MAX_MESSAGES = 1000; +// Filter out terminal focus escape sequences (focus in/out reports) +// ^[[I (focus in), ^[[O (focus out), and the enable/disable sequences +const FOCUS_ESCAPE_FILTER = /\x1b\[\?1004[hl]|\x1b\[[IO]/g; + export interface ClaudeMessage { type: 'system' | 'assistant' | 'user' | 'result'; subtype?: string; @@ -297,7 +301,11 @@ export class Session extends EventEmitter { this._pid = this.ptyProcess.pid; console.log('[Session] Interactive PTY spawned with PID:', this._pid); - this.ptyProcess.onData((data: string) => { + this.ptyProcess.onData((rawData: string) => { + // Filter out focus escape sequences + const data = rawData.replace(FOCUS_ESCAPE_FILTER, ''); + if (!data) return; // Skip if only focus sequences + this._terminalBuffer += data; this._lastActivityAt = Date.now(); @@ -376,7 +384,11 @@ export class Session extends EventEmitter { this._pid = this.ptyProcess.pid; console.log('[Session] Shell PTY spawned with PID:', this._pid); - this.ptyProcess.onData((data: string) => { + this.ptyProcess.onData((rawData: string) => { + // Filter out focus escape sequences + const data = rawData.replace(FOCUS_ESCAPE_FILTER, ''); + if (!data) return; // Skip if only focus sequences + this._terminalBuffer += data; this._lastActivityAt = Date.now(); @@ -444,7 +456,11 @@ export class Session extends EventEmitter { console.log('[Session] PTY spawned with PID:', this._pid); // Handle terminal data - this.ptyProcess.onData((data: string) => { + this.ptyProcess.onData((rawData: string) => { + // Filter out focus escape sequences + const data = rawData.replace(FOCUS_ESCAPE_FILTER, ''); + if (!data) return; // Skip if only focus sequences + this._terminalBuffer += data; this._lastActivityAt = Date.now();