diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferListAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferListAdapter.kt
index 19cf99251b367a8b243ab8b6f67d449d61bd8ca2..6a437ebc1cfb7f831fb874f1827783241cad565a 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferListAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferListAdapter.kt
@@ -29,6 +29,7 @@ class BufferListAdapter(
   lifecycleOwner: LifecycleOwner,
   liveData: LiveData<List<BufferProps>?>,
   private val selectedBuffer: MutableLiveData<BufferId>,
+  private val collapsedNetworks: MutableLiveData<Set<NetworkId>>,
   runInBackground: (() -> Unit) -> Any,
   runOnUiThread: (Runnable) -> Any,
   private val clickListener: ((BufferId) -> Unit)? = null,
@@ -36,8 +37,6 @@ class BufferListAdapter(
 ) : RecyclerView.Adapter<BufferListAdapter.BufferViewHolder>() {
   var data = mutableListOf<BufferListItem>()
 
-  private val collapsedNetworks = MutableLiveData<Set<NetworkId>>()
-
   fun expandListener(networkId: NetworkId) {
     if (collapsedNetworks.value.orEmpty().contains(networkId))
       collapsedNetworks.postValue(collapsedNetworks.value.orEmpty() - networkId)
@@ -58,9 +57,6 @@ class BufferListAdapter(
   }
 
   init {
-    collapsedNetworks.value = emptySet()
-    selectedBuffer.value = -1
-
     liveData.zip(collapsedNetworks, selectedBuffer).observe(
       lifecycleOwner, Observer { it: Triple<List<BufferProps>?, Set<NetworkId>, BufferId>? ->
       runInBackground {
@@ -163,9 +159,16 @@ class BufferListAdapter(
     val description: CharSequence,
     val activity: Message_Types,
     val highlights: Int = 0,
-    val bufferActivity: Buffer_Activities = Buffer_Activity.of(Buffer_Activity.NoActivity)
+    val bufferActivity: Buffer_Activities = Buffer_Activity.of(Buffer_Activity.NoActivity),
+    val hiddenState: HiddenState
   )
 
+  enum class HiddenState {
+    VISIBLE,
+    HIDDEN_TEMPORARY,
+    HIDDEN_PERMANENT
+  }
+
   data class BufferState(
     val networkExpanded: Boolean,
     val selected: Boolean
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferViewConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferViewConfigFragment.kt
index a4a5ab9a5453f5b6daa5ce42a42a6a2bf6b7f65f..a3c15efe2bbb72f284ade1a32f452d73323637c5 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferViewConfigFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferViewConfigFragment.kt
@@ -53,7 +53,9 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
       val selected = viewModel.selectedBuffer.value
       val info = selected?.info
       val session = viewModel.session.value
+      val bufferSyncer = session?.bufferSyncer
       val network = session?.networks?.get(selected?.info?.networkId)
+      val bufferViewConfig = viewModel.getBufferViewConfig().value
 
       return if (info != null && session != null) {
         when (item?.itemId) {
@@ -93,6 +95,20 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
             actionMode?.finish()
             true
           }
+          R.id.action_unhide     -> {
+            bufferSyncer?.let {
+              bufferViewConfig?.requestAddBuffer(info, bufferSyncer)
+            }
+            true
+          }
+          R.id.action_hide_temp  -> {
+            bufferViewConfig?.requestRemoveBuffer(info.bufferId)
+            true
+          }
+          R.id.action_hide_perm  -> {
+            bufferViewConfig?.requestRemoveBufferPermanently(info.bufferId)
+            true
+          }
           else                   -> false
         }
       } else {
@@ -180,6 +196,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
           }
       },
       viewModel.selectedBufferId,
+      viewModel.collapsedNetworks,
       handlerThread::post,
       activity!!::runOnUiThread,
       clickListener,
@@ -196,9 +213,27 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
             R.id.action_disconnect,
             R.id.action_join,
             R.id.action_part,
-            R.id.action_delete
+            R.id.action_delete,
+            R.id.action_unhide,
+            R.id.action_hide_temp,
+            R.id.action_hide_perm
           )
 
+          val visibilityActions = when (buffer.hiddenState) {
+            BufferListAdapter.HiddenState.VISIBLE          -> setOf(
+              R.id.action_hide_temp,
+              R.id.action_hide_perm
+            )
+            BufferListAdapter.HiddenState.HIDDEN_TEMPORARY -> setOf(
+              R.id.action_unhide,
+              R.id.action_hide_perm
+            )
+            BufferListAdapter.HiddenState.HIDDEN_PERMANENT -> setOf(
+              R.id.action_unhide,
+              R.id.action_hide_temp
+            )
+          }
+
           val availableActions = when (buffer.info?.type?.enabledValues()?.firstOrNull()) {
             Buffer_Type.StatusBuffer  -> {
               when (buffer.connectionState) {
@@ -214,12 +249,12 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
                 setOf(R.id.action_part)
               } else {
                 setOf(R.id.action_join, R.id.action_delete)
-              }
+              } + visibilityActions
             }
             Buffer_Type.QueryBuffer   -> {
-              setOf(R.id.action_delete)
+              setOf(R.id.action_delete) + visibilityActions
             }
-            else                      -> emptySet()
+            else                      -> visibilityActions
           }
 
           val unavailableActions = allActions - availableActions
@@ -236,7 +271,17 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
       }
     })
 
-    chatListToolbar.startActionMode(actionModeCallback)
+    chatListToolbar.inflateMenu(R.menu.context_bufferlist)
+    chatListToolbar.setOnMenuItemClickListener { item ->
+      when (item.itemId) {
+        R.id.action_show_hidden -> {
+          item.isChecked = !item.isChecked
+          viewModel.showHidden.value = item.isChecked
+          true
+        }
+        else                    -> false
+      }
+    }
     chatList.layoutManager = LinearLayoutManager(context)
     chatList.itemAnimator = DefaultItemAnimator()
     chatList.setItemViewCacheSize(10)
@@ -266,6 +311,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
   data class SelectedItem(
     val info: BufferInfo? = null,
     val connectionState: INetwork.ConnectionState = INetwork.ConnectionState.Disconnected,
-    val joined: Boolean = false
+    val joined: Boolean = false,
+    val hiddenState: BufferListAdapter.HiddenState = BufferListAdapter.HiddenState.VISIBLE
   )
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/viewmodel/QuasselViewModel.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/viewmodel/QuasselViewModel.kt
index eff40a23f4d300c6919b0de5c481211f712ee627..d9b90d73b843d64ab41a9da69fb23b73ffcf18ab 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/viewmodel/QuasselViewModel.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/viewmodel/QuasselViewModel.kt
@@ -5,10 +5,12 @@ import android.arch.lifecycle.MutableLiveData
 import android.arch.lifecycle.ViewModel
 import de.kuschku.libquassel.protocol.BufferId
 import de.kuschku.libquassel.protocol.Buffer_Type
+import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.quassel.syncables.BufferViewConfig
 import de.kuschku.libquassel.quassel.syncables.IrcChannel
 import de.kuschku.libquassel.quassel.syncables.IrcUser
+import de.kuschku.libquassel.quassel.syncables.Network
 import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.session.SessionManager
@@ -192,10 +194,23 @@ class QuasselViewModel : ViewModel() {
     }
   }
 
