@@ -76,11 +76,11 @@ github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL
 github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0=
 github.com/charmbracelet/fang v0.1.0 h1:SlZS2crf3/zQh7Mr4+W+7QR1k+L08rrPX5rm5z3d7Wg=
 github.com/charmbracelet/fang v0.1.0/go.mod h1:Zl/zeUQ8EtQuGyiV0ZKZlZPDowKRTzu8s/367EpN/fc=
-github.com/charmbracelet/glamour/v2 v2.0.0-20250516160903-6f1e2c8f9ebe h1:i6ce4CcAlPpTj2ER69m1DBeLZ3RRcHnKExuwhKa3GfY=
+github.com/charmbracelet/glamour/v2 v2.0.0-20250516160903-6f1e2c8f9ebe h1:04xT769flyN8f2oXy0C2ol0aXVJKlbQYQ/fJNgrsF58=
 github.com/charmbracelet/glamour/v2 v2.0.0-20250516160903-6f1e2c8f9ebe/go.mod h1:p3Q+aN4eQKeM5jhrmXPMgPrlKbmc59rWSnMsSA3udhk=
 github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1.0.20250523195325-2d1af06b557c h1:177KMz8zHRlEZJsWzafbKYh6OdjgvTspoH+UjaxgIXY=
 github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1.0.20250523195325-2d1af06b557c/go.mod h1:EJWvaCrhOhNGVZMvcjc0yVryl4qqpMs8tz0r9WyEkdQ=
-github.com/charmbracelet/x/ansi v0.9.3-0.20250602153603-fb931ed90413 h1:L07QkDqRF274IZ2UJ/mCTL8DR95efU9BNWLYCDXEjvQ=
+github.com/charmbracelet/x/ansi v0.9.3-0.20250602153603-fb931ed90413 h1:uwKExR2sAgLtFdP28sPca/kgiZNcQG6+7voM5pjedT0=
 github.com/charmbracelet/x/ansi v0.9.3-0.20250602153603-fb931ed90413/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
 github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa h1:lphz0Z3rsiOtMYiz8axkT24i9yFiueDhJbzyNUADmME=
 github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa/go.mod h1:xBlh2Yi3DL3zy/2n15kITpg0YZardf/aa/hgUaIM6Rk=
@@ -116,6 +116,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
 github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
 github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/gammazero/deque v1.0.0 h1:LTmimT8H7bXkkCy6gZX7zNLtkbz4NdS2z8LZuor3j34=
+github.com/gammazero/deque v1.0.0/go.mod h1:iflpYvtGfM3U8S8j+sZEKIak3SAKYpA5/SQewgfXDKo=
 github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
 github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
  
  
  
    
    @@ -15,6 +15,7 @@ import (
 	"github.com/charmbracelet/crush/internal/tui/styles"
 	"github.com/charmbracelet/crush/internal/tui/util"
 	"github.com/charmbracelet/lipgloss/v2"
+	"github.com/gammazero/deque"
 	"github.com/sahilm/fuzzy"
 )
 
