Skip to content

Commit c0916ca

Browse files
committed
feat(cli): auto-approve mode (/auto) + cwd context
- /auto toggles Codex-style approval mode: while on, tool-confirmation prompts are auto-approved (shown as "⚡ auto-approved <tool>") instead of opening the modal. - Welcome screen shows the working directory for context; /help lists /auto.
1 parent fbfe7a7 commit c0916ca

1 file changed

Lines changed: 43 additions & 5 deletions

File tree

cli/src/main.rs

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ struct App {
115115
/// Accumulated streamed JSON args of the in-progress tool call, so the
116116
/// result line can show what the tool actually did (command/path/pattern).
117117
tool_args: String,
118+
/// When true, tool-confirmation prompts are auto-approved (Codex-style
119+
/// approval mode), toggled with `/auto`.
120+
auto_approve: bool,
121+
/// Working directory shown for context.
122+
cwd: String,
118123
width: u16,
119124
height: u16,
120125
keymap: Keymap<Action>,
@@ -125,10 +130,14 @@ impl Model for App {
125130

126131
fn init(&mut self) -> Option<Cmd<Msg>> {
127132
if self.messages.is_empty() {
128-
let welcome = Style::new().fg(Color::BrightBlack).italic().render(
129-
" A3S Code — type a message and press Enter.\n \
130-
Esc interrupt | Ctrl+C quit | PgUp/PgDn scroll | /help\n",
131-
);
133+
let welcome = Style::new()
134+
.fg(Color::BrightBlack)
135+
.italic()
136+
.render(&format!(
137+
" A3S Code — {}\n Type a message and press Enter.\n \
138+
↑/↓ history · Esc interrupt · /help · Ctrl+C quit\n",
139+
self.cwd
140+
));
132141
self.viewport.set_content(&welcome);
133142
} else {
134143
// Resumed session — show the prior conversation, scrolled to the end.
@@ -325,13 +334,25 @@ impl App {
325334
"/help" => {
326335
self.messages
327336
.push(Style::new().fg(Color::BrightBlack).render(
328-
" commands: /clear reset · /exit quit\n \
337+
" commands: /clear reset · /auto toggle auto-approve · /exit quit\n \
329338
Enter send · ↑/↓ history · Esc interrupt · Ctrl+C quit · PgUp/PgDn scroll",
330339
));
331340
self.textarea.clear();
332341
self.rebuild_viewport();
333342
return None;
334343
}
344+
"/auto" => {
345+
self.auto_approve = !self.auto_approve;
346+
let state = if self.auto_approve { "on" } else { "off" };
347+
self.messages.push(
348+
Style::new()
349+
.fg(Color::Yellow)
350+
.render(&format!(" ⚡ auto-approve: {state}")),
351+
);
352+
self.textarea.clear();
353+
self.rebuild_viewport();
354+
return None;
355+
}
335356
_ => {}
336357
}
337358

@@ -421,6 +442,21 @@ impl App {
421442
args,
422443
..
423444
} => {
445+
if self.auto_approve {
446+
self.push_line(
447+
&Style::new()
448+
.fg(Color::BrightBlack)
449+
.render(&format!(" ⚡ auto-approved {tool_name}")),
450+
);
451+
let session = self.session.clone();
452+
return Some(cmd::batch(vec![
453+
cmd::cmd(move || async move {
454+
let _ = session.confirm_tool_use(&tool_id, true, None).await;
455+
Msg::Resume
456+
}),
457+
spinner_tick(),
458+
]));
459+
}
424460
self.state = State::Awaiting;
425461
self.pending_tool = Some((tool_id, tool_name.clone()));
426462
let pretty =
@@ -802,6 +838,8 @@ async fn main() -> anyhow::Result<()> {
802838
model: None,
803839
total_tokens: 0,
804840
tool_args: String::new(),
841+
auto_approve: false,
842+
cwd: workspace,
805843
width,
806844
height,
807845
keymap,

0 commit comments

Comments
 (0)