From 78130d4bb70a8f55cb5953f4d7b49584f63d783a Mon Sep 17 00:00:00 2001 From: Srinath Padmanabhan <17151014+srithreepo@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:08:13 -0800 Subject: [PATCH] fix(cli): wrap terminal capability queries in hidden sequence (#19080) Co-authored-by: Srinath Padmanabhan Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../ui/utils/terminalCapabilityManager.test.ts | 12 ++++++++++++ .../cli/src/ui/utils/terminalCapabilityManager.ts | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/ui/utils/terminalCapabilityManager.test.ts b/packages/cli/src/ui/utils/terminalCapabilityManager.test.ts index fce18cfb01..846fe2d8cb 100644 --- a/packages/cli/src/ui/utils/terminalCapabilityManager.test.ts +++ b/packages/cli/src/ui/utils/terminalCapabilityManager.test.ts @@ -11,6 +11,7 @@ import { enableKittyKeyboardProtocol, enableModifyOtherKeys, } from '@google/gemini-cli-core'; +import * as fs from 'node:fs'; // Mock fs vi.mock('node:fs', () => ({ @@ -289,5 +290,16 @@ describe('TerminalCapabilityManager', () => { expect(manager.isKittyProtocolEnabled()).toBe(false); expect(enableModifyOtherKeys).not.toHaveBeenCalled(); }); + + it('should wrap queries in hidden/clear sequence', async () => { + const manager = TerminalCapabilityManager.getInstance(); + void manager.detectCapabilities(); + + expect(fs.writeSync).toHaveBeenCalledWith( + expect.anything(), + // eslint-disable-next-line no-control-regex + expect.stringMatching(/^\x1b\[8m.*\x1b\[2K\r\x1b\[0m$/s), + ); + }); }); }); diff --git a/packages/cli/src/ui/utils/terminalCapabilityManager.ts b/packages/cli/src/ui/utils/terminalCapabilityManager.ts index 447c79ce91..76de5b831e 100644 --- a/packages/cli/src/ui/utils/terminalCapabilityManager.ts +++ b/packages/cli/src/ui/utils/terminalCapabilityManager.ts @@ -43,6 +43,9 @@ export class TerminalCapabilityManager { private static readonly TERMINAL_NAME_QUERY = '\x1b[>q'; private static readonly DEVICE_ATTRIBUTES_QUERY = '\x1b[c'; private static readonly MODIFY_OTHER_KEYS_QUERY = '\x1b[>4;?m'; + private static readonly HIDDEN_MODE = '\x1b[8m'; + private static readonly CLEAR_LINE_AND_RETURN = '\x1b[2K\r'; + private static readonly RESET_ATTRIBUTES = '\x1b[0m'; /** * Triggers a terminal background color query. @@ -219,11 +222,19 @@ export class TerminalCapabilityManager { try { fs.writeSync( process.stdout.fd, - TerminalCapabilityManager.KITTY_QUERY + + // Use hidden mode to prevent potential "m" character from being printed + // to the terminal during startup when querying for modifyOtherKeys. + // This can happen on some terminals that might echo the query or + // malform the response. We hide the output, send queries, then + // immediately clear the line and reset attributes. + TerminalCapabilityManager.HIDDEN_MODE + + TerminalCapabilityManager.KITTY_QUERY + TerminalCapabilityManager.OSC_11_QUERY + TerminalCapabilityManager.TERMINAL_NAME_QUERY + TerminalCapabilityManager.MODIFY_OTHER_KEYS_QUERY + - TerminalCapabilityManager.DEVICE_ATTRIBUTES_QUERY, + TerminalCapabilityManager.DEVICE_ATTRIBUTES_QUERY + + TerminalCapabilityManager.CLEAR_LINE_AND_RETURN + + TerminalCapabilityManager.RESET_ATTRIBUTES, ); } catch (e) { debugLogger.warn('Failed to write terminal capability queries:', e);