diff --git a/app/src/main/java/de/kuschku/quasseldroid/ssl/QuasselHostnameVerifier.kt b/app/src/main/java/de/kuschku/quasseldroid/ssl/QuasselHostnameVerifier.kt
index 4f6ec01b9087c8e6bd72612b99c6c269f7de065b..9b94a3ca5a5f4e4544ef4479df5828c8a20ca8af 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ssl/QuasselHostnameVerifier.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ssl/QuasselHostnameVerifier.kt
@@ -22,6 +22,7 @@ package de.kuschku.quasseldroid.ssl
 import de.kuschku.libquassel.connection.HostnameVerifier
 import de.kuschku.libquassel.connection.QuasselSecurityException
 import de.kuschku.libquassel.connection.SocketAddress
+import de.kuschku.libquassel.ssl.BrowserCompatibleHostnameVerifier
 import de.kuschku.quasseldroid.ssl.custom.QuasselHostnameManager
 import java.security.cert.X509Certificate
 import javax.net.ssl.SSLException
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/CoreInfoFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/CoreInfoFragment.kt
index 65330355eb579b2b53a8b83a53cfc5125b20b0a4..86f7f5ff1ec96bbfc06023df128b711ed78c80b6 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/CoreInfoFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/CoreInfoFragment.kt
@@ -33,9 +33,9 @@ import androidx.recyclerview.widget.RecyclerView
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.libquassel.quassel.QuasselFeatures
+import de.kuschku.libquassel.ssl.X509Helper
 import de.kuschku.libquassel.util.helpers.value
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ssl.X509Helper
 import de.kuschku.quasseldroid.util.helper.*
 import de.kuschku.quasseldroid.util.missingfeatures.MissingFeature
 import de.kuschku.quasseldroid.util.missingfeatures.MissingFeaturesDialog
diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts
new file mode 100644
index 0000000000000000000000000000000000000000..88efe8d89b2f77e36472fe41ff1a6314d00149cd
--- /dev/null
+++ b/desktop/build.gradle.kts
@@ -0,0 +1,39 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+plugins {
+  application
+  kotlin("jvm")
+  kotlin("kapt")
+}
+
+application {
+  mainClassName = "de.kuschku.cli.MainKt"
+}
+
+dependencies {
+  implementation(kotlin("stdlib", "1.3.11"))
+
+  implementation("io.reactivex.rxjava2", "rxjava", "2.1.9")
+  implementation("info.picocli", "picocli", "3.9.0")
+
+  implementation(project(":lib"))
+
+  testImplementation("junit", "junit", "4.12")
+}
diff --git a/desktop/src/main/java/de/kuschku/desktop/CliArguments.kt b/desktop/src/main/java/de/kuschku/desktop/CliArguments.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c1b577e84b1ec7c12007fd9264b486a937da3d51
--- /dev/null
+++ b/desktop/src/main/java/de/kuschku/desktop/CliArguments.kt
@@ -0,0 +1,59 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.desktop
+
+import picocli.CommandLine
+
+class CliArguments {
+  @CommandLine.Option(names = ["--user"])
+  var user: String = ""
+  @CommandLine.Option(names = ["--pass"])
+  var pass: String = ""
+  @CommandLine.Option(names = ["--host"])
+  var host: String = ""
+  @CommandLine.Option(names = ["--port"])
+  var port: Int = 4242
+
+  override fun toString(): String {
+    return "CliArguments(user='$user', pass='$pass', host='$host', port='$port')"
+  }
+
+  override fun equals(other: Any?): Boolean {
+    if (this === other) return true
+    if (javaClass != other?.javaClass) return false
+
+    other as CliArguments
+
+    if (user != other.user) return false
+    if (pass != other.pass) return false
+    if (host != other.host) return false
+    if (port != other.port) return false
+
+    return true
+  }
+
+  override fun hashCode(): Int {
+    var result = user.hashCode()
+    result = 31 * result + pass.hashCode()
+    result = 31 * result + host.hashCode()
+    result = 31 * result + port.hashCode()
+    return result
+  }
+}
diff --git a/desktop/src/main/java/de/kuschku/desktop/Main.kt b/desktop/src/main/java/de/kuschku/desktop/Main.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d521760f1790d4a02aa04b1aed3c7cecdbb616d5
--- /dev/null
+++ b/desktop/src/main/java/de/kuschku/desktop/Main.kt
@@ -0,0 +1,27 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.desktop
+
+import picocli.CommandLine
+
+fun main(vararg args: String) {
+  val cliArguments = CliArguments()
+  CommandLine(cliArguments).parse(*args)
+}
diff --git a/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt b/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
index 6b2f08735a16908425a98c9717cc049a1c77a5ac..fd50ab783063c7520898977a67d1a1b240197d4c 100644
--- a/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
@@ -27,13 +27,17 @@ import de.kuschku.libquassel.protocol.primitive.serializer.IntSerializer
 import de.kuschku.libquassel.protocol.primitive.serializer.ProtocolInfoSerializer
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantListSerializer
 import de.kuschku.libquassel.quassel.ProtocolFeature
