No description
  • Rust 98.5%
  • Nix 1.5%
Find a file
2026-09-05 15:11:30 +10:00
contrib feat(nix): package MUD and add a NixOS module 2026-09-05 15:08:32 +10:00
docs feat(protocol): declare version 1 and document the contract explicitly 2026-09-05 15:08:36 +10:00
nix fix(nix): scope the GStreamer plugin path to the package output 2026-09-05 15:08:36 +10:00
src feat(protocol): declare version 1 and document the contract explicitly 2026-09-05 15:08:36 +10:00
.gitignore init 2026-09-05 15:06:54 +10:00
Cargo.lock init 2026-09-05 15:06:54 +10:00
Cargo.toml chore: enforce a strict Clippy policy 2026-09-05 15:08:28 +10:00
flake.lock init 2026-09-05 15:06:54 +10:00
flake.nix feat(nix): package MUD and add a NixOS module 2026-09-05 15:08:32 +10:00
LICENSE init 2026-09-05 15:06:54 +10:00
README.md docs: lead the README with the product and trim internals 2026-09-05 15:11:30 +10:00

MUD

MUD is a music daemon for Linux. It owns the library, queue, playlists, and playback, and exposes all of it through a versioned JSON protocol over a per-user Unix socket. mudd is the daemon; mud is its command-line client, and any TUI, GUI, or script can speak the same protocol.

Out of the box MUD plays local files and Subsonic libraries through GStreamer, keeps the queue and playlists in SQLite so they survive restarts, publishes live events for library, queue, player, scanner, source, playlist, and artwork changes, and shows up on the session bus as an MPRIS player. It installs cleanly as a Nix package, a NixOS user service, or a plain systemd user unit.

What MUD can do today

Library: scan local roots with content-aware change detection, full-text search over titles, artists, albums, genres, and contributors, hierarchical browsing by artist, album, genre, year, and source, per-track details, and Subsonic sync with salted token auth, paginated discovery, and bounded parallel fetching. Metadata covers display and plural artists, album artists, dates, lyrics, work/movement, MusicBrainz and industry identifiers, and ReplayGain/R128 values.

Playback and queue: GStreamer playbin3 playback with play, pause, resume, stop, next, previous, seek, volume, mute, and repeat; a persistent, revision-safe queue with add, remove, move, replace, and clear; daemon-owned persistent playlists with full mutation operations and direct playlist playback; on-demand artwork with a bounded private cache.

Control: the mud CLI covers every protocol operation including search, browse, scan, source sync, queue and playlist editing, playback transport, and live watch event streams. Queue and playlist mutations accept an expected revision so concurrent GUI/TUI edits fail loudly instead of silently clobbering each other. The protocol is versioned (currently version 1, reported by hello), capability-described, length-prefixed JSON, and documented in docs/protocol.md.

Service integration: hardened systemd user unit, desktop entry, MPRIS adapter sharing the same protocol as every other client, XDG paths with strict 0700 / 0600 permissions, UID-checked socket peers, and a NixOS module with secret-file support for Subsonic passwords.

Quick start

nix develop
cargo build
cargo run --bin mudd
cargo run --bin mud -- status
cargo run --bin mud -- scan /path/to/music
cargo run --bin mud -- search "artist or title"
cargo run --bin mud -- play TRACK_UUID
cargo run --bin mud -- watch

mud subcommands cover status, search, browse, fields, details, scan, source list, source sync, artwork, play, play-entry, pause, resume, stop, next, previous, seek, volume, mute, unmute, queue, playlist, and watch. Run mud --help for the full tree.

The daemon uses $XDG_RUNTIME_DIR/mud/control.sock, $XDG_DATA_HOME/mud/library.sqlite3, $XDG_CONFIG_HOME/mud/config.toml, and $XDG_CACHE_HOME/mud/artwork/. Set MUD_GST_AUDIO_SINK=fakesink to exercise playback without an audio device.

Configuration

[local]
roots = ["/home/me/Music", "/mnt/archive/music"]
scan_on_start = true
scan_interval_seconds = 3600 # zero disables periodic reconciliation
watch = false                # optional inotify responsiveness hints
watch_debounce_seconds = 2
watch_max_directories = 8192
[[subsonic]]
name = "home"
url = "https://music.example.net" # server root, not the /rest path
username = "alice"
password_env = "MUD_SUBSONIC_PASSWORD_HOME" # kept in daemon memory only
sync_on_start = true
sync_interval_seconds = 3600
parallel_requests = 4

See contrib/config.toml. Manual mud scan and mud source sync home always work; scans are rejected while one is active.

Install

nix build .#mud
nix profile install .#mud

The flake provides a package wrapping mudd with its GStreamer plugins plus overlays.default, nixosModules.default, and nixosModules.mud. For NixOS, import the module and set services.mud:

services.mud = {
  enable = true;
  settings.local = {
    roots = [ "/home/you/Music" ];
    scan_on_start = true;
    scan_interval_seconds = 3600;
  };
};

Subsonic passwords stay out of the store: put only password_env in settings and point environmentFile at a secret file, or leave settings empty and set configFile to a runtime path. After rebuilding, check systemctl --user status mudd and journalctl --user -u mudd -f.

Without Nix, install the release binaries to ~/.local/bin and enable the example unit at contrib/systemd/mudd.service:

install -Dm755 target/release/mudd ~/.local/bin/mudd
install -Dm755 target/release/mud ~/.local/bin/mud
install -Dm644 contrib/systemd/mudd.service ~/.config/systemd/user/mudd.service
systemctl --user daemon-reload
systemctl --user enable --now mudd.service

A desktop entry lives at contrib/mud.desktop.

How it works

One nonblocking socket thread, one core thread owning state and SQLite writes, one GStreamer thread, and a bounded scanner pool communicate over bounded channels; there is no async runtime. The queue persists transactionally, events are bounded invalidation hints recoverable through snapshots, and artwork is fetched on demand rather than during scans.

Deliberately deferred: Jellyfin, Spotify and external engines, ReplayGain application, gapless playback and crossfade, MPD compatibility, shuffle, and stable cross-source artist identity.

License

MUD is licensed under the European Union Public Licence v. 1.2 (EUPL-1.2). See LICENSE.