diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 0ab4d06fab24683db01ed3bc2b732c01d88a6e5a..43dd2aa92aaf8c58dd88afa7da15101579c52e92 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -1,5 +1,12 @@
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
 plugins {
-    id("java")
+    kotlin("jvm") version "1.6.10"
+    id("org.jlleitschuh.gradle.ktlint") version "10.1.0"
+}
+
+tasks.withType<KotlinCompile> {
+    kotlinOptions.jvmTarget = "11"
 }
 
 repositories {
diff --git a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/AbstractBuildDataTask.java b/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/AbstractBuildDataTask.java
deleted file mode 100644
index b2a076bf19daba605645311298acd4151c628042..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/AbstractBuildDataTask.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.briarproject.briar.desktop.builddata;
-
-import org.gradle.api.internal.ConventionTask;
-import org.gradle.api.logging.Logger;
-import org.gradle.api.tasks.Nested;
-
-public abstract class AbstractBuildDataTask extends ConventionTask {
-
-	protected final Logger logger = getLogger();
-
-	@Nested
-	protected BuildDataPluginExtension configuration;
-
-	public BuildDataPluginExtension getConfiguration() {
-		return configuration;
-	}
-
-	public void setConfiguration(BuildDataPluginExtension configuration) {
-		this.configuration = configuration;
-	}
-
-}
diff --git a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/BuildDataPlugin.java b/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/BuildDataPlugin.java
deleted file mode 100644
index d35887a79e96d3b7dc3e6953417c97ff0940bf5f..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/BuildDataPlugin.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.briarproject.briar.desktop.builddata;
-
-import org.gradle.api.Plugin;
-import org.gradle.api.Project;
-import org.gradle.api.logging.Logger;
-import org.gradle.api.plugins.JavaPluginConvention;
-import org.gradle.api.tasks.SourceSet;
-
-import java.nio.file.Path;
-
-public class BuildDataPlugin implements Plugin<Project> {
-
-	@Override
-	public void apply(final Project project) {
-		Logger logger = project.getLogger();
-		logger.info("applying version access plugin");
-
-		BuildDataPluginExtension extension = project.getExtensions().create(
-				"buildData", BuildDataPluginExtension.class);
-
-		GenerateBuildDataSourceTask task = project.getTasks().create(
-				"buildData", GenerateBuildDataSourceTask.class);
-		task.setConfiguration(extension);
-
-		project.getTasks().findByName("compileJava").dependsOn(task);
-
-		Path pathBuildDir = project.getBuildDir().toPath();
-		Path source = Util.getSourceDir(pathBuildDir);
-
-		SourceSet sourceSets = project.getConvention()
-				.getPlugin(JavaPluginConvention.class).getSourceSets()
-				.findByName("main");
-		sourceSets.java(sourceSet -> {
-			sourceSet.srcDir(source);
-		});
-	}
-
-}
diff --git a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/BuildDataPluginExtension.java b/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/BuildDataPluginExtension.java
deleted file mode 100644
index 9bb4ada377b7080ceaa56fdbbac991d71347e3ee..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/BuildDataPluginExtension.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.briarproject.briar.desktop.builddata;
-
-import org.gradle.api.tasks.Input;
-import org.gradle.api.tasks.Optional;
-
-public class BuildDataPluginExtension {
-
-	@Input
-	private String packageName;
-	@Input
-	@Optional
-	private String className;
-
-	public String getPackageName() {
-		return packageName;
-	}
-
-	public void setPackageName(String packageName) {
-		this.packageName = packageName;
-	}
-
-	public String getClassName() {
-		return className;
-	}
-
-	public void setClassName(String className) {
-		this.className = className;
-	}
-
-}
diff --git a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/FileBuilder.java b/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/FileBuilder.java
deleted file mode 100644
index eaab26681a891e0f2de082617dad96b87e014c26..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/FileBuilder.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.briarproject.briar.desktop.builddata;
-
-class FileBuilder {
-
-	private static String nl = System.getProperty("line.separator");
-
-	private StringBuilder buffer = new StringBuilder();
-
-	void append(String string) {
-		buffer.append(string);
-	}
-
-	void line() {
-		buffer.append(nl);
-	}
-
-	void line(String string) {
-		buffer.append(string);
-		buffer.append(nl);
-	}
-
-	public String toString() {
-		return buffer.toString();
-	}
-
-}
diff --git a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/GenerateBuildDataSourceTask.java b/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/GenerateBuildDataSourceTask.java
deleted file mode 100644
index 51093d24da86f2ff2303e62dffd696fc08714b1a..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/GenerateBuildDataSourceTask.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package org.briarproject.briar.desktop.builddata;
-
-import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.api.errors.GitAPIException;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.gradle.api.GradleScriptException;
-import org.gradle.api.Project;
-import org.gradle.api.tasks.TaskAction;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-public class GenerateBuildDataSourceTask extends AbstractBuildDataTask {
-
-	public GenerateBuildDataSourceTask() {
-		setGroup("build");
-	}
-
-	@TaskAction
-	protected void generateSource() throws IOException {
-		Project project = getProject();
-
-		String packageName = configuration.getPackageName();
-		String className = configuration.getClassName();
-		if (className == null) {
-			className = "BuildData";
-		}
-
-		/*
-		 * Get version from Gradle project information
-		 */
-		String version = project.getVersion().toString();
-
-		/*
-		 * Get Git hash, last commit time and current branch using JGit
-		 */
-		// Open git repository
-		File dir = project.getProjectDir();
-		Git git = Git.open(dir);
-		Repository repository = git.getRepository();
-
-		// Get head ref and it's name => current hash
-		ObjectId head = repository.resolve(Constants.HEAD);
-		String gitHash = head.getName();
-
-		// Get latest commit and its commit time
-		RevCommit first;
-		try {
-			first = getLastCommit(git);
-		} catch (GitAPIException | NoSuchElementException e) {
-			throw new GradleScriptException("Error while fetching commits", e);
-		}
-
-		// Convert from seconds to milliseconds
-		long commitTime = first.getCommitTime() * 1000L;
-
-		// Get current branch, if any
-		String gitBranch = "<unknown>";
-		String prefix = "refs/heads/";
-		String fullBranch = repository.getFullBranch();
-		if (fullBranch.startsWith(prefix)) {
-			gitBranch = fullBranch.substring(prefix.length());
-		}
-
-		/*
-		 * Generate output file
-		 */
-
-		if (packageName == null) {
-			throw new IllegalStateException(
-					"Please specify 'packageName'.");
-		}
-
-		String[] parts = packageName.split("\\.");
-
-		Path pathBuildDir = project.getBuildDir().toPath();
-		Path source = Util.getSourceDir(pathBuildDir);
-
-		Path path = source;
-		for (int i = 0; i < parts.length; i++) {
-			path = path.resolve(parts[i]);
-		}
-
-		Files.createDirectories(path);
-		Path file = path.resolve(className + ".java");
-
-		String content = createSource(packageName, className, version,
-				commitTime, gitHash, gitBranch);
-
-		InputStream in = new ByteArrayInputStream(
-				content.getBytes(StandardCharsets.UTF_8));
-		Files.copy(in, file, StandardCopyOption.REPLACE_EXISTING);
-	}
-
-	private RevCommit getLastCommit(Git git) throws GitAPIException {
-		Iterable<RevCommit> commits = git.log().call();
-
-		Iterator<RevCommit> iterator = commits.iterator();
-		if (!iterator.hasNext()) {
-			throw new NoSuchElementException();
-		}
-		return iterator.next();
-	}
-
-	private String createSource(String packageName, String className,
-			String version, long gitTime, String gitHash, String gitBranch) {
-		FileBuilder buffer = new FileBuilder();
-		// // this file is generated, do not edit
-		// package org.briarproject.briar.desktop;
-		//
-		// public class BuildData {
-		buffer.line("// this file is generated, do not edit");
-		buffer.line("package " + packageName + ";");
-		buffer.line();
-		buffer.line("public class " + className + " {");
-		buffer.line();
-		// public static String getVersion() {
-		//     return "0.1";
-		// }
-		buffer.line("    public static String getVersion() {");
-		buffer.line("        return \"" + version + "\";");
-		buffer.line("    }");
-		buffer.line();
-		// public static long getGitTime() {
-		//		return 1641645802088L;
-		// }
-		buffer.line("    public static long getGitTime() {");
-		buffer.line("        return " + gitTime + "L;");
-		buffer.line("    }");
-		buffer.line();
-		// public static long getGitHash() {
-		//		return "749dda081c3e7862050255817bc239b9255b1582";
-		// }
-		buffer.line("    public static String getGitHash() {");
-		buffer.line("        return \"" + gitHash + "\";");
-		buffer.line("    }");
-		buffer.line();
-		// public static String getGitBranch() {
-		//		return "master";
-		// }
-		buffer.line("    public static String getGitBranch() {");
-		buffer.line("        return \"" + gitBranch + "\";");
-		buffer.line("    }");
-		buffer.line();
-		buffer.line("}");
-
-		return buffer.toString();
-	}
-
-}
diff --git a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/Util.java b/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/Util.java
deleted file mode 100644
index 4c7f7eb094609789e4742bd21fe8a61eddb76745..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/org/briarproject/briar/desktop/builddata/Util.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.briarproject.briar.desktop.builddata;
-
-import java.nio.file.Path;
-
-class Util {
-
-	static Path getSourceDir(Path pathBuildDir) {
-		return pathBuildDir.resolve("generatedBuildData");
-	}
-
-}
diff --git a/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/AbstractBuildDataTask.kt b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/AbstractBuildDataTask.kt
new file mode 100644
index 0000000000000000000000000000000000000000..39be5261f94d3b0418f85ae706f00bf43b96ba40
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/AbstractBuildDataTask.kt
@@ -0,0 +1,10 @@
+package org.briarproject.briar.desktop.builddata
+
+import org.gradle.api.internal.ConventionTask
+import org.gradle.api.tasks.Nested
+
+abstract class AbstractBuildDataTask : ConventionTask() {
+
+    @Nested
+    var configuration: BuildDataPluginExtension? = null
+}
diff --git a/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/BuildDataPlugin.kt b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/BuildDataPlugin.kt
new file mode 100644
index 0000000000000000000000000000000000000000..38d44dd34eade4ed98a09a621e2fb40b0b2d8b82
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/BuildDataPlugin.kt
@@ -0,0 +1,28 @@
+package org.briarproject.briar.desktop.builddata
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.file.SourceDirectorySet
+import org.gradle.api.plugins.JavaPluginConvention
+
+class BuildDataPlugin : Plugin<Project> {
+    override fun apply(project: Project) {
+        val logger = project.logger
+        logger.info("applying version access plugin")
+
+        val extension = project.extensions.create(
+            "buildData", BuildDataPluginExtension::class.java
+        )
+        val task = project.tasks.create(
+            "buildData", GenerateBuildDataSourceTask::class.java
+        )
+        task.configuration = extension
+        project.tasks.findByName("compileJava")!!.dependsOn(task)
+        val pathBuildDir = project.buildDir.toPath()
+        val source = Util.getSourceDir(pathBuildDir)
+        val sourceSets = project.convention
+            .getPlugin(JavaPluginConvention::class.java).sourceSets
+            .findByName("main")
+        sourceSets!!.java { sourceSet: SourceDirectorySet -> sourceSet.srcDir(source) }
+    }
+}
diff --git a/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/BuildDataPluginExtension.kt b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/BuildDataPluginExtension.kt
new file mode 100644
index 0000000000000000000000000000000000000000..007bd0b1f59f84a5266b058787ccb58d60f7a9e9
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/BuildDataPluginExtension.kt
@@ -0,0 +1,13 @@
+package org.briarproject.briar.desktop.builddata
+
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Optional
+
+open class BuildDataPluginExtension {
+    @Input
+    var packageName: String? = null
+
+    @Input
+    @Optional
+    var className: String? = null
+}
diff --git a/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/FileBuilder.kt b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/FileBuilder.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2062ece2e03c37a439557dbb5dd9156006177f4b
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/FileBuilder.kt
@@ -0,0 +1,22 @@
+package org.briarproject.briar.desktop.builddata
+
+internal class FileBuilder {
+    private val buffer = StringBuilder()
+
+    fun line() {
+        buffer.append(nl)
+    }
+
+    fun line(string: String?) {
+        buffer.append(string)
+        buffer.append(nl)
+    }
+
+    override fun toString(): String {
+        return buffer.toString()
+    }
+
+    companion object {
+        private val nl = System.getProperty("line.separator")
+    }
+}
diff --git a/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/GenerateBuildDataSourceTask.kt b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/GenerateBuildDataSourceTask.kt
new file mode 100644
index 0000000000000000000000000000000000000000..849f09f32ad31088f5b239acca10662c276712a6
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/GenerateBuildDataSourceTask.kt
@@ -0,0 +1,153 @@
+package org.briarproject.briar.desktop.builddata
+
+import org.eclipse.jgit.api.Git
+import org.eclipse.jgit.api.errors.GitAPIException
+import org.eclipse.jgit.lib.Constants
+import org.eclipse.jgit.revwalk.RevCommit
+import org.gradle.api.GradleScriptException
+import org.gradle.api.tasks.TaskAction
+import java.io.ByteArrayInputStream
+import java.io.IOException
+import java.io.InputStream
+import java.nio.charset.StandardCharsets
+import java.nio.file.Files
+import java.nio.file.StandardCopyOption
+
+open class GenerateBuildDataSourceTask : AbstractBuildDataTask() {
+    init {
+        group = "build"
+    }
+
+    @TaskAction
+    @Throws(IOException::class)
+    protected fun generateSource() {
+        val project = project
+        val packageName = configuration?.packageName
+        var className = configuration?.className
+        if (className == null) {
+            className = "BuildData"
+        }
+
+        /*
+		 * Get version from Gradle project information
+		 */
+        val version = project.version.toString()
+
+        /*
+		 * Get Git hash, last commit time and current branch using JGit
+		 */
+        // Open git repository
+        val dir = project.projectDir
+        val git = Git.open(dir)
+        val repository = git.repository
+
+        // Get head ref and it's name => current hash
+        val head = repository.resolve(Constants.HEAD)
+        val gitHash = head.name
+
+        // Get latest commit and its commit time
+        val first: RevCommit = try {
+            getLastCommit(git)
+        } catch (e: GitAPIException) {
+            throw GradleScriptException("Error while fetching commits", e)
+        } catch (e: NoSuchElementException) {
+            throw GradleScriptException("Error while fetching commits", e)
+        }
+
+        // Convert from seconds to milliseconds
+        val commitTime = first.commitTime * 1000L
+
+        // Get current branch, if any
+        var gitBranch = "<unknown>"
+        val prefix = "refs/heads/"
+        val fullBranch = repository.fullBranch
+        if (fullBranch.startsWith(prefix)) {
+            gitBranch = fullBranch.substring(prefix.length)
+        }
+
+        /*
+		 * Generate output file
+		 */
+        checkNotNull(packageName) { "Please specify 'packageName'." }
+        val parts = packageName.split("\\.".toRegex()).toTypedArray()
+        val pathBuildDir = project.buildDir.toPath()
+        val source = Util.getSourceDir(pathBuildDir)
+        var path = source
+        for (i in parts.indices) {
+            path = path.resolve(parts[i])
+        }
+        Files.createDirectories(path)
+        val file = path.resolve("$className.java")
+        val content = createSource(
+            packageName, className, version,
+            commitTime, gitHash, gitBranch
+        )
+        val `in`: InputStream = ByteArrayInputStream(
+            content.toByteArray(StandardCharsets.UTF_8)
+        )
+        Files.copy(`in`, file, StandardCopyOption.REPLACE_EXISTING)
+    }
+
+    @Throws(GitAPIException::class)
+    private fun getLastCommit(git: Git): RevCommit {
+        val commits = git.log().call()
+        val iterator: Iterator<RevCommit> = commits.iterator()
+        if (!iterator.hasNext()) {
+            throw NoSuchElementException()
+        }
+        return iterator.next()
+    }
+
+    private fun createSource(
+        packageName: String,
+        className: String,
+        version: String,
+        gitTime: Long,
+        gitHash: String,
+        gitBranch: String,
+    ): String {
+        return FileBuilder().also {
+            with(it) {
+                line("// this file is generated, do not edit")
+                // // this file is generated, do not edit
+                // package org.briarproject.briar.desktop;
+                //
+                // public class BuildData {
+                line("// this file is generated, do not edit")
+                line("package $packageName;")
+                line()
+                line("public class $className {")
+                line()
+                // public static String getVersion() {
+                //     return "0.1";
+                // }
+                line("    public static String getVersion() {")
+                line("        return \"$version\";")
+                line("    }")
+                line()
+                // public static long getGitTime() {
+                //     return 1641645802088L;
+                // }
+                line("    public static long getGitTime() {")
+                line("        return " + gitTime + "L;")
+                line("    }")
+                line()
+                // public static long getGitHash() {
+                //     return "749dda081c3e7862050255817bc239b9255b1582";
+                // }
+                line("    public static String getGitHash() {")
+                line("        return \"$gitHash\";")
+                line("    }")
+                line()
+                // public static String getGitBranch() {
+                //     return "master";
+                // }
+                line("    public static String getGitBranch() {")
+                line("        return \"$gitBranch\";")
+                line("    }")
+                line()
+                line("}")
+            }
+        }.toString()
+    }
+}
diff --git a/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/Util.kt b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/Util.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fbccfbe2dfc2741a15fdb4a5d57ea8bca1d6b92c
--- /dev/null
+++ b/buildSrc/src/main/kotlin/org/briarproject/briar/desktop/builddata/Util.kt
@@ -0,0 +1,9 @@
+package org.briarproject.briar.desktop.builddata
+
+import java.nio.file.Path
+
+internal object Util {
+    fun getSourceDir(pathBuildDir: Path): Path {
+        return pathBuildDir.resolve("generatedBuildData")
+    }
+}