diff --git a/Cargo.lock b/Cargo.lock
index a6801f35ce345fa54758e8909e3e8a73d07716f6..930ecd337e6e007fdbb0b57965fb20620ede1524 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1890,7 +1890,6 @@ dependencies = [
  "dirs",
  "libc",
  "log",
- "pathdiff",
  "serde",
  "serde_json",
  "tokio",
@@ -2553,12 +2552,6 @@ dependencies = [
  "windows-targets 0.48.5",
 ]
 
-[[package]]
-name = "pathdiff"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
-
 [[package]]
 name = "percent-encoding"
 version = "2.3.0"
diff --git a/Cargo.toml b/Cargo.toml
index 43d99fff1db64252f6ea22d0d01fe4bc1d8a336d..0951ca66e618a38709a3788dd82d1c8d0d4188f4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,36 +1,26 @@
 [workspace]
 resolver = "2"
 members = [
-    # Lektord
-    "lektord",
-    "lektor_nkdb",
-    "lektor_repo",
-
-    # Common things
-    "kurisu_api",
-    "lektor_lib",
-    "lektor_utils",
-    "lektor_mpris",
-    "lektor_payloads",
-    "lektor_procmacros",
-
-    # Clients
-    "amadeus",
-    "lkt",
+    "amadeus",    # GUI Client
+    "lkt",        # CLI Client
+    "lektord",    # Lektord
+    "kurisu_api", # The Kurisu API
+    "lektor_*",   # Common things
 ]
 
 [workspace.package]
 edition = "2021"
 authors = [
     "Maël MARTIN <mael.martin@protonmail.com>",
-    "Louis GOYARD",
-    "Loïc ALLEGRE",
-    "Kevin COCCHI",
-    "Félix GOUEDARD",
-    "Hubert HIRTZ",
-    "Étienne BRATEAU",
-    "Tristan DEROUET",
+    "Louis GOYARD <elliu@hashi.re>",
+    "Loïc ALLEGRE <lallegre26@gmail.com>",
+    "Kevin COCCHI <salixor@pm.me>",
+    "Félix GOUEDARD <felix.gouedard@ensiie.fr>",
+    "Hubert HIRTZ <hubert.hirtz@laposte.net>",
+    "Étienne BRATEAU <etienne.brateau@gmail.com>",
+    "Tristan DEROUET <tristan.derouet@gmail.com>",
 ]
+rust-version = "1.70"
 version = "3.0.1"
 license = "MIT"
 
@@ -55,7 +45,6 @@ regex = { version = "1.9", default-features = false, features = [
 ] }
 url = { version = "2", default-features = false }
 rand = "*"
-libc = { version = "0.2", default-features = false }
 zbus = { version = "3", default-features = false, features = ["tokio"] }
 chrono = { version = "0.4", default-features = false, features = ["clock"] }
 sha256 = { version = "1", default-features = false, features = ["async"] }
diff --git a/amadeus/Cargo.toml b/amadeus/Cargo.toml
index 2724906007ca7ba7a7d78e0fe305eab86b632b77..e3bc99b948e794db0120d640956cedfa22a981f0 100644
--- a/amadeus/Cargo.toml
+++ b/amadeus/Cargo.toml
@@ -4,6 +4,7 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
 description = "Amadeus-RS, graphical interface for lektord"
 
 [dependencies]
diff --git a/kurisu_api/Cargo.toml b/kurisu_api/Cargo.toml
index 14fa321d3e7cfb3db83b515bf759fede7ded74f3..b2d25cc338deef8e870c6bd83e7c6680d2fbc2e6 100644
--- a/kurisu_api/Cargo.toml
+++ b/kurisu_api/Cargo.toml
@@ -4,6 +4,7 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
 description = "Crate used to deserialize what Kurisu returns"
 
 [lib]
diff --git a/lektor_lib/Cargo.toml b/lektor_lib/Cargo.toml
index ecf79f7d39ee27026ce88df00cac4f60d01c3117..190cd320cdd89187a4c19169c85fa9c359f3eee8 100644
--- a/lektor_lib/Cargo.toml
+++ b/lektor_lib/Cargo.toml
@@ -4,6 +4,7 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
 description = "Client library for lektord, used to factorize the code between lkt and amadeus"
 
 [dependencies]
diff --git a/lektor_mpris/Cargo.toml b/lektor_mpris/Cargo.toml
index 5faa2c308dc42260900f22f9c94fdaf5e79047c7..2418277d856ed1a2a98e65810d4cebf1724b60ab 100644
--- a/lektor_mpris/Cargo.toml
+++ b/lektor_mpris/Cargo.toml
@@ -4,6 +4,7 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
 description = "Implement the mpris spec, designed to be plugable into lektord or amadeus"
 
 [dependencies]
diff --git a/lektor_nkdb/Cargo.toml b/lektor_nkdb/Cargo.toml
index c6aedf352840da5a748557612af55690897f7be7..5541700811d801c26109c7aa1deb84316f442222 100644
--- a/lektor_nkdb/Cargo.toml
+++ b/lektor_nkdb/Cargo.toml
@@ -4,6 +4,7 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
 description = "New database implementation for lektord (New Kara DataBase)"
 
 [dependencies]
diff --git a/lektor_payloads/Cargo.toml b/lektor_payloads/Cargo.toml
index 9a9350958343316492c97235e9513025f8acea6b..315a1e2e1011ec3d96eb7e53d13dbdc6e63a5942 100644
--- a/lektor_payloads/Cargo.toml
+++ b/lektor_payloads/Cargo.toml
@@ -4,6 +4,8 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
+description = "The payloads of the requests used to exchange messages between lektord and its client, this is a utility crate, you can build your own thing because they are all serialized to json under the hood"
 
 [dependencies]
 serde.workspace = true
diff --git a/lektor_procmacros/Cargo.toml b/lektor_procmacros/Cargo.toml
index e319eb760ec3adfc44de14baea4f3a87eb2170fd..11c1c252d2548021edd1ecb6e25aabac46070c74 100644
--- a/lektor_procmacros/Cargo.toml
+++ b/lektor_procmacros/Cargo.toml
@@ -1,10 +1,10 @@
-# Add https://crates.io/crates/derivative
 [package]
 name = "lektor_procmacros"
 authors.workspace = true
 license.workspace = true
 edition.workspace = true
 version.workspace = true
+rust-version.workspace = true
 description = "A collection of procedural macros for the workspace"
 
 [lib]
diff --git a/lektor_repo/Cargo.toml b/lektor_repo/Cargo.toml
index f32c7d41a80bc04c89e474d3a1bef54c3ce45b14..2a02274e3fb0fe1f846c57bae0537afa698ed2fe 100644
--- a/lektor_repo/Cargo.toml
+++ b/lektor_repo/Cargo.toml
@@ -4,6 +4,7 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
 description = "Structure used to update the lektord's database from a repo, can be kurisu or something else - only kurisu for now btw"
 
 [lib]
diff --git a/lektor_utils/Cargo.toml b/lektor_utils/Cargo.toml
index ef4f59a243bd1b39b2e3a628851901a983362c38..e3d8b4533baf5cb4c02d8e585042bd018efb61b1 100644
--- a/lektor_utils/Cargo.toml
+++ b/lektor_utils/Cargo.toml
@@ -4,6 +4,7 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
 description = "Utilities in common for all the crates in the workspace"
 
 [lib]
@@ -21,9 +22,5 @@ chrono.workspace = true
 serde_json.workspace = true
 
 # Some specific things for the open module.
-
-[target.'cfg(all(unix, not(macos)))'.dependencies]
-pathdiff = "0.2.0"
-
 [target."cfg(unix)".dependencies]
 libc = "0.2"
diff --git a/lektor_utils/src/lib.rs b/lektor_utils/src/lib.rs
index 05ec6081764adacf889f7c5c0c0de5c93e4660f1..ce8d14b283d64a1acf86c29f7188bc19e8145948 100644
--- a/lektor_utils/src/lib.rs
+++ b/lektor_utils/src/lib.rs
@@ -6,7 +6,7 @@ mod base64;
 mod iterator;
 mod macros;
 
-// Import the is_wsl and is_docker code here...
+/// Import the is_wsl and is_docker code here...
 #[cfg(any(
     target_os = "linux",
     target_os = "android",
@@ -19,6 +19,9 @@ mod macros;
 ))]
 pub mod is;
 
