Cross-platform directory definition URL handler
  • Rust 92.1%
  • Nix 5.3%
  • PowerShell 2.6%
Find a file
2026-10-25 22:14:28 +00:00
.github fix: smoke and metadata 2026-10-15 21:19:05 +01:00
packaging/windows feat(windows): scheme global registration script 2026-09-28 09:42:13 +01:00
src feat(linux): linux.handler 2026-10-25 22:14:28 +00:00
.envrc initial commit 2026-09-19 18:38:04 +08:00
.gitignore initial commit 2026-09-19 18:38:04 +08:00
Cargo.lock feat(log): init 2026-10-25 21:51:56 +00:00
Cargo.toml feat(log): init 2026-10-25 21:51:56 +00:00
flake.lock initial commit 2026-09-19 18:38:04 +08:00
flake.nix fix(packaging): add desktop item to nix package output 2026-09-21 14:53:00 +01:00
LICENSE docs: add license and roadmap 2026-09-19 21:27:12 +08:00
README.md feat(linux): linux.handler 2026-10-25 22:14:28 +00:00

Cross-platform directory definitions xdd

xdd registers and resolves cross-platform directory definitions.

Configuration

On Linux, create $XDG_CONFIG_HOME/xdd/config.toml, or ~/.config/xdd/config.toml when XDG_CONFIG_HOME is not set. Windows also honours XDG_CONFIG_HOME; otherwise, run xdd config path to find the default location (normally %APPDATA%\xdd\config.toml):

[roots]
docs = "~/Documents"
projects = "~/Code/contrib"

[config]
compatible_colon_separator = false
log_level = "error"

[linux]
handler = "xdg-open"

Root paths must be absolute, optionally using ~ or ~/.... Root names may contain any characters except :.

URLs

A URL uses the following form:

xdd://root/relative/path

For example:

[Repo Path](xdd://projects/code/repo)

The path is resolved below the selected root. Percent encoding is supported, including for spaces and path components. .. is allowed only when the normalised path remains below the root. Query parameters and fragments are not supported yet.

Use xdd://root/ to refer to the root directory itself.

The legacy form xdd://root:relative/path is rejected by default. To accept it alongside slash-separated URLs, set compatible_colon_separator = true under [config]. This is due to some libraries will parse the part after : as port, which will result in an error for the use case of xdd.

Existing targets are checked against the root's real filesystem path, so symbolic links that resolve outside the root are rejected by default. A missing target still resolves lexically, without a filesystem containment check. This check is not a sandbox: the filesystem can change between checking and opening. To allow existing links to targets outside the root, add the following to the configuration:

[config]
restrict_to_root = false

Usage

Open a URL explicitly with:

xdd open 'xdd://projects/code/repo'

Resolve a URL to its absolute path without opening it:

xdd resolve 'xdd://projects/code/repo'

Inspect and edit the configuration with:

xdd config path
xdd config edit

xdd config edit uses EDITOR when set, otherwise edit.exe on Windows and vim on Unix. An empty EDITOR also selects the platform default.

List configured roots:

xdd roots list

Logging

Diagnostic logs are appended to $XDG_STATE_HOME/xdd/xdd.log. When XDG_STATE_HOME is not set, the fallback is ~/.local/state/xdd/xdd.log. The default config.log_level is error; it accepts off, error, warn, info, debug, or trace. Use --log-stderr to send logs to stderr instead, for example:

xdd --log-stderr resolve 'xdd://projects/code/repo'

Command results remain on stdout, so they can still be safely piped.

Create a link from an existing directory. The deepest matching root is chosen automatically:

xdd link ~/Atelier/prj/xdd
# xdd://projects/xdd

Use --root to select an alias explicitly, and --format with plain, markdown, typst, org, or latex to render a document link. Formatted links use the directory name as their label by default; --label overrides it.

Build

Install on Linux

Build and run the program with:

cargo build
xdd register

xdd register installs a user-level desktop entry and makes xdd the default handler for xdd:// URLs. It delegates the MIME association to xdg-mime. On systems where the relevant mimeapps.list is on a read-only filesystem, xdg-mime cannot write the association and does not return status 0, so xdd register cannot complete the registration. Use another method to write the desktop association in that environment, such as managing a writable mimeapps.list through the desktop environment or system configuration.

Install on Windows

Download and extract xdd-<version>-x86_64-pc-windows-msvc.zip, or build with cargo build --release. From the extracted directory, register the URL scheme for the current user with PowerShell:

powershell -ExecutionPolicy Bypass -File .\register.ps1 -ExePath .\xdd.exe

To register for all users, install the executable in a location accessible to all users and run this from an elevated PowerShell session:

powershell -ExecutionPolicy Bypass -File .\register.ps1 -ExePath .\xdd.exe -Global

Per-user registrations take precedence over the machine-wide one.

The registration stores the executable's absolute path; rerun the script if you move it. For a source build, use packaging/windows/register.ps1 -ExePath target/release/xdd.exe instead. Windows paths in TOML can be written as literal strings, for example docs = 'C:\Users\me\Documents'. xdd register currently works only on Linux.

Build with Nix

nix build github:js0ny/xdd

Adding the package to your environment.systemPackages will handle the URI scheme registration automatically.

Roadmap Before 1.0.0

  • Linux: Basic implementation on Linux
  • Windows: Implement on Windows, define a denied list of symbols, should be cross-platform
  • Linux: Configuration linux.handler, default to xdg-open
  • macOS: Implement, URL Scheme with a swift wrapper
  • CLI: subcommands config, roots, and link

License

GPL-3.0-or-later