diff --git a/mailbox-cli/build.gradle b/mailbox-cli/build.gradle
index 51a8dfb078c35023282fc4bbf4fb6a3c87cc794e..96f9cae33f24452668eba7e0d5cf820a312dfa07 100644
--- a/mailbox-cli/build.gradle
+++ b/mailbox-cli/build.gradle
@@ -1,3 +1,9 @@
+import java.util.jar.JarEntry
+import java.util.jar.JarFile
+import java.util.jar.JarOutputStream
+
+import static java.util.Collections.list
+
 plugins {
     id 'application'
     id 'idea'
@@ -83,6 +89,66 @@ processResources {
     dependsOn unpackTorBinaries
 }
 
+void jarFactory(Jar jarTask, jarArchitecture) {
+    jarTask.doFirst {
+        println 'Building ' + jarArchitecture + ' version has started'
+    }
+    jarTask.manifest {
+        attributes(
+                'Main-Class': application.mainClassName
+        )
+    }
+    jarTask.setArchiveClassifier(jarArchitecture)
+    jarTask.from {
+        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
+    }
+            {
+                it.duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
+                String[] architectures = ["linux-aarch64", "linux-armhf", "linux-x86_64"]
+                for (String arch : architectures) {
+                    if (arch != jarArchitecture) {
+                        exclude "obfs4proxy_" + arch + ".zip"
+                        exclude "tor_" + arch + ".zip"
+                    }
+                }
+                exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA'
+            }
+    jarTask.with jar
+    jarTask.doLast {
+        // Rename the original jar
+        File jar = jarTask.archivePath
+        String srcPath = jar.toString().replaceFirst('\\.jar$', '.unsorted.jar')
+        File srcFile = new File(srcPath)
+        jar.renameTo(srcFile)
+        JarFile srcJarFile = new JarFile(srcFile)
+        OutputStream destStream = new JarOutputStream(new FileOutputStream(jar))
+        // Read and sort the entries
+        Map<String, JarEntry> entries = new TreeMap<>()
+        for (JarEntry e : list(srcJarFile.entries())) entries.put(e.getName(), e)
+        // Write the sorted entries
+        for (JarEntry srcEntry : entries.values()) {
+            JarEntry destEntry = new JarEntry(srcEntry.getName())
+            destEntry.setTime(0)
+            destStream.putNextEntry(destEntry)
+            InputStream srcStream = srcJarFile.getInputStream(srcEntry)
+            int read
+            byte[] buf = new byte[4096]
+            while ((read = srcStream.read(buf, 0, buf.length)) != -1) {
+                destStream.write(buf, 0, read)
+            }
+            destStream.closeEntry()
+            srcStream.close()
+        }
+        destStream.close()
+        srcJarFile.close()
+        println 'Building ' + jarArchitecture + ' version has finished'
+    }
+}
+
+task x86LinuxJar(type: Jar) {
+    jarFactory(it, 'linux-x86_64')
+}
+
 tasks.withType(Test) {
     systemProperty 'java.library.path', 'libs'
 }
diff --git a/mailbox-cli/src/main/java/org/briarproject/mailbox/cli/Main.kt b/mailbox-cli/src/main/java/org/briarproject/mailbox/cli/Main.kt
index 216e13ee020f57e02c13129961ccb56530b6a52d..a6fc20be8def590faa9434dc26ba5b3e48d877b0 100644
--- a/mailbox-cli/src/main/java/org/briarproject/mailbox/cli/Main.kt
+++ b/mailbox-cli/src/main/java/org/briarproject/mailbox/cli/Main.kt
@@ -31,6 +31,7 @@ import org.briarproject.mailbox.core.db.TransactionManager
 import org.briarproject.mailbox.core.lifecycle.LifecycleManager
 import org.briarproject.mailbox.core.setup.QrCodeEncoder
 import org.briarproject.mailbox.core.setup.SetupManager
+import org.briarproject.mailbox.core.setup.WipeManager
 import org.briarproject.mailbox.core.system.InvalidIdException
 import org.slf4j.LoggerFactory.getLogger
 import java.util.logging.Level.ALL
@@ -44,6 +45,10 @@ class Main : CliktCommand(
     name = "briar-mailbox",
     help = "Command line interface for the Briar Mailbox"
 ) {
+    private val wipe by option(
+        "--wipe",
+        help = "Deletes entire mailbox, will require new setup",
+    ).flag(default = false)
     private val debug by option("--debug", "-d", help = "Enable printing of debug messages").flag(
         default = false
     )
@@ -69,6 +74,9 @@ class Main : CliktCommand(
     @Inject
     internal lateinit var setupManager: SetupManager
 
+    @Inject
+    internal lateinit var wipeManager: WipeManager
+
     @Inject
     internal lateinit var qrCodeEncoder: QrCodeEncoder
 
@@ -104,17 +112,36 @@ class Main : CliktCommand(
         lifecycleManager.startServices()
         lifecycleManager.waitForStartup()
 
-        if (setupToken != null) try {
-            setupManager.setToken(setupToken, null)
-        } catch (e: InvalidIdException) {
-            System.err.println("Invalid setup token")
-            exitProcess(1)
+        if (wipe) {
+            // FIXME this can cause a deadlock
+            //  see: https://code.briarproject.org/briar/briar-mailbox/-/issues/76
+            val wipeResult = lifecycleManager.wipeMailbox()
+            lifecycleManager.stopServices()
+            lifecycleManager.waitForShutdown()
+            if (wipeResult) {
+                println("Mailbox wiped successfully \\o/")
+                exitProcess(0)
+            } else {
+                println("ERROR: Mailbox was not wiped cleanly")
+                exitProcess(1)
+            }
+        } else if (setupToken != null) {
+            try {
+                setupManager.setToken(setupToken, null)
+            } catch (e: InvalidIdException) {
+                System.err.println("Invalid setup token")
+                exitProcess(1)
+            }
         }
 
         val ownerTokenExists = db.read { txn ->
             setupManager.getOwnerToken(txn) != null
         }
         if (!ownerTokenExists) {
+            // TODO remove before release
+            val token = setupToken ?: db.read { setupManager.getSetupToken(it) }
+            println("curl -v -H \"Authorization: Bearer $token\" -X PUT http://localhost:8000/setup")
+            // FIXME: We need to wait for the hidden service address to become available
             // If not set up, show QR code for manual setup
             qrCodeEncoder.getQrCodeBitMatrix()?.let {
                 println(QrCodeRenderer.getQrString(it))