Skip to content

Commit 032b32d

Browse files
BunsDevclaude
andauthored
feat(steer): opt-in /steer command to steer the running turn (OpenCoven#125)
Adds a discoverable `/steer <message>` command, gated behind a new off-by- default `steer` Cargo feature (build with `--features steer`). Behavior: - While a turn is in flight: queue the message; it auto-runs after the current turn, mirroring the existing Enter-while-busy queueing (issue OpenCoven#149). - When idle: submit the message immediately via the auto-submit path. Implementation reuses the proven queued_messages + pending_auto_submit mechanisms, so no new turn-dispatch logic is introduced. The command is registered in PROMPT_SLASH_COMMANDS (feature-gated) for palette/help discoverability, handled in the CLI main loop, and added to the prompt_slash_commands_covers_registry allow-list (like /handoff, /stats). Verified: builds with and without the feature; the coverage test passes in both configurations; /steer appears in the command palette when enabled. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6178c13 commit 032b32d

5 files changed

Lines changed: 49 additions & 1 deletion

File tree

src-rust/crates/cli/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ path = "src/main.rs"
1111
default = ["voice"]
1212
voice = ["claurst-core/voice", "claurst-tui/voice"]
1313

14+
# Opt-in `/steer` command (see crates/tui). Build with `--features steer`.
15+
steer = ["claurst-tui/steer"]
16+
1417
[dependencies]
1518
claurst-core = { workspace = true }
1619
claurst-api = { workspace = true }

src-rust/crates/cli/src/main.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,6 +2631,39 @@ async fn run_interactive(
26312631
let cmd_name = cmd_name.to_string();
26322632
let cmd_args = cmd_args.to_string();
26332633

2634+
// ── /steer <message> (opt-in feature) ─────────────────────
2635+
// Explicit steering: queue the message when a turn is in
2636+
// flight (it auto-runs after the current turn, mirroring
2637+
// Enter-while-busy), or submit it immediately when idle.
2638+
#[cfg(feature = "steer")]
2639+
if cmd_name == "steer" {
2640+
let msg = cmd_args.trim().to_string();
2641+
if msg.is_empty() {
2642+
app.notifications.push(
2643+
claurst_tui::NotificationKind::Info,
2644+
"Usage: /steer <message> — steer the running turn"
2645+
.to_string(),
2646+
Some(4),
2647+
);
2648+
continue;
2649+
}
2650+
if app.is_streaming || current_query.is_some() {
2651+
let preview: String = msg.chars().take(40).collect();
2652+
app.queued_messages.push_back(msg);
2653+
let total = app.queued_messages.len();
2654+
app.notifications.push(
2655+
claurst_tui::NotificationKind::Info,
2656+
format!("Steer queued ({total}): {preview}"),
2657+
Some(3),
2658+
);
2659+
} else {
2660+
// Idle: submit now via the auto-submit path.
2661+
app.set_prompt_text(msg);
2662+
app.pending_auto_submit = true;
2663+
}
2664+
continue;
2665+
}
2666+
26342667
// ── Step 1: TUI-layer intercept (overlays, toggles) ────────
26352668
// Run first so we know whether a UI overlay opened, which
26362669
// lets us suppress redundant CLI text output below.

src-rust/crates/commands/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11314,7 +11314,10 @@ mod tests {
1131411314
// - stats: intercepted directly by the TUI to open the live stats
1131511315
// dialog; the named CLI `stats` command handles aggregate saved
1131611316
// session reports outside the TUI.
11317-
const ALLOWED_ALIAS_NAMES: &[&str] = &["quit", "settings", "survey", "handoff"];
11317+
// - steer: opt-in feature, intercepted directly in the CLI main loop
11318+
// (queues/sends a steering message); only present when built with
11319+
// `--features steer`.
11320+
const ALLOWED_ALIAS_NAMES: &[&str] = &["quit", "settings", "survey", "handoff", "steer"];
1131811321

1131911322
let prompt_names: HashSet<&str> = claurst_tui::app::PROMPT_SLASH_COMMANDS
1132011323
.iter()

src-rust/crates/tui/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ edition.workspace = true
77
# Enable real microphone capture for voice PTT mode.
88
voice = ["claurst-core/voice", "dep:cpal", "dep:hound"]
99

10+
# Opt-in `/steer` command: explicitly queue a steering message for the running
11+
# turn (auto-runs after it), or submit immediately when idle. Off by default.
12+
steer = []
13+
1014
# UI & Interaction features (pass-through from cc-core)
1115
token_budget = ["claurst-core/token_budget"]
1216
ultraplan = ["claurst-core/ultraplan"]

src-rust/crates/tui/src/app.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ pub const PROMPT_SLASH_COMMANDS: &[(&str, &str)] = &[
133133
"status",
134134
"Show session status or run diagnostics (/status doctor)",
135135
),
136+
#[cfg(feature = "steer")]
137+
(
138+
"steer",
139+
"Queue a steering message for the running turn (or send it now if idle)",
140+
),
136141
("survey", "Open session feedback survey"),
137142
("tasks", "Manage tracked background tasks"),
138143
(

0 commit comments

Comments
 (0)