aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-08-16 00:05:24 +0300
committerGitHub <noreply@github.com>2026-08-16 00:05:24 +0300
commit2b4b3849ca7760d6fcff10cd560553bb8081a8e2 (patch)
treeae2439467edc2595d632ade5f17affaaa558caf4
parent9166e07b31f920540802fe46cbe3c0d52eece2bd (diff)
fix(theme): skip host palette queries under wsl (#2852)
refs #2440
-rw-r--r--docs/next/CHANGELOG.md1
-rw-r--r--src/app/theme_sync.rs4
-rw-r--r--src/client/mod.rs9
-rw-r--r--src/platform/fallback.rs4
-rw-r--r--src/platform/linux.rs4
-rw-r--r--src/platform/macos.rs4
-rw-r--r--src/platform/windows.rs4
-rw-r--r--src/terminal_theme.rs15
8 files changed, 38 insertions, 7 deletions
diff --git a/docs/next/CHANGELOG.md b/docs/next/CHANGELOG.md
index 8190fbc1..1ded91d0 100644
--- a/docs/next/CHANGELOG.md
+++ b/docs/next/CHANGELOG.md
@@ -23,6 +23,7 @@
- Experimental pane graphics now support bounded named layers, acknowledged full-RGBA primary-layer direct file frames on audited local terminals, owned BGRA fallback, exact pixel mouse input, and placement-only resize replay.
### Fixed
+- Herdr no longer sends the full OSC 4 palette query burst under WSL, preventing reply fragments from leaking into the shell through ConPTY. (#2440)
- Qwen Code panes now use locale-independent terminal-title states and localized confirmation fallbacks, preventing active or blocked turns from appearing idle. (#2756)
- Closing a terminal running `herdr --remote` no longer produces a local client core dump while the remote session stays alive. (#2424)
- Active Space and Agent rows now use dedicated theme colors that remain visible when the host terminal background matches the selected Herdr theme. (#2792)
diff --git a/src/app/theme_sync.rs b/src/app/theme_sync.rs
index 6bf06685..58f95bec 100644
--- a/src/app/theme_sync.rs
+++ b/src/app/theme_sync.rs
@@ -13,7 +13,9 @@ impl App {
pub(super) fn query_host_terminal_theme(&self) {
use std::io::Write;
- let query = crate::terminal_theme::host_terminal_theme_query_sequence();
+ let query = crate::terminal_theme::host_terminal_theme_query_sequence(
+ crate::platform::should_query_host_terminal_palette(),
+ );
let _ = std::io::stdout().write_all(query.as_bytes());
let _ = std::io::stdout().flush();
}
diff --git a/src/client/mod.rs b/src/client/mod.rs
index b70b6c9c..c33157fb 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -2571,7 +2571,9 @@ fn should_query_host_terminal_theme() -> bool {
}
fn write_host_terminal_theme_query(mut writer: impl io::Write) -> io::Result<()> {
- let query = crate::terminal_theme::host_terminal_theme_query_sequence();
+ let query = crate::terminal_theme::host_terminal_theme_query_sequence(
+ crate::platform::should_query_host_terminal_palette(),
+ );
writer.write_all(query.as_bytes())?;
writer.flush()
}
@@ -2999,7 +3001,10 @@ mod tests {
write_host_terminal_theme_query(&mut output).unwrap();
assert_eq!(
output,
- crate::terminal_theme::host_terminal_theme_query_sequence().as_bytes()
+ crate::terminal_theme::host_terminal_theme_query_sequence(
+ crate::platform::should_query_host_terminal_palette(),
+ )
+ .as_bytes()
);
assert!(!output
.windows(crate::terminal_theme::HOST_COLOR_SCHEME_QUERY_SEQUENCE.len())
diff --git a/src/platform/fallback.rs b/src/platform/fallback.rs
index f0e5c2ca..1b02fae8 100644
--- a/src/platform/fallback.rs
+++ b/src/platform/fallback.rs
@@ -89,6 +89,10 @@ pub(crate) fn should_draw_host_cursor_by_default() -> bool {
false
}
+pub(crate) fn should_query_host_terminal_palette() -> bool {
+ false
+}
+
pub(crate) fn hostname() -> Option<String> {
None
}
diff --git a/src/platform/linux.rs b/src/platform/linux.rs
index 89e6c96d..f84d9e96 100644
--- a/src/platform/linux.rs
+++ b/src/platform/linux.rs
@@ -41,6 +41,10 @@ pub(crate) fn should_draw_host_cursor_by_default() -> bool {
running_inside_wsl()
}
+pub(crate) fn should_query_host_terminal_palette() -> bool {
+ !running_inside_wsl()
+}
+
fn running_inside_wsl() -> bool {
proc_file_indicates_wsl("/proc/sys/kernel/osrelease")
|| proc_file_indicates_wsl("/proc/version")
diff --git a/src/platform/macos.rs b/src/platform/macos.rs
index d85da440..9c59b39c 100644
--- a/src/platform/macos.rs
+++ b/src/platform/macos.rs
@@ -26,6 +26,10 @@ pub(crate) fn should_draw_host_cursor_by_default() -> bool {
false
}
+pub(crate) fn should_query_host_terminal_palette() -> bool {
+ true
+}
+
fn raw_command_argv(command: &str, flag: &str) -> Vec<std::ffi::OsString> {
vec!["/bin/sh".into(), flag.into(), command.into()]
}
diff --git a/src/platform/windows.rs b/src/platform/windows.rs
index 83f85e6a..4e444877 100644
--- a/src/platform/windows.rs
+++ b/src/platform/windows.rs
@@ -362,6 +362,10 @@ pub(crate) fn should_draw_host_cursor_by_default() -> bool {
true
}
+pub(crate) fn should_query_host_terminal_palette() -> bool {
+ false
+}
+
/// The machine's node name, as shown by tmux's `#h`.
pub(crate) fn hostname() -> Option<String> {
std::env::var("COMPUTERNAME")
diff --git a/src/terminal_theme.rs b/src/terminal_theme.rs
index 3f04cc4c..2460731e 100644
--- a/src/terminal_theme.rs
+++ b/src/terminal_theme.rs
@@ -79,12 +79,14 @@ impl TerminalTheme {
}
}
-pub fn host_terminal_theme_query_sequence() -> String {
+pub fn host_terminal_theme_query_sequence(include_palette: bool) -> String {
use std::fmt::Write as _;
let mut sequence = String::from(HOST_COLOR_QUERY_SEQUENCE);
- for index in 0..=u8::MAX {
- let _ = write!(sequence, "\x1b]4;{index};?\x1b\\");
+ if include_palette {
+ for index in 0..=u8::MAX {
+ let _ = write!(sequence, "\x1b]4;{index};?\x1b\\");
+ }
}
sequence
}
@@ -218,11 +220,16 @@ mod tests {
))
);
- let query = host_terminal_theme_query_sequence();
+ let query = host_terminal_theme_query_sequence(true);
assert!(query.starts_with(HOST_COLOR_QUERY_SEQUENCE));
assert!(query.contains("\x1b]4;0;?\x1b\\"));
assert!(query.ends_with("\x1b]4;255;?\x1b\\"));
assert_eq!(query.matches("\x1b]4;").count(), 256);
+
+ assert_eq!(
+ host_terminal_theme_query_sequence(false),
+ HOST_COLOR_QUERY_SEQUENCE
+ );
}
#[test]