diff --git a/crates/goose-cli/src/session/mod.rs b/crates/goose-cli/src/session/mod.rs index f099f7a7e4..0622550092 100644 --- a/crates/goose-cli/src/session/mod.rs +++ b/crates/goose-cli/src/session/mod.rs @@ -1210,6 +1210,9 @@ impl CliSession { && std::io::stdin().is_terminal() && std::io::stdout().is_terminal(); let (steer_control, mut steer_rx) = steer::spawn_steer_reader(steer_enabled); + if steer_enabled { + output::render_steer_hint(); + } let mut stream = self .agent diff --git a/crates/goose-cli/src/session/output.rs b/crates/goose-cli/src/session/output.rs index 98ccde6151..7aef4ad941 100644 --- a/crates/goose-cli/src/session/output.rs +++ b/crates/goose-cli/src/session/output.rs @@ -439,6 +439,24 @@ pub fn render_text_no_newlines(text: &str, color: Option, dim: bool) { print!("{}", styled_text); } +/// Print a faint hint that mid-run steering is available. Safe to call while +/// the thinking spinner is active: the spinner is hidden first and restored +/// after so it doesn't duplicate its line. +pub fn render_steer_hint() { + if !std::io::stdout().is_terminal() { + return; + } + let was_thinking = THINKING.with(|t| t.borrow().is_shown()); + hide_thinking(); + println!( + "{}", + style("↳ type a steering message and press Enter to queue it").dim() + ); + if was_thinking { + show_thinking(); + } +} + /// Draw the live steer compose line. Called on every keystroke while the /// user types mid-run. When `in_place` is true the compose line was the last /// thing drawn, so it is redrawn over itself; otherwise it starts on a fresh