@@ -1417,10 +1417,16 @@ func (m *appModel) Bindings() []key.Binding {
14171417 bindings = append (bindings , m .chatPage .Bindings ()... )
14181418 } else {
14191419 editorName := getEditorDisplayNameFromEnv (os .Getenv ("VISUAL" ), os .Getenv ("EDITOR" ))
1420- bindings = append (bindings , key .NewBinding (
1421- key .WithKeys ("ctrl+g" ),
1422- key .WithHelp ("Ctrl+g" , fmt .Sprintf ("edit in %s" , editorName )),
1423- ))
1420+ bindings = append (bindings ,
1421+ key .NewBinding (
1422+ key .WithKeys ("ctrl+g" ),
1423+ key .WithHelp ("Ctrl+g" , fmt .Sprintf ("edit in %s" , editorName )),
1424+ ),
1425+ key .NewBinding (
1426+ key .WithKeys ("ctrl+r" ),
1427+ key .WithHelp ("Ctrl+r" , "history search" ),
1428+ ),
1429+ )
14241430 }
14251431 return bindings
14261432}
@@ -1434,9 +1440,12 @@ func (m *appModel) handleKeyPress(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
14341440 return m , cmd
14351441 }
14361442
1437- // Tab bar keys (Ctrl+t, Ctrl+p, Ctrl+n, Ctrl+w)
1438- if cmd := m .tabBar .Update (msg ); cmd != nil {
1439- return m , cmd
1443+ // Tab bar keys (Ctrl+t, Ctrl+p, Ctrl+n, Ctrl+w) are suppressed during
1444+ // history search so that ctrl+n/ctrl+p cycle through matches instead.
1445+ if ! m .editor .IsHistorySearchActive () {
1446+ if cmd := m .tabBar .Update (msg ); cmd != nil {
1447+ return m , cmd
1448+ }
14401449 }
14411450
14421451 // Completion popup gets priority when open
@@ -1458,7 +1467,7 @@ func (m *appModel) handleKeyPress(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
14581467 return m , tea .Batch (cmds ... )
14591468 }
14601469
1461- // Global keyboard shortcuts
1470+ // Global keyboard shortcuts (active even during history search)
14621471 switch {
14631472 case key .Matches (msg , key .NewBinding (key .WithKeys ("ctrl+c" ))):
14641473 return m , core .CmdHandler (dialog.OpenDialogMsg {
@@ -1488,10 +1497,26 @@ func (m *appModel) handleKeyPress(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
14881497
14891498 case key .Matches (msg , key .NewBinding (key .WithKeys ("ctrl+x" ))):
14901499 return m , core .CmdHandler (messages.ClearQueueMsg {})
1500+ }
1501+
1502+ // History search is a modal state — capture all remaining keys before normal routing
1503+ if m .focusedPanel == PanelEditor && m .editor .IsHistorySearchActive () {
1504+ editorModel , cmd := m .editor .Update (msg )
1505+ m .editor = editorModel .(editor.Editor )
1506+ return m , cmd
1507+ }
14911508
1509+ switch {
14921510 case key .Matches (msg , key .NewBinding (key .WithKeys ("ctrl+g" ))):
14931511 return m .openExternalEditor ()
14941512
1513+ case key .Matches (msg , key .NewBinding (key .WithKeys ("ctrl+r" ))):
1514+ if m .focusedPanel == PanelEditor && ! m .editor .IsRecording () {
1515+ model , cmd := m .editor .EnterHistorySearch ()
1516+ m .editor = model .(editor.Editor )
1517+ return m , cmd
1518+ }
1519+
14951520 // Toggle sidebar (propagates to content view regardless of focus)
14961521 case key .Matches (msg , key .NewBinding (key .WithKeys ("ctrl+b" ))):
14971522 updated , cmd := m .chatPage .Update (msg )
0 commit comments