@@ -126,15 +127,15 @@ func (ss *selectionState) isValidIndex(itemCount int) bool {
 // model is the main implementation of the ListModel interface.
 // It coordinates between view state, render state, and selection state.
 type model struct {
-	viewState      viewState      // Display and scrolling state
-	renderState    *renderState   // Rendering cache and state
-	selectionState selectionState // Item selection state
-	help           help.Model     // Help system for keyboard shortcuts
-	keyMap         KeyMap         // Key bindings for navigation
-	allItems       []util.Model   // The actual list items
-	gapSize        int            // Number of empty lines between items
-	padding        []int          // Padding around the list content
-	wrapNavigation bool           // Whether to wrap navigation at the ends
+	viewState      viewState                // Display and scrolling state
+	renderState    *renderState             // Rendering cache and state
+	selectionState selectionState           // Item selection state
+	help           help.Model               // Help system for keyboard shortcuts
+	keyMap         KeyMap                   // Key bindings for navigation
+	allItems       *deque.Deque[util.Model] // Item list using deque for efficient prepend/append
+	gapSize        int                      // Number of empty lines between items
+	padding        []int                    // Padding around the list content
+	wrapNavigation bool                     // Whether to wrap navigation at the ends
 
 	filterable        bool            // Whether items can be filtered
 	filterPlaceholder string          // Placeholder text for filter input
@@ -183,7 +184,10 @@ func WithPadding(padding ...int) listOptions {
 // WithItems sets the initial items for the list.
 func WithItems(items []util.Model) listOptions {
 	return func(m *model) {
-		m.allItems = items
+		m.allItems.Clear()
+		for _, item := range items {
+			m.allItems.PushBack(item)
+		}
 		m.filteredItems = items // Initially, all items are visible
 	}
 }
@@ -232,7 +236,7 @@ func New(opts ...listOptions) ListModel {
 	m := &model{
 		help:              help.New(),
 		keyMap:            DefaultKeyMap(),
-		allItems:          []util.Model{},
+		allItems:          &deque.Deque[util.Model]{},
 		filteredItems:     []util.Model{},
 		renderState:       newRenderState(),
 		gapSize:           DefaultGapSize,
@@ -258,6 +262,18 @@ func New(opts ...listOptions) ListModel {
 	return m
 }
 
+// allItemsSlice converts the deque to a slice for compatibility with existing code.
+func (m *model) allItemsSlice() []util.Model {
+	if m.allItems.Len() == 0 {
+		return nil
+	}
+	result := make([]util.Model, m.allItems.Len())
+	for i := 0; i < m.allItems.Len(); i++ {
+		result[i] = m.allItems.At(i)
+	}
+	return result
+}
+
 // Init initializes the list component and sets up the initial items.
 // This is called automatically by the Bubble Tea framework.
 func (m *model) Init() tea.Cmd {
@@ -1052,8 +1068,8 @@ func (m *model) AppendItem(item util.Model) tea.Cmd {
 	cmds := []tea.Cmd{
 		item.Init(),
 	}
-	m.allItems = append(m.allItems, item)
-	m.filteredItems = m.allItems
+	m.allItems.PushBack(item)
+	m.filteredItems = m.allItemsSlice()
 	cmds = append(cmds, m.setItemSize(len(m.filteredItems)-1))
 	cmds = append(cmds, m.goToBottom())
 	m.renderState.needsRerender = true
@@ -1063,12 +1079,12 @@ func (m *model) AppendItem(item util.Model) tea.Cmd {
 // DeleteItem removes an item at the specified index.
 // Adjusts selection if necessary and triggers a complete re-render.
 func (m *model) DeleteItem(i int) {
-	if i < 0 || i >= len(m.filteredItems) {
+	if i < 0 || i >= m.allItems.Len() {
 		return
 	}
-	m.allItems = slices.Delete(m.allItems, i, i+1)
+	m.allItems.Remove(i)
 	delete(m.renderState.items, i)
-	m.filteredItems = m.allItems
+	m.filteredItems = m.allItemsSlice()
 
 	if m.selectionState.selectedIndex == i && m.selectionState.selectedIndex > 0 {
 		m.selectionState.selectedIndex--
@@ -1084,8 +1100,8 @@ func (m *model) DeleteItem(i int) {
 // Adjusts cached positions and selection index, then switches to forward mode.
 func (m *model) PrependItem(item util.Model) tea.Cmd {
 	cmds := []tea.Cmd{item.Init()}
-	m.allItems = append([]util.Model{item}, m.allItems...)
-	m.filteredItems = m.allItems
+	m.allItems.PushFront(item)
+	m.filteredItems = m.allItemsSlice()
 
 	// Shift all cached item indices by 1
 	newItems := make(map[int]renderedItem, len(m.renderState.items))
@@ -1117,7 +1133,10 @@ func (m *model) setReverse(reverse bool) {
 // Initializes all items, sets their sizes, and establishes initial selection.
 // Ensures the initial selection skips section headers.
 func (m *model) SetItems(items []util.Model) tea.Cmd {
-	m.allItems = items
+	m.allItems.Clear()
+	for _, item := range items {
+		m.allItems.PushBack(item)
+	}
 	m.filteredItems = items
 	cmds := []tea.Cmd{m.setAllItemsSize()}
 
@@ -1153,7 +1172,8 @@ func (m *model) parseSections() []section {
 	var sections []section
 	var currentSection *section
 
-	for _, item := range m.allItems {
+	for i := 0; i < m.allItems.Len(); i++ {
+		item := m.allItems.At(i)
 		if header, ok := item.(SectionHeader); ok && header.IsSectionHeader() {
 			// Start a new section
 			if currentSection != nil {
@@ -1208,17 +1228,18 @@ func (m *model) Filter(search string) tea.Cmd {
 	search = strings.ToLower(search)
 
 	// Clear focus and match indexes from all items
-	for _, item := range m.allItems {
-		if i, ok := item.(layout.Focusable); ok {
-			cmds = append(cmds, i.Blur())
+	for i := 0; i < m.allItems.Len(); i++ {
+		item := m.allItems.At(i)
+		if focusable, ok := item.(layout.Focusable); ok {
+			cmds = append(cmds, focusable.Blur())
 		}
-		if i, ok := item.(HasMatchIndexes); ok {
-			i.MatchIndexes(make([]int, 0))
+		if hasMatch, ok := item.(HasMatchIndexes); ok {
+			hasMatch.MatchIndexes(make([]int, 0))
 		}
 	}
 
 	if search == "" {
-		cmds = append(cmds, m.SetItems(m.allItems))
+		cmds = append(cmds, m.SetItems(m.allItemsSlice()))
 		return tea.Batch(cmds...)
 	}