fix(maestro): chain default-terminal into new-session instead of pre-set
ci / rust (push) Successful in 2m59s
ci / rust (push) Successful in 2m59s
CI e2e tests failed with "tmux exited with code 1: server exited unexpectedly" because the startup `start-server \; set-option -g default-terminal` call left an empty server that tmux's default `exit-empty on` killed before the first `new-session` could attach. Move the `set-option -g default-terminal tmux-256color` into the same tmux command as `new-session` (chained with `;`) so a single tmux invocation creates the server, sets the option, and spawns the pane. The pane reads `default-terminal` at creation time, so chaining before `new-session` still applies to the very first session. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -121,12 +121,6 @@ async fn run(config_override: Option<PathBuf>) -> Result<(), Box<dyn Error>> {
|
||||
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,
|
||||
|
||||
@@ -77,13 +77,17 @@ impl Tmux {
|
||||
c
|
||||
}
|
||||
|
||||
/// `tmux new-session -d -e TERM=xterm-256color -e COLORTERM=truecolor -s maestro-<id> -c <cwd> <command>`.
|
||||
/// `tmux set-option -g default-terminal tmux-256color \; new-session -d -e TERM=xterm-256color -e COLORTERM=truecolor -s maestro-<id> -c <cwd> <command>`.
|
||||
///
|
||||
/// `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 <name> <value>`. 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-<id>`.
|
||||
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<OsString> {
|
||||
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",
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user