From 5a4a67f7b8358564fb9337f2955553f166ad57bd Mon Sep 17 00:00:00 2001 From: Daniel Bast <2790401+dbast@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:21:51 +0100 Subject: [PATCH] fix(progress): Detect Ghostty through TERM over SSH Recognize TERM=xterm-ghostty alongside TERM_PROGRAM=ghostty. Observed in a Ghostty SSH session: stderr was a TTY and TERM was xterm-ghostty, but TERM_PROGRAM was absent because the server did not accept environment forwarding (default for OpenSSH). Progress detection therefore returned false despite the terminal supporting OSC 9;4. SSH sends TERM when requesting a PTY without requiring AcceptEnv. This fallback enables detection in that setup without SSH server configuration changes. The existing TTY gate remains unchanged; generic xterm values are not treated as supporting progress. The same exact TERM fallback is also used here: https://github.com/MoonshotAI/kimi-code/blob/main/apps/kimi-code/src/tui/utils/terminal-notification.ts References: https://ghostty.org/docs/help/terminfo https://ghostty.org/docs/install/release-notes/1-2-0#graphical-progress-bars --- crates/anstyle-progress/src/query.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/anstyle-progress/src/query.rs b/crates/anstyle-progress/src/query.rs index 7e8af688..d006676b 100644 --- a/crates/anstyle-progress/src/query.rs +++ b/crates/anstyle-progress/src/query.rs @@ -21,6 +21,16 @@ pub fn supports_term_progress(is_terminal: bool) -> bool { return true; } + // Ghostty is detected through TERM_PROGRAM locally and over SSH when the + // client requests forwarding and the server's AcceptEnv permits it. + // SSH also carries TERM in PTY requests independently of AcceptEnv, so + // xterm-ghostty identifies sessions without TERM_PROGRAM forwarding. + // This fallback does not apply when SSH integration or user configuration + // substitutes xterm-256color. + if std::env::var("TERM").as_deref() == Ok("xterm-ghostty") { + return true; + } + // https://github.com/microsoft/terminal/pull/8055 if std::env::var("WT_SESSION").is_ok() { return true;