Sync Lidarr metadata into the musefs SQLite store
Project description
lidarr-musefs
A Lidarr integration that syncs Lidarr's metadata into a musefs SQLite store, so a live musefs mount shows a re-tagged view of your library without Lidarr ever copying, moving, or rewriting backing audio bytes.
Lidarr stays the downloader, matcher, and metadata source; its destination tree becomes a placeholder of symlinks that exists only so Lidarr can track files. Point Navidrome, Plex, Jellyfin, or other consumers at the musefs mount instead.
How it fits together
The package installs two console scripts that plug into Lidarr's hooks:
musefs-lidarr-import(Import Using Script) — replaces Lidarr's own copy/move when it imports a download: it creates the destination entry as a symlink (or hardlink) to the downloaded file and fails closed — it never falls back to copying bytes.musefs-lidarr-sync(Custom Script notification) — fires after an import or rename: it queries Lidarr's API for the affected tracks' metadata (title, artist/albumartist, album, track/disc numbers, release date, MusicBrainz ids, genres), runsmusefs scanon the files to create/refresh their track rows (the structural columns only musefs can compute), and writes the tags into the store.
musefs's auto-refresh surfaces each sync at the mount with no remount. Both
scripts build on the shared python-musefs
store-contract library.
Install
Install the package — with its python-musefs dependency — into the
environment Lidarr uses to run custom scripts, so both scripts are on
Lidarr's PATH:
pip install lidarr-musefs
Or, from this repository (the working-tree library first — it is the local
source of the python-musefs dependency):
pip install -e contrib/python-musefs
pip install -e contrib/lidarr
You also need the musefs binary reachable by the sync script (see
MUSEFS_BIN below) and a musefs store/mount of your own — see the
main README.
Required Lidarr settings
- Settings -> Media Management -> Import Using Script: enabled.
- Import Script Path:
musefs-lidarr-import. - Metadata Provider -> Write Audio Tags:
Never. - File Date:
None. - Linux permission management: disabled.
Do not rely on Lidarr's built-in "Use Hardlinks instead of Copy" for this
workflow. Lidarr uses a hardlink-or-copy transfer mode internally, so a hardlink
failure can copy bytes. musefs-lidarr-import creates the destination entry
itself and fails closed.
musefs-lidarr-sync --doctor verifies these settings over the API (see
Doctor).
Lidarr Custom Script
Configure a Custom Script notification (Settings -> Connect):
- On Release Import: enabled.
- On Rename: enabled.
- Path:
musefs-lidarr-sync.
Test events exit successfully without touching files or the database.
TrackRetag events are skipped with a warning because they fire after Lidarr
writes tags.
Environment
Both scripts are configured through environment variables, set in the environment Lidarr launches scripts with.
Import script:
MUSEFS_LIDARR_LINK_MODE=symlink # default; use hardlink only if symlinks are unsuitable
Sync script:
MUSEFS_DB=/path/to/musefs.db # the musefs SQLite store (required)
MUSEFS_BIN=musefs # musefs executable; full path if not on PATH
MUSEFS_LIDARR_URL=http://localhost:8686
MUSEFS_LIDARR_API_KEY=your-api-key
MUSEFS_LIDARR_AUTOSCAN=1 # default; runs `musefs scan` before each sync
API keys are redacted from logs and errors.
Manual backfill
To sync every track file Lidarr already knows about (e.g. on first setup):
musefs-lidarr-sync --all
Manual backfill requires MUSEFS_LIDARR_URL and MUSEFS_LIDARR_API_KEY. It
runs the doctor preflight first (skip with --skip-lidarr-preflight), then
queries all Lidarr artists and syncs their known track files into the musefs
DB.
Doctor
To verify your Lidarr settings are musefs-safe:
musefs-lidarr-sync --doctor
The doctor checks Lidarr's API for:
writeAudioTags = nofileDate = nonesetPermissionsLinux = false
If MUSEFS_LIDARR_URL and MUSEFS_LIDARR_API_KEY are not configured, doctor
and sync fail because the integration cannot verify safe settings or build
complete per-track metadata.
Smoke test
- Build and install musefs.
- Install
python-musefsandlidarr-musefsinto the environment Lidarr uses for custom scripts. - Configure Import Using Script and Custom Script as described above.
- Import a small album.
- Confirm Lidarr's destination entry is a symlink by default.
- Run
musefs mount /tmp/mnt --db "$MUSEFS_DB". - Confirm the mount shows Lidarr metadata.
- Confirm the source file's bytes and mtime did not change.
Notes
- Tags are fully replaced with Lidarr's view on every sync (scanner-written binary tags always survive — see the external-writer contract).
- No art sync: the integration writes text tags only; any art
musefs scaningested from embedded pictures is preserved. - Schema version: the sync refuses to run if the DB's
user_versiondiffers from the version it targets — rebuild the store after upgrading musefs. - CI coverage: a fast smoke (real Lidarr exec path + mocked API) gates PRs, and a full real-instance download-client import e2e gates the Python releases — see CONTRIBUTING.md.
Tests
cd contrib/lidarr
python -m venv .venv && source .venv/bin/activate
pip install -e ../python-musefs # shared library (unpublished in-tree; install first)
pip install -e ".[test]"
python -m pytest # unit + integration (no Rust binary)
python -m pytest -m musefs_bin # path-matching gate vs the real `musefs` binary
The musefs_bin gate shells out to the real musefs binary, so build it first
from the repo root (cargo build). It is deselected from the default run and
skips cleanly if the binary is absent.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lidarr_musefs-1.0.0.tar.gz.
File metadata
- Download URL: lidarr_musefs-1.0.0.tar.gz
- Upload date:
- Size: 20.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff6656152ce1994fdb67412aea26249497b89a0410e6354da93088ec6ed7ad37
|
|
| MD5 |
9faf079df4add7eb2a8aa96866d4ae77
|
|
| BLAKE2b-256 |
01718ea7d5027cee204d7b0637ea6d9a3ed94364d4e403703763c5e24fc81a59
|
Provenance
The following attestation bundles were made for lidarr_musefs-1.0.0.tar.gz:
Publisher:
release-python.yml on Sohex/musefs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lidarr_musefs-1.0.0.tar.gz -
Subject digest:
ff6656152ce1994fdb67412aea26249497b89a0410e6354da93088ec6ed7ad37 - Sigstore transparency entry: 1805241280
- Sigstore integration time:
-
Permalink:
Sohex/musefs@de6f17129eadc8883ec9ac0ef0eb976466723068 -
Branch / Tag:
refs/tags/py-v1.0.0 - Owner: https://github.com/Sohex
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-python.yml@de6f17129eadc8883ec9ac0ef0eb976466723068 -
Trigger Event:
push
-
Statement type:
File details
Details for the file lidarr_musefs-1.0.0-py3-none-any.whl.
File metadata
- Download URL: lidarr_musefs-1.0.0-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5360de88dd7483b8a7c9ff32ddd338a25d54b82471f8592a982c743a5c725e97
|
|
| MD5 |
af403b8a552edd337d274bd06ee0e70e
|
|
| BLAKE2b-256 |
9f612a6137b24ce3d6c5c35a183941a1c9c4fdd83810dc14392f09e1296e75f3
|
Provenance
The following attestation bundles were made for lidarr_musefs-1.0.0-py3-none-any.whl:
Publisher:
release-python.yml on Sohex/musefs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lidarr_musefs-1.0.0-py3-none-any.whl -
Subject digest:
5360de88dd7483b8a7c9ff32ddd338a25d54b82471f8592a982c743a5c725e97 - Sigstore transparency entry: 1805241367
- Sigstore integration time:
-
Permalink:
Sohex/musefs@de6f17129eadc8883ec9ac0ef0eb976466723068 -
Branch / Tag:
refs/tags/py-v1.0.0 - Owner: https://github.com/Sohex
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-python.yml@de6f17129eadc8883ec9ac0ef0eb976466723068 -
Trigger Event:
push
-
Statement type: