@@ -163,6 +163,8 @@ pub struct App {
163163 pub input_mode : PromptInputMode ,
164164 /// Timestamp of last Ctrl+C press for double-press detection.
165165 last_interrupt : Option < Instant > ,
166+ /// Current permission mode (cycled via Shift+Tab).
167+ pub permission_mode : crab_core:: permission:: PermissionMode ,
166168}
167169
168170impl App {
@@ -199,6 +201,7 @@ impl App {
199201 unseen_message_count : 0 ,
200202 input_mode : PromptInputMode :: Prompt ,
201203 last_interrupt : None ,
204+ permission_mode : crab_core:: permission:: PermissionMode :: Default ,
202205 }
203206 }
204207
@@ -362,9 +365,19 @@ impl App {
362365 self . scroll_to_search_match ( ) ;
363366 return AppAction :: None ;
364367 }
365- // CycleMode: CC cycles permission modes. Needs agent integration.
368+ Action :: CycleMode if self . state != AppState :: Confirming => {
369+ // CC cycles: default β acceptEdits β plan β default
370+ use crab_core:: permission:: PermissionMode ;
371+ self . permission_mode = match self . permission_mode {
372+ PermissionMode :: Default => PermissionMode :: AcceptEdits ,
373+ PermissionMode :: AcceptEdits => PermissionMode :: Plan ,
374+ // All other modes cycle back to Default
375+ _ => PermissionMode :: Default ,
376+ } ;
377+ return AppAction :: None ;
378+ }
366379 // Redraw: handled by outer loop on next frame.
367- Action :: CycleMode | Action :: Redraw => {
380+ Action :: Redraw => {
368381 return AppAction :: None ;
369382 }
370383 // These actions are recognized but currently act as no-ops
@@ -492,9 +505,8 @@ impl App {
492505 if key. code == KeyCode :: Enter && !key. modifiers . contains ( KeyModifiers :: SHIFT ) {
493506 if !self . input . is_empty ( ) {
494507 let text = self . input . submit ( ) ;
495- // Turn separator: show user prompt then divider
496- let _ = writeln ! ( self . content_buffer, "β― {text}" ) ;
497- let _ = writeln ! ( self . content_buffer, "ββββββββββββββββββββββββββββββββ" ) ;
508+ // Show user prompt in content area (no divider β CC doesn't have one)
509+ let _ = writeln ! ( self . content_buffer, "\n β― {text}\n " ) ;
498510 self . state = AppState :: Processing ;
499511 self . spinner . start_with_random_verb ( ) ;
500512 return AppAction :: Submit ( text) ;
@@ -737,6 +749,7 @@ impl App {
737749 } else {
738750 render_status_line (
739751 & self . model_name ,
752+ self . permission_mode ,
740753 self . total_input_tokens ,
741754 self . total_output_tokens ,
742755 & self . thinking ,
@@ -1230,6 +1243,7 @@ fn classify_tool_risk(tool_name: &str) -> RiskLevel {
12301243/// Matches CC's `StatusLine` component showing operational data.
12311244fn render_status_line (
12321245 model : & str ,
1246+ perm_mode : crab_core:: permission:: PermissionMode ,
12331247 input_tokens : u64 ,
12341248 output_tokens : u64 ,
12351249 thinking : & ThinkingState ,
@@ -1243,6 +1257,8 @@ fn render_status_line(
12431257 let mut spans = vec ! [
12441258 Span :: styled( model, Style :: default ( ) . fg( Color :: Cyan ) ) ,
12451259 Span :: styled( " β " , Style :: default ( ) . fg( Color :: DarkGray ) ) ,
1260+ Span :: styled( perm_mode. to_string( ) , Style :: default ( ) . fg( Color :: Yellow ) ) ,
1261+ Span :: styled( " β " , Style :: default ( ) . fg( Color :: DarkGray ) ) ,
12461262 ] ;
12471263
12481264 // Token counts
0 commit comments