diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_format_list_numbered_24dp.xml b/composeApp/src/commonMain/composeResources/drawable/ic_format_list_numbered_24dp.xml
new file mode 100644
index 0000000..202a65d
--- /dev/null
+++ b/composeApp/src/commonMain/composeResources/drawable/ic_format_list_numbered_24dp.xml
@@ -0,0 +1,9 @@
+
+  
+
diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index 82b5f9c..780f8ed 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -207,6 +207,8 @@
     Délai après lequel le chat disparaît
     Défilement automatique
     Défilement automatique du chat vers le dernier message reçu lors de la réception de ce dernier.
+    Nombre de lignes de textes visibles
+    Limite le nombre maximale de messages affichés par le chat.
 
     Montée de niveau
     Level Up !
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt
index 3d29f4f..8d90f6f 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt
@@ -28,8 +28,8 @@ class DataSyncViewModel(
         if (settings.playerName.isEmpty()) return
 
         networkRepository.connect(
-            host = settings.host,
-            port = settings.port,
+            host = settings.network.host,
+            port = settings.network.port,
         )
     }
 
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt
index b1b2c69..5bf3676 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt
@@ -19,7 +19,7 @@ class LwaClientImpl(
     private val client: HttpClient,
     setting: SettingsRepository,
 ) : LwaClient {
-    private val root = setting.settings().root
+    private val root = setting.settings().network.root
 
     override suspend fun characters(): List = client
         .get("$root/characters")
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/SettingsFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/SettingsFactory.kt
index 73f4168..9852842 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/SettingsFactory.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/SettingsFactory.kt
@@ -13,14 +13,15 @@ class SettingsFactory(
         settings: Settings,
     ): SettingsJson {
         return SettingsJsonV1(
-            host = settings.host,
-            port = settings.port,
+            host = settings.network.host,
+            port = settings.network.port,
             playerName = settings.playerName,
-            dynamicDice = settings.dynamicDice,
-            autoHideChat = settings.autoHideChat,
-            autoHideDelay = settings.autoHideDelay,
-            autoShowChat = settings.autoShowChat,
-            autoScrollChat = settings.autoScrollChat,
+            dynamicDice = settings.portrait.dynamicDice,
+            autoHideChat = settings.chat.autoHideChat,
+            autoHideDelay = settings.chat.autoHideDelay,
+            autoShowChat = settings.chat.autoShowChat,
+            autoScrollChat = settings.chat.autoScrollChat,
+            maxLineCount = settings.chat.maxLineCount,
             isAdmin = settings.isAdmin,
             isGameMaster = settings.isGameMaster,
         )
@@ -39,14 +40,21 @@ class SettingsFactory(
     ): Settings {
         val default = useCase.defaultSettings()
         return Settings(
-            host = json.host ?: default.host,
-            port = json.port ?: default.port,
             playerName = json.playerName ?: default.playerName,
-            dynamicDice = json.dynamicDice ?: default.dynamicDice,
-            autoHideChat = json.autoHideChat ?: default.autoHideChat,
-            autoHideDelay = json.autoHideDelay ?: default.autoHideDelay,
-            autoShowChat = json.autoShowChat ?: default.autoShowChat,
-            autoScrollChat = json.autoScrollChat ?: default.autoScrollChat,
+            network = Settings.Network(
+                host = json.host ?: default.network.host,
+                port = json.port ?: default.network.port,
+            ),
+            portrait = Settings.Portrait(
+                dynamicDice = json.dynamicDice ?: default.portrait.dynamicDice,
+            ),
+            chat = Settings.Chat(
+                autoHideChat = json.autoHideChat ?: default.chat.autoHideChat,
+                autoHideDelay = json.autoHideDelay ?: default.chat.autoHideDelay,
+                autoShowChat = json.autoShowChat ?: default.chat.autoShowChat,
+                autoScrollChat = json.autoScrollChat ?: default.chat.autoScrollChat,
+                maxLineCount = json.maxLineCount ?: default.chat.maxLineCount,
+            ),
             isAdmin = json.isAdmin ?: default.isAdmin,
             isGameMaster = json.isGameMaster ?: default.isGameMaster,
         )
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/Settings.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/Settings.kt
index 61e2d38..4dcec1d 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/Settings.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/Settings.kt
@@ -1,16 +1,29 @@
 package com.pixelized.desktop.lwa.repository.settings.model
 
 data class Settings(
-    val host: String,
-    val port: Int,
     val playerName: String,
-    val dynamicDice: Boolean,
-    val autoHideChat: Boolean,
-    val autoHideDelay: Int,
-    val autoShowChat: Boolean,
-    val autoScrollChat: Boolean,
+    val portrait: Portrait,
+    val chat: Chat,
+    val network: Network,
     val isAdmin: Boolean? = null,
     val isGameMaster: Boolean? = null,
 ) {
-    val root: String get() = "http://${"${host}:${port}".removePrefix("http://")}"
+    data class Portrait(
+        val dynamicDice: Boolean,
+    )
+
+    data class Chat(
+        val autoHideChat: Boolean,
+        val autoHideDelay: Int,
+        val autoShowChat: Boolean,
+        val autoScrollChat: Boolean,
+        val maxLineCount: Int,
+    )
+
+    data class Network(
+        val host: String,
+        val port: Int,
+    ) {
+        val root: String get() = "http://${"${host}:${port}".removePrefix("http://")}"
+    }
 }
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV1.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV1.kt
index 91a2a67..386314f 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV1.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV1.kt
@@ -12,6 +12,7 @@ data class SettingsJsonV1(
     val autoHideDelay: Int?,
     val autoShowChat: Boolean?,
     val autoScrollChat: Boolean?,
+    val maxLineCount: Int?,
     val isGameMaster: Boolean?,
     val isAdmin: Boolean?,
 ) : SettingsJson
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/network/NetworkViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/network/NetworkViewModel.kt
index fa64620..0ff50ae 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/network/NetworkViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/network/NetworkViewModel.kt
@@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
 import com.pixelized.desktop.lwa.repository.network.NetworkRepository
 import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
+import com.pixelized.desktop.lwa.repository.settings.model.Settings
 import com.pixelized.desktop.lwa.ui.composable.blur.BlurContentController
 import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackUio
 import kotlinx.coroutines.CancellationException
@@ -32,8 +33,8 @@ class NetworkViewModel(
 ) : ViewModel() {
     private val settings = settingsRepository.settings()
     private val nameFlow = MutableStateFlow(settings.playerName)
-    private val hostFlow = MutableStateFlow(settings.host)
-    private val portFlow = MutableStateFlow(settings.port)
+    private val hostFlow = MutableStateFlow(settings.network.host)
+    private val portFlow = MutableStateFlow(settings.network.port)
 
     private val _networkError = MutableSharedFlow()
     val networkError: SharedFlow get() = _networkError
@@ -57,9 +58,9 @@ class NetworkViewModel(
             player = name,
             status = status,
             host = host,
-            resetHost = settings.host != host,
+            resetHost = settings.network.host != host,
             port = port,
-            resetPort = settings.port != port,
+            resetPort = settings.network.port != port,
         )
     }.stateIn(
         scope = viewModelScope,
@@ -71,8 +72,8 @@ class NetworkViewModel(
         settingsRepository.settingsFlow()
             .onEach {
                 nameFlow.value = it.playerName
-                hostFlow.value = it.host
-                portFlow.value = it.port
+                hostFlow.value = it.network.host
+                portFlow.value = it.network.port
             }
             .launchIn(viewModelScope)
     }
@@ -86,7 +87,7 @@ class NetworkViewModel(
     }
 
     fun onResetPortChange() {
-        portFlow.value = settings.port
+        portFlow.value = settings.network.port
     }
 
     fun onHostChange(host: String) {
@@ -94,7 +95,7 @@ class NetworkViewModel(
     }
 
     fun onResetHostChange() {
-        hostFlow.value = settings.host
+        hostFlow.value = settings.network.host
     }
 
     suspend fun connect() {
@@ -103,14 +104,16 @@ class NetworkViewModel(
 
         if (
             settings.playerName != nameFlow.value ||
-            settings.host != hostFlow.value ||
-            settings.port != portFlow.value
+            settings.network.host != hostFlow.value ||
+            settings.network.port != portFlow.value
         ) {
             settingsRepository.update(
                 settings = settings.copy(
                     playerName = nameFlow.value,
-                    host = hostFlow.value,
-                    port = portFlow.value
+                    network = Settings.Network(
+                        host = hostFlow.value,
+                        port = portFlow.value,
+                    ),
                 )
             )
         }
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt
index 3cff5b6..8f84f32 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt
@@ -117,7 +117,7 @@ abstract class CharacterRibbonViewModel(
                 settingsRepository.settingsFlow(),
                 rollHistoryRepository.rolls,
             ) { settings, roll ->
-                if (settings.dynamicDice &&
+                if (settings.portrait.dynamicDice &&
                     characterId.equals(roll.prefix, roll.characterSheetId, roll.instanceId)
                 ) {
                     state.value = CharacterPortraitRollUio(
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChat.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChat.kt
index 2c4b8eb..5be2552 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChat.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChat.kt
@@ -32,7 +32,6 @@ import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.max
 import androidx.compose.ui.unit.min
 import androidx.compose.ui.window.WindowState
-import com.pixelized.desktop.lwa.repository.settings.model.Settings
 import com.pixelized.desktop.lwa.ui.navigation.window.LocalWindowState
 import com.pixelized.desktop.lwa.ui.screen.campaign.CampaignLayoutScope
 import com.pixelized.desktop.lwa.ui.screen.campaign.LocalCampaignLayoutScope
@@ -45,9 +44,27 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessag
 import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessageUio
 import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.TextMessage
 import com.pixelized.desktop.lwa.ui.theme.lwa
+import com.pixelized.desktop.lwa.usecase.SettingsUseCase
 import kotlinx.coroutines.launch
 import org.koin.compose.viewmodel.koinViewModel
 
+@Stable
+data class ChatSettingsUio(
+    val autoShowChat: Boolean,
+    val autoScrollChat: Boolean,
+    val autoHideChat: Boolean,
+) {
+    companion object {
+        fun default() = with(SettingsUseCase().defaultSettings()) {
+            ChatSettingsUio(
+                autoShowChat = chat.autoShowChat,
+                autoScrollChat = chat.autoScrollChat,
+                autoHideChat = chat.autoHideChat,
+            )
+        }
+    }
+}
+
 @OptIn(ExperimentalComposeUiApi::class)
 @Composable
 fun CampaignChat(
@@ -119,7 +136,7 @@ fun CampaignChat(
 private fun ChatScrollDownEffect(
     lazyState: LazyListState,
     messages: State>,
-    settings: State,
+    settings: State,
     displayChat: suspend () -> Unit,
     hideChat: suspend () -> Unit,
 ) {
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChatViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChatViewModel.kt
index 1a9978b..8283293 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChatViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChatViewModel.kt
@@ -6,40 +6,54 @@ import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
 import com.pixelized.desktop.lwa.repository.network.NetworkRepository
 import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
-import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.TextMessage
+import com.pixelized.shared.lwa.protocol.websocket.SocketMessage
 import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.runningFold
 import kotlinx.coroutines.flow.stateIn
 
 
 class CampaignChatViewModel(
+    private val settingsRepository: SettingsRepository,
     networkRepository: NetworkRepository,
     textMessageFactory: TextMessageFactory,
-    settingsRepository: SettingsRepository,
 ) : ViewModel() {
 
-    val settings = settingsRepository.settingsFlow()
-
     val chatAnimatedVisibility = Animatable(0f)
 
-    private var _messages = emptyList()
-    val messages: StateFlow> = networkRepository.data
-        .mapNotNull { message ->
-            val text = textMessageFactory
-                .convertToTextMessage(message = message)
-                ?: return@mapNotNull _messages
-
-            _messages = _messages.toMutableList().also {
-                it.add(index = it.lastIndex + 1, element = text)
-            }
-            _messages
-        }
-        .stateIn(
-            scope = viewModelScope,
-            started = SharingStarted.Eagerly,
-            initialValue = _messages,
+    val settings = settingsRepository.settingsFlow().map {
+        ChatSettingsUio(
+            autoShowChat = it.chat.autoShowChat,
+            autoScrollChat = it.chat.autoScrollChat,
+            autoHideChat = it.chat.autoHideChat,
         )
+    }.stateIn(
+        scope = viewModelScope,
+        started = SharingStarted.Eagerly,
+        initialValue = ChatSettingsUio.default(),
+    )
+
+    val messages = combine(
+        settingsRepository.settingsFlow(),
+        networkRepository.data.runningFold(
+            initial = mutableListOf(),
+            operation = List::plus
+        )
+    ) { settings, messages ->
+        messages.mapNotNull { message ->
+            textMessageFactory.convertToTextMessage(
+                settings = settings,
+                message = message,
+            )
+        }.takeLast(
+            n = settings.chat.maxLineCount,
+        )
+    }.stateIn(
+        scope = viewModelScope,
+        started = SharingStarted.Eagerly,
+        initialValue = emptyList(),
+    )
 
     suspend fun displayChat() {
         chatAnimatedVisibility.animateTo(
@@ -48,11 +62,12 @@ class CampaignChatViewModel(
     }
 
     suspend fun hideChat() {
+        val settings = settingsRepository.settingsFlow().value
         chatAnimatedVisibility.animateTo(
             targetValue = 0f,
             animationSpec = tween(
                 durationMillis = 2000,
-                delayMillis = settings.value.autoHideDelay * 1000,
+                delayMillis = settings.chat.autoHideDelay * 1000,
             )
         )
     }
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt
index 3b6a121..b5e40a6 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt
@@ -1,12 +1,11 @@
 package com.pixelized.desktop.lwa.ui.screen.campaign.text
 
-import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
 import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
+import com.pixelized.desktop.lwa.repository.settings.model.Settings
 import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.CharacteristicTextMessageUio
 import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.DiminishedTextMessageUio
 import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessageUio
 import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.TextMessage
-import com.pixelized.shared.lwa.model.AlteredCharacterSheetFactory
 import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Damage
 import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Power
 import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage
@@ -26,13 +25,12 @@ import kotlin.math.abs
 
 class TextMessageFactory(
     private val characterSheetRepository: CharacterSheetRepository,
-    private val alterationRepository: AlterationRepository,
-    private val alteredCharacterSheetFactory: AlteredCharacterSheetFactory,
 ) {
     private val formatId = SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS")
     private val formatTime = SimpleDateFormat("HH:mm:ss")
 
     suspend fun convertToTextMessage(
+        settings: Settings,
         message: SocketMessage,
     ): TextMessage? {
         val time = message.timestamp
@@ -44,6 +42,8 @@ class TextMessageFactory(
                     .characterPreview(characterId = message.characterSheetId)
                     ?: return null
 
+                val isGm = settings.isGameMaster ?: false
+
                 RollTextMessageUio(
                     id = "${message.uuid}-${message.timestamp}",
                     timestamp = formatTime.format(time),
@@ -51,7 +51,7 @@ class TextMessageFactory(
                     skillLabel = message.skillLabel,
                     rollDifficulty = message.rollDifficulty,
                     rollValue = message.rollValue,
-                    rollSuccessLimit = message.rollSuccessLimit,
+                    rollSuccessLimit = takeIf { isGm }?.let { message.rollSuccessLimit },
                     resultLabel = message.resultLabel,
                     resultType = when (message.critical) {
                         RollMessage.Critical.CRITICAL_SUCCESS -> RollTextMessageUio.Critical.CRITICAL_SUCCESS
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/messages/RollTextMessage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/messages/RollTextMessage.kt
index 3d477cd..8287452 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/messages/RollTextMessage.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/messages/RollTextMessage.kt
@@ -8,7 +8,6 @@ import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Stable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
 import com.pixelized.desktop.lwa.ui.theme.lwa
@@ -72,7 +71,6 @@ fun RollTextMessage(
         Text(
             modifier = Modifier.alignByBaseline(),
             style = MaterialTheme.lwa.typography.chat.text,
-            fontWeight = FontWeight.ExtraLight,
             overflow = TextOverflow.Ellipsis,
             maxLines = 1,
             text = stringResource(Res.string.roll_history__item__throw),
@@ -114,7 +112,7 @@ fun RollTextMessage(
                 style = MaterialTheme.lwa.typography.chat.text,
                 overflow = TextOverflow.Ellipsis,
                 maxLines = 1,
-                text = "${message.rollValue}",
+                text = "(${message.rollValue}",
             )
             message.rollSuccessLimit?.let {
                 Text(
@@ -125,6 +123,13 @@ fun RollTextMessage(
                     text = "/$it",
                 )
             }
+            Text(
+                modifier = Modifier.alignByBaseline(),
+                style = MaterialTheme.lwa.typography.chat.text,
+                overflow = TextOverflow.Ellipsis,
+                maxLines = 1,
+                text = ")",
+            )
         }
         message.rollDifficulty?.let {
             Text(
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt
index d3f374f..bc72c57 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt
@@ -12,6 +12,7 @@ import com.pixelized.desktop.lwa.usecase.SettingsUseCase
 import kotlinx.coroutines.launch
 import lwacharactersheet.composeapp.generated.resources.Res
 import lwacharactersheet.composeapp.generated.resources.ic_fan_focus_24dp
+import lwacharactersheet.composeapp.generated.resources.ic_format_list_numbered_24dp
 import lwacharactersheet.composeapp.generated.resources.ic_ifl_24dp
 import lwacharactersheet.composeapp.generated.resources.ic_timer_24dp
 import lwacharactersheet.composeapp.generated.resources.ic_visibility_24dp
@@ -28,6 +29,8 @@ import lwacharactersheet.composeapp.generated.resources.settings__chat_log__sect
 import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_description
 import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_tile
 import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__section
+import lwacharactersheet.composeapp.generated.resources.settings__chat_log__line_count_title
+import lwacharactersheet.composeapp.generated.resources.settings__chat_log__line_count_description
 
 
 class SettingsViewModel(
@@ -48,7 +51,11 @@ class SettingsViewModel(
             description = Res.string.settings__player_portrait__dyn_dice_description,
             checked = booleanStates.dynamicDice,
             onToggle = {
-                settingsRepository.update(settings = settings.value.copy(dynamicDice = it))
+                settingsRepository.update(
+                    settings = settings.value.copy(
+                        portrait = settings.value.portrait.copy(dynamicDice = it)
+                    )
+                )
             },
         ),
         SettingSectionUio(
@@ -60,7 +67,11 @@ class SettingsViewModel(
             description = Res.string.settings__chat_log__auto_show_description,
             checked = booleanStates.autoShowChat,
             onToggle = {
-                settingsRepository.update(settings = settings.value.copy(autoShowChat = it))
+                settingsRepository.update(
+                    settings = settings.value.copy(
+                        chat = settings.value.chat.copy(autoShowChat = it)
+                    )
+                )
             },
         ),
         SettingToggleItemUio(
@@ -69,7 +80,11 @@ class SettingsViewModel(
             description = Res.string.settings__chat_log__auto_hide_description,
             checked = booleanStates.autoHideChat,
             onToggle = {
-                settingsRepository.update(settings = settings.value.copy(autoHideChat = it))
+                settingsRepository.update(
+                    settings = settings.value.copy(
+                        chat = settings.value.chat.copy(autoHideChat = it)
+                    )
+                )
             },
         ),
         SettingNumberItemUio(
@@ -80,7 +95,11 @@ class SettingsViewModel(
             value = intStates.autoHideDelay,
             onValueChange = {
                 if (it in 0..999) {
-                    settingsRepository.update(settings = settings.value.copy(autoHideDelay = it))
+                    settingsRepository.update(
+                        settings = settings.value.copy(
+                            chat = settings.value.chat.copy(autoHideDelay = it)
+                        )
+                    )
                 }
             }
         ),
@@ -90,19 +109,40 @@ class SettingsViewModel(
             description = Res.string.settings__chat_log__auto_scroll_description,
             checked = booleanStates.autoScrollChat,
             onToggle = {
-                settingsRepository.update(settings = settings.value.copy(autoScrollChat = it))
+                settingsRepository.update(
+                    settings = settings.value.copy(
+                        chat = settings.value.chat.copy(autoScrollChat = it)
+                    )
+                )
             },
         ),
+        SettingNumberItemUio(
+            icon = Res.drawable.ic_format_list_numbered_24dp,
+            title = Res.string.settings__chat_log__line_count_title,
+            description = Res.string.settings__chat_log__line_count_description,
+            enable = mutableStateOf(true),
+            value = intStates.maxLineCount,
+            onValueChange = {
+                if (it in 0..999) {
+                    settingsRepository.update(
+                        settings = settings.value.copy(
+                            chat = settings.value.chat.copy(maxLineCount = it)
+                        )
+                    )
+                }
+            }
+        ),
     )
 
     init {
         viewModelScope.launch {
             settingsRepository.settingsFlow().collect { settings ->
-                booleanStates.dynamicDice.value = settings.dynamicDice
-                booleanStates.autoShowChat.value = settings.autoShowChat
-                booleanStates.autoHideChat.value = settings.autoHideChat
-                intStates.autoHideDelay.value = settings.autoHideDelay
-                booleanStates.autoScrollChat.value = settings.autoScrollChat
+                booleanStates.dynamicDice.value = settings.portrait.dynamicDice
+                booleanStates.autoShowChat.value = settings.chat.autoShowChat
+                booleanStates.autoHideChat.value = settings.chat.autoHideChat
+                intStates.autoHideDelay.value = settings.chat.autoHideDelay
+                booleanStates.autoScrollChat.value = settings.chat.autoScrollChat
+                intStates.maxLineCount.value = settings.chat.maxLineCount
             }
         }
     }
@@ -120,17 +160,20 @@ class SettingsViewModel(
     }
 
     private val HashMap>.dynamicDice
-        get() = getOrPut("DYNAMIC_DICE") { mutableStateOf(settings.value.dynamicDice) }
+        get() = getOrPut("DYNAMIC_DICE") { mutableStateOf(settings.value.portrait.dynamicDice) }
 
     private val HashMap>.autoShowChat
-        get() = getOrPut("AUTO_SHOW_CHAT") { mutableStateOf(settings.value.autoShowChat) }
+        get() = getOrPut("AUTO_SHOW_CHAT") { mutableStateOf(settings.value.chat.autoShowChat) }
 
     private val HashMap>.autoHideChat
-        get() = getOrPut("AUTO_HIDE_CHAT") { mutableStateOf(settings.value.autoHideChat) }
+        get() = getOrPut("AUTO_HIDE_CHAT") { mutableStateOf(settings.value.chat.autoHideChat) }
 
     private val HashMap>.autoHideDelay
-        get() = getOrPut("AUTO_HIDE_DELAY") { mutableStateOf(settings.value.autoHideDelay) }
+        get() = getOrPut("AUTO_HIDE_DELAY") { mutableStateOf(settings.value.chat.autoHideDelay) }
 
     private val HashMap>.autoScrollChat
-        get() = getOrPut("AUTO_SCROLL_CHAT") { mutableStateOf(settings.value.autoScrollChat) }
+        get() = getOrPut("AUTO_SCROLL_CHAT") { mutableStateOf(settings.value.chat.autoScrollChat) }
+
+    private val HashMap>.maxLineCount
+        get() = getOrPut("MAX_LINE_COUNT") { mutableStateOf(settings.value.chat.maxLineCount) }
 }
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt
index 8cc524e..c1f1d63 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt
@@ -5,14 +5,21 @@ import com.pixelized.desktop.lwa.repository.settings.model.Settings
 class SettingsUseCase {
 
     fun defaultSettings(): Settings = Settings(
-        host = DEFAULT_HOST,
-        port = DEFAULT_PORT,
         playerName = "",
-        dynamicDice = true,
-        autoHideChat = true,
-        autoHideDelay = 8,
-        autoShowChat = true,
-        autoScrollChat = true,
+        portrait = Settings.Portrait(
+            dynamicDice = true
+        ),
+        chat = Settings.Chat(
+            autoHideChat = true,
+            autoHideDelay = 8,
+            autoShowChat = true,
+            autoScrollChat = true,
+            maxLineCount = 200,
+        ),
+        network = Settings.Network(
+            host = DEFAULT_HOST,
+            port = DEFAULT_PORT,
+        ),
         isAdmin = null,
         isGameMaster = null,
     )