+/// Pathdiff to handle some errors with WSL...
+pub mod pathdiff;
+
 pub mod config;
 pub mod log;
 pub mod logger;
diff --git a/lektor_utils/src/open/haiku.rs b/lektor_utils/src/open/haiku.rs
index 2fbcd138d3e2bd3df733ac61eba7ab0e59f62fc1..1eb43ad8fc1a1a59bd34f33011427ed1282a886d 100644
--- a/lektor_utils/src/open/haiku.rs
+++ b/lektor_utils/src/open/haiku.rs
@@ -1,12 +1,12 @@
 use std::{ffi::OsStr, process::Command};
 
-pub fn commands<T: AsRef<OsStr>>(path: T) -> Vec<Command> {
+pub fn commands(path: impl AsRef<OsStr>) -> Vec<Command> {
     let mut cmd = Command::new("/bin/open");
     cmd.arg(path.as_ref());
     vec![cmd]
 }
 
-pub fn with_command<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> Command {
+pub fn with_command(path: impl AsRef<OsStr>, app: impl Into<String>) -> Command {
     let mut cmd = Command::new(app.into());
     cmd.arg(path.as_ref());
     cmd
diff --git a/lektor_utils/src/open/ios.rs b/lektor_utils/src/open/ios.rs
index e1d78f1dc46a97b696a3e5ed1a665a45be7a54bf..d1fbdbe464393ff1060194d3de5fc108d4674a92 100644
--- a/lektor_utils/src/open/ios.rs
+++ b/lektor_utils/src/open/ios.rs
@@ -1,12 +1,12 @@
 use std::{ffi::OsStr, process::Command};
 
-pub fn commands<T: AsRef<OsStr>>(path: T) -> Vec<Command> {
+pub fn commands(path: impl AsRef<OsStr>) -> Vec<Command> {
     let mut cmd = Command::new("uiopen");
     cmd.arg("--url").arg(path.as_ref());
     vec![cmd]
 }
 
-pub fn with_command<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> Command {
+pub fn with_command(path: impl AsRef<OsStr>, app: impl Into<String>) -> Command {
     let mut cmd = Command::new("uiopen");
     cmd.arg("--url")
         .arg(path.as_ref())
diff --git a/lektor_utils/src/open/macos.rs b/lektor_utils/src/open/macos.rs
index 6033d64c394005060cba798e63dde7d3119347ce..7c9a7aea78af72886aea2fdd5a2782895453b257 100644
--- a/lektor_utils/src/open/macos.rs
+++ b/lektor_utils/src/open/macos.rs
@@ -1,12 +1,12 @@
 use std::{ffi::OsStr, process::Command};
 
-pub fn commands<T: AsRef<OsStr>>(path: T) -> Vec<Command> {
+pub fn commands(path: impl AsRef<OsStr>) -> Vec<Command> {
     let mut cmd = Command::new("/usr/bin/open");
     cmd.arg(path.as_ref());
     vec![cmd]
 }
 
-pub fn with_command<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> Command {
+pub fn with_command(path: impl AsRef<OsStr>, app: impl Into<String>) -> Command {
     let mut cmd = Command::new("/usr/bin/open");
     cmd.arg(path.as_ref()).arg("-a").arg(app.into());
     cmd
diff --git a/lektor_utils/src/open/mod.rs b/lektor_utils/src/open/mod.rs
index f21897b8dc9dd6155d47b23dffa99ad5a7a54d99..20b9bdc0e44a92bf68de1018e77588428562be77 100644
--- a/lektor_utils/src/open/mod.rs
+++ b/lektor_utils/src/open/mod.rs
@@ -66,20 +66,25 @@
 //! }
 //! ```
 
-#[cfg(target_os = "windows")]
-use windows as os;
+#[cfg(windows)]
+#[path = "windows.rs"]
+mod windows;
 
 #[cfg(target_os = "macos")]
-use macos as os;
+#[path = "macos.rs"]
+mod os;
 
 #[cfg(target_os = "ios")]
-use ios as os;
+#[path = "ios.rs"]
+mod os;
 
 #[cfg(target_os = "haiku")]
-use haiku as os;
+#[path = "haiku.rs"]
+mod os;
 
 #[cfg(target_os = "redox")]
-use redox as os;
+#[path = "redox.rs"]
+mod os;
 
 #[cfg(any(
     target_os = "linux",
@@ -91,7 +96,8 @@ use redox as os;
     target_os = "illumos",
     target_os = "solaris"
 ))]
-use unix as os;
+#[path = "unix.rs"]
+mod os;
 
 #[cfg(not(any(
     target_os = "linux",
@@ -108,7 +114,7 @@ use unix as os;
     target_os = "haiku",
     target_os = "redox"
 )))]
-compile_error!("open is not supported on this platform");
+compile_error!("unsupported on this platform");
 
 use std::{
     ffi::OsStr,
@@ -223,8 +229,8 @@ pub fn that_in_background(path: impl AsRef<OsStr>) -> thread::JoinHandle<io::Res
 /// straightforward error handling.
 ///
 /// See documentation of [`with()`] for more details.
-pub fn with_in_background<T: AsRef<OsStr>>(
-    path: T,
+pub fn with_in_background(
+    path: impl AsRef<OsStr>,
     app: impl Into<String>,
 ) -> thread::JoinHandle<io::Result<()>> {
     let path = path.as_ref().to_os_string();
@@ -240,9 +246,7 @@ pub fn that_detached(path: impl AsRef<OsStr>) -> io::Result<()> {
     let mut last_err = None;
     for mut cmd in commands(path) {
         match cmd.spawn_detached() {
-            Ok(_) => {
-                return Ok(());
-            }
+            Ok(_) => return Ok(()),
             Err(err) => last_err = Some(err),
         }
     }
@@ -254,9 +258,8 @@ pub fn that_detached(path: impl AsRef<OsStr>) -> io::Result<()> {
 /// straightforward error handling.
 ///
 /// See documentation of [`with()`] for more details.
-pub fn with_detached<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> io::Result<()> {
-    let mut cmd = with_command(path, app);
-    cmd.spawn_detached()
+pub fn with_detached(path: impl AsRef<OsStr>, app: impl Into<String>) -> io::Result<()> {
+    with_command(path, app).spawn_detached()
 }
 
 trait IntoResult<T> {
@@ -292,26 +295,21 @@ impl CommandExt for Command {
     fn spawn_detached(&mut self) -> io::Result<()> {
         // This is pretty much lifted from the implementation in Alacritty:
         // https://github.com/alacritty/alacritty/blob/b9c886872d1202fc9302f68a0bedbb17daa35335/alacritty/src/daemon.rs
-
         self.stdin(Stdio::null())
             .stdout(Stdio::null())
             .stderr(Stdio::null());
-
         #[cfg(unix)]
         unsafe {
             use std::os::unix::process::CommandExt as _;
-
             self.pre_exec(move || {
                 match libc::fork() {
-                    -1 => return Err(io::Error::last_os_error()),
+                    x if x < 0 => return Err(io::Error::last_os_error()),
                     0 => (),
                     _ => libc::_exit(0),
                 }
-
-                if libc::setsid() == -1 {
+                if libc::setsid() < 0 {
                     return Err(io::Error::last_os_error());
                 }
-
                 Ok(())
             });
         }
@@ -322,34 +320,6 @@ impl CommandExt for Command {
             const CREATE_NO_WINDOW: u32 = 0x08000000;
             self.creation_flags(CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW);
         }
-
         self.spawn().map(|_| ())
     }
 }
-
-#[cfg(windows)]
-mod windows;
-
-#[cfg(target_os = "macos")]
-mod macos;
-
-#[cfg(target_os = "ios")]
-mod ios;
-
-#[cfg(target_os = "haiku")]
-mod haiku;
-
-#[cfg(target_os = "redox")]
-mod redox;
-
-#[cfg(any(
-    target_os = "linux",
-    target_os = "android",
-    target_os = "freebsd",
-    target_os = "dragonfly",
-    target_os = "netbsd",
-    target_os = "openbsd",
-    target_os = "illumos",
-    target_os = "solaris"
-))]
-mod unix;
diff --git a/lektor_utils/src/open/redox.rs b/lektor_utils/src/open/redox.rs
index 8fab3434207ebdeb2ec1a09581105bf3e6f61743..84609e5a5b5a49f88cd1ee8ec20ae0ffca70dc98 100644
--- a/lektor_utils/src/open/redox.rs
+++ b/lektor_utils/src/open/redox.rs
@@ -1,12 +1,12 @@
 use std::{ffi::OsStr, process::Command};
 
-pub fn commands<T: AsRef<OsStr>>(path: T) -> Vec<Command> {
+pub fn commands(path: impl AsRef<OsStr>) -> Vec<Command> {
     let mut cmd = Command::new("/ui/bin/launcher");
     cmd.arg(path.as_ref());
     vec![cmd]
 }
 
-pub fn with_command<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> Command {
+pub fn with_command(path: impl AsRef<OsStr>, app: impl Into<String>) -> Command {
     let mut cmd = Command::new(app.into());
     cmd.arg(path.as_ref());
     cmd
diff --git a/lektor_utils/src/open/unix.rs b/lektor_utils/src/open/unix.rs
index 7cb23eebb01f36176c10ca6bcc038e7cc23f7b37..3df5e3eb161b7e4718dfe3b30874e65df86d7f75 100644
--- a/lektor_utils/src/open/unix.rs
+++ b/lektor_utils/src/open/unix.rs
@@ -1,11 +1,11 @@
 use std::{
     env,
     ffi::{OsStr, OsString},
-    path::{Path, PathBuf},
+    path::Path,
     process::Command,
 };
 
-pub fn commands<T: AsRef<OsStr>>(path: T) -> Vec<Command> {
+pub fn commands(path: impl AsRef<OsStr>) -> Vec<Command> {
     let path = path.as_ref();
     let mut commands: Vec<(&str, Vec<&OsStr>)> = vec![];
 
@@ -37,23 +37,20 @@ pub fn with_command<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> Command
     cmd
 }
 
-// Polyfill to workaround absolute path bug in wslu(wslview). In versions before
-// v3.1.1, wslview is unable to find absolute paths. `wsl_path` converts an
-// absolute path into a relative path starting from the current directory. If
-// the path is already a relative path or the conversion fails the original path
-// is returned.
-fn wsl_path<T: AsRef<OsStr>>(path: T) -> OsString {
-    fn path_relative_to_current_dir<T: AsRef<OsStr>>(path: T) -> Option<PathBuf> {
-        let path = Path::new(&path);
-        if path.is_relative() {
-            return None;
-        }
-
-        pathdiff::diff_paths(path, env::current_dir().ok()?)
-    }
-
-    match path_relative_to_current_dir(&path) {
-        None => OsString::from(&path),
-        Some(relative) => OsString::from(relative),
+/// Polyfill to workaround absolute path bug in wslu(wslview). In versions before v3.1.1, wslview
+/// is unable to find absolute paths. `wsl_path` converts an absolute path into a relative path
+/// starting from the current directory. If the path is already a relative path or the conversion
+/// fails the original path is returned.
+fn wsl_path(path_str: impl AsRef<OsStr>) -> OsString {
+    let path = Path::new(path_str.as_ref());
+    match env::current_dir().ok() {
+        Some(current) => match path
+            .is_relative()
+            .then(|| crate::pathdiff::diff_paths(path, current))
+        {
+            Some(Some(relative)) => OsString::from(relative),
+            _ => path_str.as_ref().to_owned(),
+        },
+        None => path_str.as_ref().to_owned(),
     }
 }
diff --git a/lektor_utils/src/open/windows.rs b/lektor_utils/src/open/windows.rs
index e44b1610fa2ae524a932cb438fc51e1c921f8983..202aefbe6861cc499a7bb3a3d7307c31fb98fa80 100644
--- a/lektor_utils/src/open/windows.rs
+++ b/lektor_utils/src/open/windows.rs
@@ -6,7 +6,7 @@ use std::{
 
 const CREATE_NO_WINDOW: u32 = 0x08000000;
 
-pub fn commands<T: AsRef<OsStr>>(path: T) -> Vec<Command> {
+pub fn commands(path: impl AsRef<OsStr>) -> Vec<Command> {
     let mut cmd = Command::new("cmd");
     cmd.arg("/c")
         .arg("start")
@@ -16,7 +16,7 @@ pub fn commands<T: AsRef<OsStr>>(path: T) -> Vec<Command> {
     vec![cmd]
 }
 
-pub fn with_command<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> Command {
+pub fn with_command(path: impl AsRef<OsStr>, app: impl Into<String>) -> Command {
     let mut cmd = Command::new("cmd");
     cmd.arg("/c")
         .arg("start")
@@ -27,7 +27,7 @@ pub fn with_command<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> Command
     cmd
 }
 
-fn wrap_in_quotes<T: AsRef<OsStr>>(path: T) -> OsString {
+fn wrap_in_quotes(path: impl AsRef<OsStr>) -> OsString {
     let mut result = OsString::from("\"");
     result.push(path);
     result.push("\"");
diff --git a/lektor_utils/src/pathdiff.rs b/lektor_utils/src/pathdiff.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b9a72acb3bafc171b77cf0584b32e5a889662003
--- /dev/null
+++ b/lektor_utils/src/pathdiff.rs
@@ -0,0 +1,144 @@
+use std::path::*;
+
+/// Construct a relative path from a provided base directory path to the provided path.
+///
+/// ```rust
+/// use pathdiff::diff_paths;
+/// use std::path::*;
+///
+/// let baz = "/foo/bar/baz";
+/// let bar = "/foo/bar";
+/// let quux = "/foo/bar/quux";
+/// assert_eq!(diff_paths(bar, baz), Some("../".into()));
+/// assert_eq!(diff_paths(baz, bar), Some("baz".into()));
+/// assert_eq!(diff_paths(quux, baz), Some("../quux".into()));
+/// assert_eq!(diff_paths(baz, quux), Some("../baz".into()));
+/// assert_eq!(diff_paths(bar, quux), Some("../".into()));
+///
+/// assert_eq!(diff_paths(&baz, &bar.to_string()), Some("baz".into()));
+/// assert_eq!(diff_paths(Path::new(baz), Path::new(bar).to_path_buf()), Some("baz".into()));
+/// ```
+pub fn diff_paths<P, B>(path: P, base: B) -> Option<PathBuf>
+where
+    P: AsRef<Path>,
+    B: AsRef<Path>,
+{
+    let path = path.as_ref();
+    let base = base.as_ref();
+
+    if path.is_absolute() != base.is_absolute() {
+        if path.is_absolute() {
+            Some(PathBuf::from(path))
+        } else {
+            None
+        }
+    } else {
+        let mut ita = path.components();
+        let mut itb = base.components();
+        let mut comps: Vec<Component> = vec![];
+        loop {
+            match (ita.next(), itb.next()) {
+                (None, None) => break,
+                (Some(a), None) => {
+                    comps.push(a);
+                    comps.extend(ita.by_ref());
+                    break;
+                }
+                (None, _) => comps.push(Component::ParentDir),
+                (Some(a), Some(b)) if comps.is_empty() && a == b => (),
+                (Some(a), Some(b)) if b == Component::CurDir => comps.push(a),
+                (Some(_), Some(b)) if b == Component::ParentDir => return None,
+                (Some(a), Some(_)) => {
+                    comps.push(Component::ParentDir);
+                    for _ in itb {
+                        comps.push(Component::ParentDir);
+                    }
+                    comps.push(a);
+                    comps.extend(ita.by_ref());
+                    break;
+                }
+            }
+        }
+        Some(comps.iter().map(|c| c.as_os_str()).collect())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_absolute() {
+        #[cfg(windows)]
+        fn abs(path: &str) -> String {
+            format!("C:\\{}", path)
+        }
+
+        #[cfg(not(windows))]
+        fn abs(path: &str) -> String {
+            format!("/{}", path)
+        }
+
+        assert_diff_paths(&abs("foo"), &abs("bar"), Some("../foo"));
+        assert_diff_paths(&abs("foo"), "bar", Some(&abs("foo")));
+        assert_diff_paths("foo", &abs("bar"), None);
+        assert_diff_paths("foo", "bar", Some("../foo"));
+    }
+
+    #[test]
+    fn test_identity() {
+        assert_diff_paths(".", ".", Some(""));
+        assert_diff_paths("../foo", "../foo", Some(""));
+        assert_diff_paths("./foo", "./foo", Some(""));
+        assert_diff_paths("/foo", "/foo", Some(""));
+        assert_diff_paths("foo", "foo", Some(""));
+
+        assert_diff_paths("../foo/bar/baz", "../foo/bar/baz", Some("".into()));
+        assert_diff_paths("foo/bar/baz", "foo/bar/baz", Some(""));
+    }
+
+    #[test]
+    fn test_subset() {
+        assert_diff_paths("foo", "fo", Some("../foo"));
+        assert_diff_paths("fo", "foo", Some("../fo"));
+    }
+
+    #[test]
+    fn test_empty() {
+        assert_diff_paths("", "", Some(""));
+        assert_diff_paths("foo", "", Some("foo"));
+        assert_diff_paths("", "foo", Some(".."));
+    }
+
+    #[test]
+    fn test_relative() {
+        assert_diff_paths("../foo", "../bar", Some("../foo"));
+        assert_diff_paths("../foo", "../foo/bar/baz", Some("../.."));
+        assert_diff_paths("../foo/bar/baz", "../foo", Some("bar/baz"));
+
+        assert_diff_paths("foo/bar/baz", "foo", Some("bar/baz"));
+        assert_diff_paths("foo/bar/baz", "foo/bar", Some("baz"));
+        assert_diff_paths("foo/bar/baz", "foo/bar/baz", Some(""));
+        assert_diff_paths("foo/bar/baz", "foo/bar/baz/", Some(""));
+
+        assert_diff_paths("foo/bar/baz/", "foo", Some("bar/baz"));
+        assert_diff_paths("foo/bar/baz/", "foo/bar", Some("baz"));
+        assert_diff_paths("foo/bar/baz/", "foo/bar/baz", Some(""));
+        assert_diff_paths("foo/bar/baz/", "foo/bar/baz/", Some(""));
+
+        assert_diff_paths("foo/bar/baz", "foo/", Some("bar/baz"));
+        assert_diff_paths("foo/bar/baz", "foo/bar/", Some("baz"));
+        assert_diff_paths("foo/bar/baz", "foo/bar/baz", Some(""));
+    }
+
+    #[test]
+    fn test_current_directory() {
+        assert_diff_paths(".", "foo", Some("../."));
+        assert_diff_paths("foo", ".", Some("foo"));
+        assert_diff_paths("/foo", "/.", Some("foo"));
+    }
+
+    fn assert_diff_paths(path: &str, base: &str, expected: Option<&str>) {
+        assert_eq!(diff_paths(path, base), expected.map(|s| s.into()));
+    }
+}
diff --git a/lektord/Cargo.toml b/lektord/Cargo.toml
index 45650932cd635bb6f5cf6fc4cb57189c227bd8e6..b22fcff071228ca8474f7092991c16b7c736a4b6 100644
--- a/lektord/Cargo.toml
+++ b/lektord/Cargo.toml
@@ -4,6 +4,7 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
 description = "The lektord daemon"
 
 [dependencies]
diff --git a/lkt/Cargo.toml b/lkt/Cargo.toml
index e6caa3cfc02b8516a49d8add94dda50ca9a306d7..88681dfe93c97b66e6f91189a14c53db59b0eeba 100644
--- a/lkt/Cargo.toml
+++ b/lkt/Cargo.toml
@@ -4,6 +4,7 @@ version.workspace = true
 edition.workspace = true
 authors.workspace = true
 license.workspace = true
+rust-version.workspace = true
 description = "Simple command line utility to interact with the lektord daemon"
 
 [dependencies]