@@ -830,11 +830,14 @@ func (m *UI) loadNestedToolCalls(items []chat.MessageItem) {
830830// if the message is a tool result it will update the corresponding tool call message
831831func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd {
832832 var cmds []tea.Cmd
833+ atBottom := m.chat.list.AtBottom()
834+
833835 existing := m.chat.MessageItem(msg.ID)
834836 if existing != nil {
835837 // message already exists, skip
836838 return nil
837839 }
840+
838841 switch msg.Role {
839842 case message.User:
840843 m.lastUserMessageTime = msg.CreatedAt
@@ -860,14 +863,18 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd {
860863 }
861864 }
862865 m.chat.AppendMessages(items...)
863− if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
864− cmds = append(cmds, cmd)
866+ if atBottom {
867+ if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
868+ cmds = append(cmds, cmd)
869+ }
865870 }
866871 if msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
867872 infoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, time.Unix(m.lastUserMessageTime, 0))
868873 m.chat.AppendMessages(infoItem)
869− if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
870− cmds = append(cmds, cmd)
874+ if atBottom {
875+ if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
876+ cmds = append(cmds, cmd)
877+ }
871878 }
872879 }
873880 case message.Tool:
@@ -879,6 +886,11 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd {
879886 }
880887 if toolMsgItem, ok := toolItem.(chat.ToolMessageItem); ok {
881888 toolMsgItem.SetResult(&tr)
889+ if atBottom {
890+ if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
891+ cmds = append(cmds, cmd)
892+ }
893+ }
882894 }
883895 }
884896 }