+import de.kuschku.libquassel.quassel.QuasselFeatures
 import de.kuschku.libquassel.session.ProtocolHandler
+import de.kuschku.libquassel.ssl.BrowserCompatibleHostnameVerifier
+import de.kuschku.libquassel.ssl.TrustManagers
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.libquassel.util.compatibility.CompatibilityUtils
 import de.kuschku.libquassel.util.compatibility.HandlerService
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.DEBUG
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.WARN
+import de.kuschku.libquassel.util.compatibility.reference.JavaHandlerService
 import de.kuschku.libquassel.util.flag.hasFlag
 import de.kuschku.libquassel.util.helpers.hexDump
 import de.kuschku.libquassel.util.helpers.write
@@ -49,12 +53,12 @@ import javax.net.ssl.SSLSession
 import javax.net.ssl.X509TrustManager
 
 class CoreConnection(
-  private val clientData: ClientData,
-  private val features: Features,
-  private val trustManager: X509TrustManager,
-  private val hostnameVerifier: HostnameVerifier,
   private val address: SocketAddress,
-  private val handlerService: HandlerService
+  private val clientData: ClientData = ClientData.DEFAULT,
+  private val features: Features = Features(clientData.clientFeatures, QuasselFeatures.empty()),
+  private val handlerService: HandlerService = JavaHandlerService(),
+  private val trustManager: X509TrustManager = TrustManagers.default(),
+  private val hostnameVerifier: HostnameVerifier = BrowserCompatibleHostnameVerifier()
 ) : Thread(), Closeable {
   companion object {
     private const val TAG = "CoreConnection"
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/ClientData.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/ClientData.kt
index 1a39495f90a237ee9e361737567f14114010080f..5b48da23764a39d906b0786ffc23c60d0650f3ee 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/ClientData.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/ClientData.kt
@@ -28,4 +28,17 @@ data class ClientData(
   val clientFeatures: QuasselFeatures,
   val protocolFeatures: Protocol_Features,
   val supportedProtocols: List<Protocol>
-)
+) {
+  companion object {
+    val DEFAULT = ClientData(
+      identifier = "libquassel-java",
+      buildDate = Instant.EPOCH,
+      clientFeatures = QuasselFeatures.all(),
+      protocolFeatures = Protocol_Features.of(
+        Protocol_Feature.Compression,
+        Protocol_Feature.TLS
+      ),
+      supportedProtocols = listOf(Protocol.Datastream)
+    )
+  }
+}
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt
index 0f50ef1e8caa7e3aa29d17475f2a9dcff7da6598..369d287118869c551471dc954a9d164352ae7bc5 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt
@@ -28,7 +28,7 @@ import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.DEBUG
 
 class BacklogManager(
   var session: ISession,
-  private val backlogStorage: BacklogStorage
+  private val backlogStorage: BacklogStorage? = null
 ) : SyncableObject(session.proxy, "BacklogManager"), IBacklogManager {
   private val loading = mutableMapOf<BufferId, (List<Message>) -> Boolean>()
   private val loadingFiltered = mutableMapOf<BufferId, (List<Message>) -> Boolean>()
@@ -42,7 +42,7 @@ class BacklogManager(
     initialized = true
   }
 
-  fun updateIgnoreRules() = backlogStorage.updateIgnoreRules(session)
+  fun updateIgnoreRules() = backlogStorage?.updateIgnoreRules(session)
 
   fun requestBacklog(bufferId: BufferId, first: MsgId = -1, last: MsgId = -1, limit: Int = -1,
                      additional: Int = 0, callback: (List<Message>) -> Boolean) {
@@ -79,7 +79,7 @@ class BacklogManager(
     val list = messages.mapNotNull<QVariant_, Message>(QVariant_::value)
     if (loading.remove(bufferId)?.invoke(list) != false) {
       log(DEBUG, "BacklogManager", "storeMessages(${list.size})")
-      backlogStorage.storeMessages(session, list)
+      backlogStorage?.storeMessages(session, list)
     }
   }
 
@@ -88,7 +88,7 @@ class BacklogManager(
     val list = messages.mapNotNull<QVariant_, Message>(QVariant_::value)
     if (loading.remove(-1)?.invoke(list) != false) {
       log(DEBUG, "BacklogManager", "storeMessages(${list.size})")
-      backlogStorage.storeMessages(session, list)
+      backlogStorage?.storeMessages(session, list)
     }
   }
 
@@ -98,7 +98,7 @@ class BacklogManager(
     val list = messages.mapNotNull<QVariant_, Message>(QVariant_::value)
     if (loadingFiltered.remove(bufferId)?.invoke(list) != false) {
       log(DEBUG, "BacklogManager", "storeMessages(${list.size})")
-      backlogStorage.storeMessages(session, list)
+      backlogStorage?.storeMessages(session, list)
     }
   }
 
@@ -107,11 +107,11 @@ class BacklogManager(
     val list = messages.mapNotNull<QVariant_, Message>(QVariant_::value)
     if (loadingFiltered.remove(-1)?.invoke(list) != false) {
       log(DEBUG, "BacklogManager", "storeMessages(${list.size})")
-      backlogStorage.storeMessages(session, list)
+      backlogStorage?.storeMessages(session, list)
     }
   }
 
   fun removeBuffer(buffer: BufferId) {
-    backlogStorage.clearMessages(buffer)
+    backlogStorage?.clearMessages(buffer)
   }
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt
index 9d431723ad125bb1026410c5edcf969966a1cd4d..1b63fd4250a3346e7b85a69e88ccfeb655202831 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt
@@ -32,7 +32,7 @@ import io.reactivex.subjects.BehaviorSubject
 
 class BufferSyncer constructor(
   var session: ISession,
-  private val notificationManager: NotificationManager?
+  private val notificationManager: NotificationManager? = null
 ) : SyncableObject(session.proxy, "BufferSyncer"), IBufferSyncer {
   override fun deinit() {
     super.deinit()
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
index b106c9b09ad817b00ccc992b36f1bd9f5554bd47..8fb675f6c76e3caeab66def415cf8abf466d9e21 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
@@ -32,8 +32,8 @@ import java.nio.ByteBuffer
 
 class RpcHandler(
   override val session: Session,
-  private val backlogStorage: BacklogStorage,
-  private val notificationManager: NotificationManager?
+  private val backlogStorage: BacklogStorage? = null,
+  private val notificationManager: NotificationManager? = null
 ) : IRpcHandler {
   override fun displayStatusMsg(net: String, msg: String) {
   }
@@ -61,7 +61,7 @@ class RpcHandler(
 
   override fun displayMsg(message: Message) {
     session.bufferSyncer.bufferInfoUpdated(message.bufferInfo)
-    backlogStorage.storeMessages(session, message)
+    backlogStorage?.storeMessages(session, message)
     notificationManager?.processMessages(session, true, message)
   }
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
index 6fd36247fcc12bf1dcaf33d0b0ae3b66ea3f9356..ac5799918455f19af7165b5daf3ae9ec1f74b395 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
@@ -32,7 +32,7 @@ import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.DEBUG
 import java.io.Closeable
 
 abstract class ProtocolHandler(
-  private val exceptionHandler: (Throwable) -> Unit
+  private val exceptionHandler: ((Throwable) -> Unit)? = null
 ) : SignalProxy, AuthHandler, Closeable {
   protected var closed = false
   protected abstract val objectStorage: ObjectStorage
@@ -61,7 +61,7 @@ abstract class ProtocolHandler(
     } catch (e: ObjectNotFoundException) {
       log(DEBUG, "ProtocolHandler", "An error has occured while processing $f", e)
     } catch (e: Throwable) {
-      exceptionHandler.invoke(MessageHandlingException.SignalProxy(f, e))
+      exceptionHandler?.invoke(MessageHandlingException.SignalProxy(f, e))
     }
     return true
   }
@@ -76,7 +76,7 @@ abstract class ProtocolHandler(
     } catch (e: ObjectNotFoundException) {
       log(DEBUG, "ProtocolHandler", "An error has occured while processing $f", e)
     } catch (e: Throwable) {
-      exceptionHandler.invoke(MessageHandlingException.Handshake(f, e))
+      exceptionHandler?.invoke(MessageHandlingException.Handshake(f, e))
     }
     return true
   }
@@ -103,7 +103,7 @@ abstract class ProtocolHandler(
         try {
           this.handle(it)
         } catch (e: Throwable) {
-          exceptionHandler.invoke(e)
+          exceptionHandler?.invoke(e)
         }
       }
     }
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
index ea53f85f35ec2402cb101ca501e8925d8dd3ba66..fbafa47d4f1880091c6589a1d192d006c6e566f5 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
@@ -26,9 +26,12 @@ import de.kuschku.libquassel.protocol.message.SignalProxyMessage
 import de.kuschku.libquassel.quassel.ExtendedFeature
 import de.kuschku.libquassel.quassel.QuasselFeatures
 import de.kuschku.libquassel.quassel.syncables.*
+import de.kuschku.libquassel.ssl.BrowserCompatibleHostnameVerifier
+import de.kuschku.libquassel.ssl.TrustManagers
 import de.kuschku.libquassel.util.compatibility.HandlerService
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.INFO
+import de.kuschku.libquassel.util.compatibility.reference.JavaHandlerService
 import de.kuschku.libquassel.util.rxjava.ReusableUnicastSubject
 import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
@@ -37,19 +40,19 @@ import org.threeten.bp.Instant
 import javax.net.ssl.X509TrustManager
 
 class Session(
-  clientData: ClientData,
-  trustManager: X509TrustManager,
-  hostnameVerifier: HostnameVerifier,
   address: SocketAddress,
-  private val handlerService: HandlerService,
-  backlogStorage: BacklogStorage,
-  private val notificationManager: NotificationManager?,
   private var userData: Pair<String, String>,
-  heartBeatFactory: () -> HeartBeatRunner,
-  val disconnectFromCore: (() -> Unit)?,
-  private val initCallback: ((Session) -> Unit)?,
-  exceptionHandler: (Throwable) -> Unit,
-  private val hasErroredCallback: (Error) -> Unit
+  trustManager: X509TrustManager = TrustManagers.default(),
+  hostnameVerifier: HostnameVerifier = BrowserCompatibleHostnameVerifier(),
+  clientData: ClientData = ClientData.DEFAULT,
+  private val handlerService: HandlerService = JavaHandlerService(),
+  heartBeatFactory: () -> HeartBeatRunner = ::JavaHeartBeatRunner,
+  val disconnectFromCore: (() -> Unit)? = null,
+  private val initCallback: ((Session) -> Unit)? = null,
+  exceptionHandler: ((Throwable) -> Unit)? = null,
+  private val hasErroredCallback: ((Error) -> Unit)? = null,
+  private val notificationManager: NotificationManager? = null,
+  backlogStorage: BacklogStorage? = null
 ) : ProtocolHandler(exceptionHandler), ISession {
   override val objectStorage: ObjectStorage = ObjectStorage(this)
   override val proxy: SignalProxy = this
@@ -59,12 +62,12 @@ class Session(
     get() = coreConnection.sslSession
 
   private val coreConnection = CoreConnection(
+    address,
     clientData,
     features,
+    handlerService,
     trustManager,
-    hostnameVerifier,
-    address,
-    handlerService
+    hostnameVerifier
   )
   override val state = coreConnection.state
 
@@ -112,7 +115,7 @@ class Session(
   }
 
   private fun handleError(error: Error) {
-    hasErroredCallback.invoke(error)
+    hasErroredCallback?.invoke(error)
     this.error.onNext(error)
   }
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
index 5ed8b2298c193d43abdaf3bc3e0cf6d323b7899a..b240aa1580cdb2237705bbcd9cf3ffd97da97227 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
@@ -124,19 +124,19 @@ class SessionManager(
     hasErrored = false
     inProgressSession.onNext(
       Session(
-        clientData,
+        address,
+        userData,
         trustManager,
         hostnameVerifier,
-        address,
+        clientData,
         handlerService,
-        backlogStorage,
-        notificationManager,
-        userData,
         heartBeatFactory,
         disconnectFromCore,
         initCallback,
         exceptionHandler,
-        ::hasErroredCallback
+        ::hasErroredCallback,
+        notificationManager,
+        backlogStorage
       )
     )
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ssl/BrowserCompatibleHostnameVerifier.kt b/lib/src/main/java/de/kuschku/libquassel/ssl/BrowserCompatibleHostnameVerifier.kt
similarity index 96%
rename from app/src/main/java/de/kuschku/quasseldroid/ssl/BrowserCompatibleHostnameVerifier.kt
rename to lib/src/main/java/de/kuschku/libquassel/ssl/BrowserCompatibleHostnameVerifier.kt
index 72c6e80332d2e8a93638050abf98b34522e36d52..4b5ddaefd6a5cfcf2baa846f7f2d38dfb5316d8c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ssl/BrowserCompatibleHostnameVerifier.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/ssl/BrowserCompatibleHostnameVerifier.kt
@@ -17,11 +17,11 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.ssl
+package de.kuschku.libquassel.ssl
 
 import de.kuschku.libquassel.connection.HostnameVerifier
 import de.kuschku.libquassel.connection.SocketAddress
-import de.kuschku.quasseldroid.ssl.X509Helper.hostnames
+import de.kuschku.libquassel.ssl.X509Helper.hostnames
 import java.net.IDN
 import java.security.cert.X509Certificate
 import javax.net.ssl.SSLException
diff --git a/lib/src/main/java/de/kuschku/libquassel/ssl/TrustAllHostnameVerifier.kt b/lib/src/main/java/de/kuschku/libquassel/ssl/TrustAllHostnameVerifier.kt
new file mode 100644
index 0000000000000000000000000000000000000000..88d1e4268c23dc8baa42f0047562301765998088
--- /dev/null
+++ b/lib/src/main/java/de/kuschku/libquassel/ssl/TrustAllHostnameVerifier.kt
@@ -0,0 +1,28 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.ssl
+
+import de.kuschku.libquassel.connection.HostnameVerifier
+import de.kuschku.libquassel.connection.SocketAddress
+import java.security.cert.X509Certificate
+
+class TrustAllHostnameVerifier : HostnameVerifier {
+  override fun checkValid(address: SocketAddress, chain: Array<out X509Certificate>) = Unit
+}
diff --git a/lib/src/main/java/de/kuschku/libquassel/ssl/TrustManagers.kt b/lib/src/main/java/de/kuschku/libquassel/ssl/TrustManagers.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3bd19a4f80c95b885de7c8683ce53f5b5f5d975e
--- /dev/null
+++ b/lib/src/main/java/de/kuschku/libquassel/ssl/TrustManagers.kt
@@ -0,0 +1,43 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.ssl
+
+import java.security.GeneralSecurityException
+import java.security.KeyStore
+import java.security.cert.X509Certificate
+import javax.net.ssl.KeyManagerFactory
+import javax.net.ssl.TrustManagerFactory
+import javax.net.ssl.X509TrustManager
+
+object TrustManagers {
+  fun default() = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()).apply {
+    init(null as KeyStore?)
+  }.trustManagers.mapNotNull {
+    it as? X509TrustManager
+  }.firstOrNull() ?: throw GeneralSecurityException("No TrustManager available")
+
+  fun trustAll() = TrustAllX509TrustManager()
+
+  class TrustAllX509TrustManager : X509TrustManager {
+    override fun checkClientTrusted(p0: Array<out X509Certificate>?, p1: String?) = Unit
+    override fun checkServerTrusted(p0: Array<out X509Certificate>?, p1: String?) = Unit
+    override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray()
+  }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ssl/X509Helper.kt b/lib/src/main/java/de/kuschku/libquassel/ssl/X509Helper.kt
similarity index 96%
rename from app/src/main/java/de/kuschku/quasseldroid/ssl/X509Helper.kt
rename to lib/src/main/java/de/kuschku/libquassel/ssl/X509Helper.kt
index 0270a1ea23f68bedb5fa35083c3466871999a4e5..a2562c2a2f6a125bec8c35131c64f18be407e9f6 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ssl/X509Helper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/ssl/X509Helper.kt
@@ -17,14 +17,15 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.ssl
+package de.kuschku.libquassel.ssl
 
 import java.security.cert.X509Certificate
 
 // FIXME: re-read RFC and check it's actually secure
 object X509Helper {
   fun hostnames(certificate: X509Certificate): Sequence<String> =
-    (sequenceOf(commonName(certificate)) + subjectAlternativeNames(certificate))
+    (sequenceOf(commonName(certificate)) + subjectAlternativeNames(
+      certificate))
       .filterNotNull()
       .distinct()
 
diff --git a/settings.gradle b/settings.gradle
index 919e4870e4df32dd5f12405d1963c70db8c35773..ee35cd8474d514f9dbd53a8203c3cadf6a47ab45 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -17,9 +17,11 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-include ':invokerannotations', ':lifecycle-ktx',
+include ':invokerannotations',
         ':invokergenerator',
         ':lib',
+        ':lifecycle-ktx',
+        ':desktop',
         ":viewmodel",
         ":persistence",
         ':malheur',