diff --git a/crates/maestro-daemon/src/main.rs b/crates/maestro-daemon/src/main.rs index e0c108d..a37a934 100644 --- a/crates/maestro-daemon/src/main.rs +++ b/crates/maestro-daemon/src/main.rs @@ -121,12 +121,6 @@ async fn run(config_override: Option) -> Result<(), Box> { let sidecar = SidecarStore::new(config.sidecar_dir()); let worktree_mgr = WorktreeManager::new(config.worktree_root.clone()); let tmux = Tmux::new(); - // The pane process's TERM comes from tmux's `default-terminal`, which on - // most distros is `screen` (8 colors). Promote it so attach clients see - // 256-color output. NAP-252. - if let Err(e) = tmux.set_option_global("default-terminal", "tmux-256color") { - tracing::warn!(error = ?e, "failed to set tmux default-terminal — sessions may lack color"); - } let manager = SessionManager::new_with_replay( config.daemon_id.clone(), tmux, diff --git a/crates/maestro-daemon/src/tmux.rs b/crates/maestro-daemon/src/tmux.rs index bf47ba8..1f017de 100644 --- a/crates/maestro-daemon/src/tmux.rs +++ b/crates/maestro-daemon/src/tmux.rs @@ -77,13 +77,17 @@ impl Tmux { c } - /// `tmux new-session -d -e TERM=xterm-256color -e COLORTERM=truecolor -s maestro- -c `. + /// `tmux set-option -g default-terminal tmux-256color \; new-session -d -e TERM=xterm-256color -e COLORTERM=truecolor -s maestro- -c `. /// /// `command` is passed as a single shell-line argument to tmux, which - /// invokes it via `$SHELL -c`. The `-e TERM=…`/`COLORTERM=…` flags ensure - /// the spawned shell sees sensible color env vars even when `maestrod` - /// runs from a stripped systemd unit. Pair with [`Self::set_option_global`] - /// of `default-terminal` for true 256-color output in the pane. + /// invokes it via `$SHELL -c`. Two layers ensure attach clients see color: + /// the `-e TERM=…`/`COLORTERM=…` flags populate the spawned shell's env + /// even when `maestrod` runs from a stripped systemd unit, and the chained + /// `set-option -g default-terminal tmux-256color` overrides tmux's + /// distro-default `screen` (8-color) terminfo for the pane process. The + /// `set-option` is chained into the same tmux invocation because a + /// stand-alone server with no sessions exits immediately under tmux's + /// default `exit-empty on`. pub fn new_session(&self, id: Uuid, cwd: &Path, command: &str) -> Result<(), TmuxError> { let name = session_name(id); let out = self @@ -93,19 +97,6 @@ impl Tmux { check(out) } - /// `tmux start-server \; set-option -g `. Used on daemon - /// startup to set `default-terminal` to `tmux-256color` so the pane's - /// `TERM` is a 256-color terminfo entry (the distro default `screen` caps - /// at 8). The chained `start-server` makes the call work before any - /// session exists. - pub fn set_option_global(&self, name: &str, value: &str) -> Result<(), TmuxError> { - let out = self - .cmd() - .args(["start-server", ";", "set-option", "-g", name, value]) - .output()?; - check(out) - } - /// `tmux kill-session -t maestro-`. pub fn kill_session(&self, id: Uuid) -> Result<(), TmuxError> { let name = session_name(id); @@ -224,6 +215,11 @@ pub fn session_name(id: Uuid) -> String { /// can be asserted without invoking tmux. fn new_session_args(name: &str, cwd: &Path, command: &str) -> Vec { vec![ + OsString::from("set-option"), + OsString::from("-g"), + OsString::from("default-terminal"), + OsString::from("tmux-256color"), + OsString::from(";"), OsString::from("new-session"), OsString::from("-d"), OsString::from("-e"), @@ -254,12 +250,17 @@ mod tests { use super::*; #[test] - fn new_session_args_pass_256color_env() { + fn new_session_args_pass_256color_env_and_default_terminal() { let args = new_session_args("maestro-abc", Path::new("/tmp/proj"), "sleep 30"); let strs: Vec<&str> = args.iter().map(|s| s.to_str().unwrap()).collect(); assert_eq!( strs, vec![ + "set-option", + "-g", + "default-terminal", + "tmux-256color", + ";", "new-session", "-d", "-e", diff --git a/crates/maestro-daemon/tests/tmux.rs b/crates/maestro-daemon/tests/tmux.rs index a6264e1..40acbc2 100644 --- a/crates/maestro-daemon/tests/tmux.rs +++ b/crates/maestro-daemon/tests/tmux.rs @@ -123,10 +123,6 @@ fn new_session_sets_256color_env_and_default_terminal() { let sink_path = sink.path().join("env.log"); let id = Uuid::new_v4(); - fx.tmux - .set_option_global("default-terminal", "tmux-256color") - .expect("set default-terminal"); - fx.tmux .new_session(id, cwd.path(), "bash --noprofile --norc") .expect("new_session");