+  val showHidden = MutableLiveData<Boolean>()
+  val collapsedNetworks = MutableLiveData<Set<NetworkId>>()
   val selectedBufferId = MutableLiveData<BufferId>()
-  val selectedBuffer = session.zip(selectedBufferId).switchMapRx { (session, buffer) ->
+  val selectedBuffer = session.zip(
+    selectedBufferId, bufferViewConfig
+  ).switchMapRx { (session, buffer, bufferViewConfig) ->
     val bufferSyncer = session?.bufferSyncer
-    if (bufferSyncer != null) {
+    if (bufferSyncer != null && bufferViewConfig != null) {
+      val hiddenState = when {
+        bufferViewConfig.removedBuffers().contains(buffer)            ->
+          BufferListAdapter.HiddenState.HIDDEN_PERMANENT
+        bufferViewConfig.temporarilyRemovedBuffers().contains(buffer) ->
+          BufferListAdapter.HiddenState.HIDDEN_TEMPORARY
+        else                                                          ->
+          BufferListAdapter.HiddenState.VISIBLE
+      }
+
       val info = bufferSyncer.bufferInfo(buffer)
       if (info != null) {
         val network = session.networks[info.networkId]
@@ -204,7 +219,8 @@ class QuasselViewModel : ViewModel() {
             network?.liveConnectionState?.map {
               BufferViewConfigFragment.SelectedItem(
                 info,
-                connectionState = it
+                connectionState = it,
+                hiddenState = hiddenState
               )
             }
           }
@@ -212,14 +228,16 @@ class QuasselViewModel : ViewModel() {
             network?.liveIrcChannel(info.bufferName)?.map {
               BufferViewConfigFragment.SelectedItem(
                 info,
-                joined = it != IrcChannel.NULL
+                joined = it != IrcChannel.NULL,
+                hiddenState = hiddenState
               )
             }
           }
-          else                      -> Observable.just(BufferViewConfigFragment.SelectedItem(info))
+          else                      ->
+            Observable.just(BufferViewConfigFragment.SelectedItem(info, hiddenState = hiddenState))
         }
       } else {
-        Observable.just(BufferViewConfigFragment.SelectedItem(info))
+        Observable.just(BufferViewConfigFragment.SelectedItem(info, hiddenState = hiddenState))
       }
     } else {
       Observable.just(BufferViewConfigFragment.SelectedItem())
@@ -227,103 +245,131 @@ class QuasselViewModel : ViewModel() {
   }
 
   val bufferList: LiveData<Pair<BufferViewConfig?, List<BufferListAdapter.BufferProps>>?> = session.zip(
-    bufferViewConfig
-  ).switchMapRx { (session, config) ->
+    bufferViewConfig, showHidden
+  ).switchMapRx { (session, config, showHiddenRaw) ->
     val bufferSyncer = session?.bufferSyncer
+    val showHidden = showHiddenRaw ?: false
     if (bufferSyncer != null && config != null) {
       config.live_config.debounce(16, TimeUnit.MILLISECONDS).switchMap { currentConfig ->
-        config.live_buffers.switchMap { ids ->
-          bufferSyncer.liveBufferInfos().switchMap {
-            Observable.combineLatest(
-              ids.mapNotNull { id ->
-                bufferSyncer.bufferInfo(id)
+        Observable.combineLatest(
+          listOf(
+            config.live_buffers,
+            config.live_temporarilyRemovedBuffers,
+            config.live_removedBuffers
+          ),
+          object : Function<Array<Any>, List<Collection<BufferId>>> {
+            override fun apply(objects: Array<Any>): List<Collection<BufferId>> {
+              return objects.toList() as List<Collection<BufferId>>
+            }
+          }
+        ).switchMap { (ids, temp, perm) ->
+          fun transformIds(ids: Collection<BufferId>, state: BufferListAdapter.HiddenState) =
+            ids.mapNotNull { id ->
+              bufferSyncer.bufferInfo(id)
+            }.filter {
+                currentConfig.networkId() <= 0 || currentConfig.networkId() == it.networkId
               }.filter {
-                  currentConfig.networkId() <= 0 || currentConfig.networkId() == it.networkId
-                }.filter {
-                  (currentConfig.allowedBufferTypes() and it.type).isNotEmpty() ||
-                  it.type.hasFlag(Buffer_Type.StatusBuffer)
-                }.mapNotNull {
-                  val network = session.networks[it.networkId]
-                  if (network == null) {
-                    null
-                  } else {
-                    it to network
+                (currentConfig.allowedBufferTypes() and it.type).isNotEmpty() ||
+                it.type.hasFlag(Buffer_Type.StatusBuffer)
+              }.mapNotNull {
+                val network = session.networks[it.networkId]
+                if (network == null) {
+                  null
+                } else {
+                  it to network
+                }
+              }.map<Pair<BufferInfo, Network>, Observable<BufferListAdapter.BufferProps>?> { (info, network) ->
+                bufferSyncer.liveActivity(info.bufferId).switchMap { activity ->
+                  bufferSyncer.liveHighlightCount(info.bufferId).map { highlights ->
+                    activity to highlights
                   }
-                }.map { (info, network) ->
-                  bufferSyncer.liveActivity(info.bufferId).switchMap { activity ->
-                    bufferSyncer.liveHighlightCount(info.bufferId).map { highlights ->
-                      activity to highlights
-                    }
-                  }.switchMap { (activity, highlights) ->
-                      when (info.type.toInt()) {
-                        BufferInfo.Type.QueryBuffer.toInt()   -> {
-                          network.liveIrcUser(info.bufferName).switchMap { user ->
-                            user.live_away.switchMap { away ->
-                              user.live_realName.map { realName ->
-                                BufferListAdapter.BufferProps(
-                                  info = info,
-                                  network = network.networkInfo(),
-                                  bufferStatus = when {
-                                    user == IrcUser.NULL -> BufferListAdapter.BufferStatus.OFFLINE
-                                    away                 -> BufferListAdapter.BufferStatus.AWAY
-                                    else                 -> BufferListAdapter.BufferStatus.ONLINE
-                                  },
-                                  description = realName,
-                                  activity = activity,
-                                  highlights = highlights
-                                )
-                              }
-                            }
-                          }
-                        }
-                        BufferInfo.Type.ChannelBuffer.toInt() -> {
-                          network.liveIrcChannel(
-                            info.bufferName
-                          ).switchMap { channel ->
-                            channel.live_topic.map { topic ->
+                }.switchMap { (activity, highlights) ->
+                    when (info.type.toInt()) {
+                      BufferInfo.Type.QueryBuffer.toInt()   -> {
+                        network.liveIrcUser(info.bufferName).switchMap { user ->
+                          user.live_away.switchMap { away ->
+                            user.live_realName.map { realName ->
                               BufferListAdapter.BufferProps(
                                 info = info,
                                 network = network.networkInfo(),
-                                bufferStatus = when (channel) {
-                                  IrcChannel.NULL -> BufferListAdapter.BufferStatus.OFFLINE
-                                  else            -> BufferListAdapter.BufferStatus.ONLINE
+                                bufferStatus = when {
+                                  user == IrcUser.NULL -> BufferListAdapter.BufferStatus.OFFLINE
+                                  away                 -> BufferListAdapter.BufferStatus.AWAY
+                                  else                 -> BufferListAdapter.BufferStatus.ONLINE
                                 },
-                                description = topic,
+                                description = realName,
                                 activity = activity,
-                                highlights = highlights
+                                highlights = highlights,
+                                hiddenState = state
                               )
                             }
                           }
                         }
-                        BufferInfo.Type.StatusBuffer.toInt()  -> {
-                          network.liveConnectionState.map {
+                      }
+                      BufferInfo.Type.ChannelBuffer.toInt() -> {
+                        network.liveIrcChannel(
+                          info.bufferName
+                        ).switchMap { channel ->
+                          channel.live_topic.map { topic ->
                             BufferListAdapter.BufferProps(
                               info = info,
                               network = network.networkInfo(),
-                              bufferStatus = BufferListAdapter.BufferStatus.OFFLINE,
-                              description = "",
+                              bufferStatus = when (channel) {
+                                IrcChannel.NULL -> BufferListAdapter.BufferStatus.OFFLINE
+                                else            -> BufferListAdapter.BufferStatus.ONLINE
+                              },
+                              description = topic,
                               activity = activity,
-                              highlights = highlights
+                              highlights = highlights,
+                              hiddenState = state
                             )
                           }
                         }
-                        else                                  -> Observable.just(
+                      }
+                      BufferInfo.Type.StatusBuffer.toInt()  -> {
+                        network.liveConnectionState.map {
                           BufferListAdapter.BufferProps(
                             info = info,
                             network = network.networkInfo(),
                             bufferStatus = BufferListAdapter.BufferStatus.OFFLINE,
                             description = "",
                             activity = activity,
-                            highlights = highlights
+                            highlights = highlights,
+                            hiddenState = state
                           )
-                        )
+                        }
                       }
+                      else                                  -> Observable.just(
+                        BufferListAdapter.BufferProps(
+                          info = info,
+                          network = network.networkInfo(),
+                          bufferStatus = BufferListAdapter.BufferStatus.OFFLINE,
+                          description = "",
+                          activity = activity,
+                          highlights = highlights,
+                          hiddenState = state
+                        )
+                      )
                     }
-                }, object : Function<Array<Any>, List<BufferListAdapter.BufferProps>> {
-              override fun apply(objects: Array<Any>): List<BufferListAdapter.BufferProps> {
-                return objects.toList() as List<BufferListAdapter.BufferProps>
+                  }
               }
+
+          bufferSyncer.liveBufferInfos().switchMap {
+            val buffers = if (showHidden) {
+              transformIds(ids, BufferListAdapter.HiddenState.VISIBLE) +
+              transformIds(temp, BufferListAdapter.HiddenState.HIDDEN_TEMPORARY) +
+              transformIds(perm, BufferListAdapter.HiddenState.HIDDEN_PERMANENT)
+            } else {
+              transformIds(ids, BufferListAdapter.HiddenState.VISIBLE)
             }
+
+            Observable.combineLatest(
+              buffers,
+              object : Function<Array<Any>, List<BufferListAdapter.BufferProps>> {
+                override fun apply(objects: Array<Any>): List<BufferListAdapter.BufferProps> {
+                  return objects.toList() as List<BufferListAdapter.BufferProps>
+                }
+              }
             ).map { list ->
               Pair<BufferViewConfig?, List<BufferListAdapter.BufferProps>>(
                 config,
@@ -342,4 +388,10 @@ class QuasselViewModel : ViewModel() {
       )
     }
   }
+
+  init {
+    showHidden.postValue(false)
+    selectedBufferId.postValue(-1)
+    collapsedNetworks.value = emptySet()
+  }
 }
\ No newline at end of file
diff --git a/app/src/main/res/menu/context_buffer.xml b/app/src/main/res/menu/context_buffer.xml
index 08152e25cae16452dc58001bed6d8411fbfe2b79..9754406733c30da0117b61e6e71c436cd4c0e712 100644
--- a/app/src/main/res/menu/context_buffer.xml
+++ b/app/src/main/res/menu/context_buffer.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+  xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
     android:id="@+id/action_connect"
     android:title="@string/label_connect" />
@@ -15,5 +16,16 @@
   <item
     android:id="@+id/action_delete"
     android:title="@string/label_delete" />
-  <!--<item android:title="Merge" />-->
+  <item
+    android:id="@+id/action_unhide"
+    android:title="@string/label_unhide"
+    app:showAsAction="never" />
+  <item
+    android:id="@+id/action_hide_temp"
+    android:title="@string/label_hide_temp"
+    app:showAsAction="never" />
+  <item
+    android:id="@+id/action_hide_perm"
+    android:title="@string/label_hide_perm"
+    app:showAsAction="never" />
 </menu>
\ No newline at end of file
diff --git a/app/src/main/res/menu/context_bufferlist.xml b/app/src/main/res/menu/context_bufferlist.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2c85564867ec2735ae80c3ef28478c5a60d99b3f
--- /dev/null
+++ b/app/src/main/res/menu/context_bufferlist.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+  <item
+    android:id="@+id/action_show_hidden"
+    android:checkable="true"
+    android:title="@string/label_show_hidden" />
+</menu>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dd5bb3719004db9b2e10d4ff236574a732c84058..fe8fac721ac408771ae41cf424ced212c7850ad7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,6 +11,8 @@
   <string name="label_delete">Delete</string>
   <string name="label_disconnect">Disconnect</string>
   <string name="label_filter_messages">Filter Messages</string>
+  <string name="label_hide_perm">Hide Permanently</string>
+  <string name="label_hide_temp">Hide Temporarily</string>
   <string name="label_input_history">Input History</string>
   <string name="label_join">Join</string>
   <string name="label_open">Open</string>
@@ -19,6 +21,8 @@
   <string name="label_save">Save</string>
   <string name="label_select_multiple">Select</string>
   <string name="label_settings">Settings</string>
+  <string name="label_show_hidden">Show Hidden</string>
+  <string name="label_unhide">Make Visible</string>
 
   <string name="label_status_disconnected">Disconnected</string>
   <string name="label_status_connecting">Connecting</string>