@@ -175,8 +175,7 @@ impl App {
175175 state : AppState :: Idle ,
176176 input : InputBox :: new ( ) ,
177177 spinner : Spinner :: new ( ) ,
178- content_buffer : "Welcome! Type a message to start, or /help for commands.\n \n "
179- . to_string ( ) ,
178+ content_buffer : String :: new ( ) ,
180179 model_name : model_name. into ( ) ,
181180 permission_dialog : None ,
182181 should_quit : false ,
@@ -584,6 +583,10 @@ impl App {
584583 use crab_core:: event:: Event ;
585584 match event {
586585 Event :: ContentDelta { delta, .. } => {
586+ // Add β marker at the start of assistant response (CC style)
587+ if self . state == AppState :: Processing && !self . content_buffer . ends_with ( "β " ) {
588+ self . content_buffer . push_str ( "β " ) ;
589+ }
587590 // Track unseen content when the user is scrolled up
588591 if self . scroll_anchor . is_some ( ) {
589592 // Count newlines in the delta as new "messages"
@@ -796,7 +799,13 @@ impl App {
796799 }
797800
798801 // Bottom bar
799- render_bottom_bar ( self . state , self . search . is_active ( ) , layout. bottom_bar , buf) ;
802+ render_bottom_bar (
803+ self . state ,
804+ self . search . is_active ( ) ,
805+ self . permission_mode ,
806+ layout. bottom_bar ,
807+ buf,
808+ ) ;
800809
801810 // Autocomplete popup (renders above input)
802811 if self . autocomplete . is_active ( ) {
@@ -1308,7 +1317,13 @@ fn format_token_count(tokens: u64) -> String {
13081317 }
13091318}
13101319
1311- fn render_bottom_bar ( state : AppState , search_active : bool , area : Rect , buf : & mut Buffer ) {
1320+ fn render_bottom_bar (
1321+ state : AppState ,
1322+ search_active : bool ,
1323+ perm_mode : crab_core:: permission:: PermissionMode ,
1324+ area : Rect ,
1325+ buf : & mut Buffer ,
1326+ ) {
13121327 let line = if search_active {
13131328 Line :: from ( Span :: styled (
13141329 "Enter: next match | Esc: close | type to search" ,
@@ -1320,10 +1335,35 @@ fn render_bottom_bar(state: AppState, search_active: bool, area: Rect, buf: &mut
13201335 "y: allow | n: deny | a: always | Esc: deny" ,
13211336 Style :: default ( ) . fg ( Color :: DarkGray ) ,
13221337 ) ) ,
1323- _ => Line :: from ( Span :: styled (
1324- "? for shortcuts" ,
1325- Style :: default ( ) . fg ( Color :: DarkGray ) ,
1326- ) ) ,
1338+ AppState :: Processing => {
1339+ // CC shows: "βΆβΆ accept edits on (shift+tab to cycle) Β· esc to interrupt"
1340+ Line :: from ( vec ! [
1341+ Span :: styled( " βΆβΆ " , Style :: default ( ) . fg( Color :: DarkGray ) ) ,
1342+ Span :: styled( perm_mode. to_string( ) , Style :: default ( ) . fg( Color :: DarkGray ) ) ,
1343+ Span :: styled(
1344+ " (shift+tab to cycle) Β· esc to interrupt" ,
1345+ Style :: default ( ) . fg( Color :: DarkGray ) ,
1346+ ) ,
1347+ ] )
1348+ }
1349+ _ => {
1350+ // CC shows: "βΆβΆ accept edits on (shift+tab to cycle)" or "? for shortcuts"
1351+ if perm_mode == crab_core:: permission:: PermissionMode :: Default {
1352+ Line :: from ( Span :: styled (
1353+ " ? for shortcuts" ,
1354+ Style :: default ( ) . fg ( Color :: DarkGray ) ,
1355+ ) )
1356+ } else {
1357+ Line :: from ( vec ! [
1358+ Span :: styled( " βΆβΆ " , Style :: default ( ) . fg( Color :: DarkGray ) ) ,
1359+ Span :: styled( perm_mode. to_string( ) , Style :: default ( ) . fg( Color :: DarkGray ) ) ,
1360+ Span :: styled(
1361+ " (shift+tab to cycle)" ,
1362+ Style :: default ( ) . fg( Color :: DarkGray ) ,
1363+ ) ,
1364+ ] )
1365+ }
1366+ }
13271367 }
13281368 } ;
13291369 Widget :: render ( line, area, buf) ;
@@ -1348,7 +1388,7 @@ mod tests {
13481388 assert_eq ! ( app. state, AppState :: Idle ) ;
13491389 assert ! ( app. input. is_empty( ) ) ;
13501390 assert ! ( !app. spinner. is_active( ) ) ;
1351- assert ! ( app. content_buffer. contains ( "Welcome" ) ) ;
1391+ assert ! ( app. content_buffer. is_empty ( ) ) ;
13521392 assert_eq ! ( app. model_name, "gpt-4o" ) ;
13531393 assert ! ( !app. should_quit) ;
13541394 assert ! ( !app. sidebar_visible) ;
0 commit comments