- Python 97%
- Shell 3%
| docs/images | ||
| legacy/server | ||
| src/music_maintenance | ||
| tests | ||
| .gitignore | ||
| CHANGELOG.md | ||
| install.sh | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
musicfix
musicfix is a safety-focused command-line toolkit for maintaining large,
folder-based music libraries on Linux. It can validate and repair FLAC files,
clean metadata and titles, normalize filenames, manage album and artist
artwork, quarantine unwanted files, and keep detailed logs, reports, backups,
and reversible run manifests.
The application is designed for both careful dry runs and explicit write operations. An incremental SQLite index avoids repeatedly processing unchanged music, while a configurable cleanup allow-list protects audio, image, lyrics, video, and custom file formats. Optional Apprise notifications provide service-neutral success and failure summaries for email, Telegram, Discord, Slack, ntfy, Gotify, and many other destinations.
Installation
Installer
Install the latest release from Forgejo:
curl -fsSL \
https://git.justdoit.network/Jan/musicfix/raw/branch/main/install.sh \
| bash
Install a specific tag:
curl -fsSL \
https://git.justdoit.network/Jan/musicfix/raw/branch/main/install.sh \
| bash -s -- v1.2.3
The installer:
- detects common Linux package managers
- installs Git, Python, pipx, FLAC and FFmpeg when required
- installs
musicfixwith pipx - installs the Python dependencies, including Apprise
- prints the Fish command needed when the pipx binary directory is not in
PATH
After installation:
musicfix --version
musicfix doctor
musicfix index rebuild
Manual installation
Clone the repository and install it with pipx:
git clone https://git.justdoit.network/Jan/musicfix.git
cd musicfix
pipx install .
To reinstall after updating the repository:
git pull
pipx install --force .
Apprise is included as a normal musicfix dependency and does not require a
separate installation.
Configuration
Show the current configuration:
musicfix config
Set the music-library path:
musicfix config /path/to/music
Set the interface language:
musicfix config --language de
musicfix config --language en
Enable or disable rainbow progress bars:
musicfix config --rainbow on
musicfix config --rainbow off
Set custom quarantine and log directories:
musicfix config --quarantine-dir /path/to/quarantine
musicfix config --logs-dir /path/to/logs
Reset custom paths to their defaults:
musicfix config --reset-quarantine-dir
musicfix config --reset-logs-dir
Validate the configuration and required directories:
musicfix config --check
Open the active configuration file directly in Nano:
musicfix config --edit
Configuration inspection and validation are read-only:
musicfix config
musicfix config --check
The configuration file is rewritten only when an actual setting is changed.
Cleanup allow-list
The cleanup step preserves only file extensions listed in
cleanup.keep_extensions. Matching is case-insensitive.
The default configuration preserves common audio, lyrics, image and video formats. To stop preserving a format, comment out or remove its entry. To keep another format, add its extension to the list.
Files whose extension is not present may be moved to quarantine during:
musicfix cleanup --write
musicfix all --write
A dry run shows what would be quarantined without changing the library:
musicfix cleanup
Example:
[cleanup]
# Extensions that cleanup must preserve. Matching is case-insensitive.
# Comment out an entry to stop preserving that format.
# Add another extension to preserve additional file types.
# Files not listed here may be moved to quarantine by cleanup --write.
keep_extensions = [
# Audio
".flac",
".mp3",
".m4a",
".mp4",
# Lyrics
".lrc",
".lyrics",
# Images
".jpg",
".jpeg",
".png",
".webp",
# Video
".avi",
".m2ts",
".m4v",
".mkv",
".mov",
".mpeg",
".mpg",
".mts",
".ts",
".vob",
".webm",
".wmv",
# Custom examples
# ".cue",
# ".nfo",
]
The configuration is stored at:
~/.config/musicfix/config.toml
The default state directory is:
~/.local/share/musicfix
Example configuration:
# musicfix configuration
# Generated and updated by `musicfix config`.
# TOML comments begin with # and may be edited freely.
[paths]
# Root directory of the music library. The directory must exist.
music_root = "/path/to/music"
# Directory for logs, reports, backups, run manifests and quarantine.
state_dir = "/home/user/.local/share/musicfix"
# Optional custom quarantine directory.
# Remove this line or run `musicfix config --reset-quarantine-dir`
# to use <state_dir>/quarantine.
quarantine_dir = "/path/to/quarantine"
# Optional custom log directory.
# Remove this line or run `musicfix config --reset-logs-dir`
# to use <state_dir>/logs.
logs_dir = "/path/to/logs"
[ui]
# Terminal language. Allowed values: "de" or "en".
language = "de"
# Rainbow progress bars. Allowed values: true or false.
# Set the NO_COLOR environment variable to disable all ANSI colors.
rainbow = true
[retention]
# Number of days to retain generated state.
# Use 0 to disable pruning for a category.
logs_days = 30
runs_days = 90
backups_days = 30
reports_days = 90
[library]
# Top-level library categories recognized by musicfix.
# Add, remove or rename entries to match the directory layout.
categories = [
"Anime",
"Filme und Serien",
"Gaming",
"Künstler",
"Youtube",
]
Configuration options
paths.music_root: existing root directory of the music librarypaths.state_dir: base directory for reports, backups, runs, logs and quarantinepaths.quarantine_dir: optional override for the quarantine directorypaths.logs_dir: optional override for the log directoryui.language:deorenui.rainbow:trueorfalseretention.*_days: retention period in days;0disables pruninglibrary.categories: top-level folders used to describe the library layoutnotifications.enabled: enable or disable Apprise notificationsnotifications.notify_on_success: notify after successful complete runsnotifications.notify_on_failure: notify after failed complete runsnotifications.urls: one or more Apprise service URLs
Commands
Inspection and diagnostics
musicfix doctor
musicfix status
musicfix config
musicfix config --check
musicfix scan
musicfix scan --no-tags
musicfix logs
musicfix logs --last
Library maintenance
musicfix flac-repair
musicfix title
musicfix update
musicfix files
musicfix covers
musicfix cover-online
musicfix placeholder-covers
musicfix artist-images
musicfix cleanup
Complete workflow
Preview every maintenance step:
musicfix all
Apply the proposed changes:
musicfix all --write
Revert and retention
Preview reverting the latest write run:
musicfix revert
Apply the revert:
musicfix revert --write
Preview expired logs, runs, backups, and reports:
musicfix prune
Delete expired state:
musicfix prune --write
Notification templates and compatibility
Notifications use a service-neutral structure that remains readable in email, Telegram, Discord, Slack, ntfy, Gotify, and plain-text destinations.
The default format is Markdown:
[notifications]
format = "markdown"
When an apprise:// or apprises:// gateway URL is configured, musicfix
sends directly to the Apprise API /notify/{key} endpoint. This preserves the
selected format value across the gateway instead of allowing an intermediate
client plugin to downgrade HTML or Markdown to plain text.
For HTML notifications, musicfix uses an email-client-safe layout with inline styles and presentation tables. This avoids collapsed labels and values in mail clients that strip modern CSS or semantic definition-list formatting.
Supported values are:
textfor maximum compatibilitymarkdownas the recommended default for mixed serviceshtmlmainly for email and other rich-content destinations
Templates avoid tables and complex nesting. Run notifications include mode,
run ID, runtime, library statistics, incremental change counts, log and
manifest paths, the installed version, and failure details when applicable.
Apprise notification types are set to success, failure, or info so
compatible services may apply their own icons, colors, or priorities.
Preview the exact configured template with realistic example data:
musicfix apprise test
Incremental maintenance
musicfix all uses a SQLite index to process only new, modified, deleted, or
otherwise affected library items.
Create the initial baseline after installation:
musicfix index rebuild
Inspect the current index and pending changes:
musicfix index status
Normal runs are incremental:
musicfix all
musicfix all --write
Force a complete pass when needed:
musicfix all --full
musicfix all --full --write
Delete the index and return to an uninitialized state:
musicfix index clear
The index is stored below the configured state directory as index.sqlite3.
Detection uses path, file size, and nanosecond modification time. Audio and
artwork changes select the affected album files. Directory-level artist-image
validation and cleanup still run globally because they validate library
structure rather than individual audio files.
The index is updated only after a successful write run. Dry runs never consume pending changes.
Optional Apprise notifications
musicfix all can send a compact summary through
Apprise after a successful or failed run.
Apprise is installed automatically as a musicfix dependency.
Test all configured notification targets without running library maintenance:
musicfix apprise test
The test uses every URL from [notifications].urls. It can also be used while
notifications.enabled is false, which makes it useful while preparing a
configuration before enabling automatic run notifications.
The generated configuration contains a commented example. Uncomment it and replace the service URL:
[notifications]
enabled = true
notify_on_success = true
notify_on_failure = true
format = "markdown"
urls = [
"tgram://BOT_TOKEN/CHAT_ID",
]
Multiple Apprise URLs may be configured:
urls = [
"tgram://BOT_TOKEN/CHAT_ID",
"discord://WEBHOOK_ID/WEBHOOK_TOKEN",
]
The notification includes:
- success or failure status
- dry-run or write mode
- run ID
- runtime
- audio-file and folder counts
- total library size
- log-file path
Notification failures are reported as warnings and never change the result of the music-maintenance run.
Apprise supports Telegram, Discord, Matrix, Gotify, ntfy, email and many other services. Service URL formats are documented in the Apprise wiki.
Safety model
All commands that can change the library use dry-run mode by default.
Changes require the explicit --write option. Write operations are protected by
a process lock, and suspiciously broad library roots are rejected. Each complete
write run records logs, reports, backups, and a JSON manifest for recovery.
Features
- detailed library scans with JSON reports
- FLAC metadata inspection and repair
- title and tag normalization
- filename normalization with collision checks
- embedded cover extraction
- online cover lookup with confidence scoring
- fallback cover generation
- artist image generation
- quarantine-based cleanup
- dry-run and explicit write modes
- write locking and path-safety checks
- timestamped logs and run manifests
- previewable revert operations
- configurable retention and pruning
- German and English terminal output
- live progress bars with optional rainbow rendering
Requirements
- Python 3.11 or newer
pipxflacmetaflacffmpegffprobe
Arch Linux, CachyOS, EndeavourOS, and Manjaro
sudo pacman -Syu --needed git python python-pipx flac ffmpeg
Debian, Ubuntu, Linux Mint, and Pop!_OS
sudo apt update
sudo apt install -y git python3 python3-venv pipx flac ffmpeg
Fedora
sudo dnf install -y git python3 pipx flac ffmpeg-free
License
MIT
