canticle

module
v1.18.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: GPL-3.0

README

Canticle

CI Release codecov OpenSSF Scorecard

Command line tool and webhook service to fetch synced lyrics from Musixmatch and save them as .lrc files.

Documentation

Full documentation is published at https://doxazo-net.github.io/canticle/:

  • Getting Started - onboarding guide: pick a path (one-shot, directory, or daemon) and get to working lyrics.
  • User Guide - webhook server, Docker/Unraid, the filesystem watcher, inspection commands.
  • CLI Reference - every subcommand and flag.
  • Configuration - env vars, TOML keys, token precedence, XDG paths.
  • Developer Guide - build, test, the quality gate, design decisions.

Install

macOS / Linuxbrew (Homebrew):

brew install doxazo-net/tap/canticle

Linux (.deb / .rpm / .apk): Download the appropriate package for your distro from the GitHub Releases page and install it with your package manager:

# Debian / Ubuntu
sudo apt install ./canticle_*.deb

# RHEL / Fedora / Rocky
sudo dnf install ./canticle_*.rpm

# Alpine
sudo apk add --allow-untrusted canticle_*.apk

The package installs the binary to /usr/local/bin/canticle, a systemd unit (or OpenRC script on Alpine), and an example config at /etc/mxlrcgo-svc/config.example.toml. It also creates a mxlrcgo-svc system user and a state directory at /var/lib/mxlrcgo-svc (mode 0750) that holds the SQLite database. The service does not start automatically on install.

After installing, copy the example config, set your token, and start the service:

sudo cp /etc/mxlrcgo-svc/config.example.toml /etc/mxlrcgo-svc/config.toml
# edit /etc/mxlrcgo-svc/config.toml and set [api] token = "YOUR_TOKEN"
sudo systemctl enable --now mxlrcgo-svc   # systemd
# or: sudo rc-update add mxlrcgo-svc default && sudo rc-service mxlrcgo-svc start  # Alpine OpenRC

The state directory and system user are preserved on package removal so the database survives upgrades and reinstalls. See the User Guide for service commands, log access, and data paths.

Tarballs / macOS / Windows: Versioned archives for all platforms are also available on the GitHub Releases page.

Build from source (requires Go 1.26.4+):

# go install resolves the module path from go.mod, which declares
# github.com/doxazo-net/canticle.
go install github.com/doxazo-net/canticle/cmd/mxlrcgo-svc@latest

This fork starts its release line at v1.0.0. The upstream fashni/mxlrc-go repository does not publish semver release tags, so v1.0.0 is reserved as the first canticle version.

Quickstart

# One song
canticle adele,hello

# Multiple songs into a custom output directory
canticle adele,hello "the killers,mr. brightside" -o some_directory

# Directory mode (recursive): writes each lyric file next to its audio file
canticle "Dream Theater"

# Lidarr webhook server
MUSIXMATCH_TOKEN=YOUR_TOKEN MXLRC_WEBHOOK_API_KEY=mxlrc_your_webhook_key \
  canticle serve --listen 127.0.0.1:3876

Directory mode overrides -o/--outdir; the output extension is .lrc for synced lyrics and .txt for unsynced lyrics or an instrumental marker. See the CLI Reference for every flag and the User Guide for Docker, Unraid, and webhook deployment.

Renamed an audio file and left its .lrc/.txt behind? canticle realign re-attaches orphaned lyric sidecars to their audio (dry-run by default; --yes to apply), and contrib/lidarr-rename-sidecars.sh is a Lidarr Custom Script that prevents the orphan at rename time. See Realign.

Token

A Musixmatch API token is required. Supply it via the --token CLI flag, the MUSIXMATCH_TOKEN environment variable, or a .env/config file, in that order of precedence (CLI > env > file). To get a token, follow steps 1 to 5 from the Spicetify guide. See Configuration for the full env-var and TOML surface.

Encrypted secrets

The Musixmatch token and the webhook API key can be stored encrypted at rest in the SQLite database (AES-256-GCM) instead of as plaintext in config and environment variables. It is opt-in and backward compatible: the encrypted store is the lowest-precedence source, so existing env/TOML setups are unchanged. Import the current plaintext with canticle secrets import, set one by name from stdin with canticle secrets set <name>, and list stored names (never values) with canticle secrets list. The 32-byte master key is auto-generated as a 0600 key file on first use (the universal zero-setup default on all platforms including Docker). Set MXLRC_MASTER_KEY to an optional base64-encoded override for key/data separation (recommended when the threat model includes whole-volume theft). Losing the key makes the encrypted secrets unrecoverable by design; the remedy is to re-import or re-set them with the original plaintext. See the Encrypted secrets guide.

Web UI access (serve mode)

The serve-mode browser UI is gated by a single admin account (session login, separate from the webhook API key). It is off by default; enable it with web_ui_enabled = true under [server].

First run is interactive. With no admin yet, every UI page redirects to /setup, an onboarding form that creates the admin account and (optionally) stores the Musixmatch token and webhook API key encrypted at rest. /setup is reachable only from loopback or a configured trusted network ([server.trusted_networks].cidrs), so a stranger on the network cannot claim the admin account. After the admin exists, /setup is closed.

For headless deployments (Docker), you can skip the interactive form by setting both MXLRC_WEBAUTH_ADMIN_USER and MXLRC_WEBAUTH_ADMIN_PASSWORD in the environment. On startup, if no admin exists yet, the daemon creates one from these values (password must be at least 8 characters). It is idempotent (an existing admin is never overwritten) and the password is never logged. Treat these as bootstrap-only credentials: after first run, sign in and rotate the password, then remove the variables from the environment.

TLS

TLS for the serve listener is off by default (plain HTTP), so deployments behind a TLS-terminating reverse proxy avoid double-encryption by leaving it disabled. Enable it under [server.tls] in one of two ways:

  • Bring-your-own certificate: set cert_file and key_file (both required together). The listener terminates TLS itself with a TLS 1.2 minimum. Env: MXLRC_TLS_CERT_FILE, MXLRC_TLS_KEY_FILE.
  • Self-signed bootstrap: set self_signed = true (mutually exclusive with cert_file/key_file). An ECDSA P-256 certificate (CN mxlrcgo-svc, ~365-day validity) is generated and persisted 0600 under <dir(db_path)>/tls/, and regenerated when missing or expired. Browsers show an untrusted-certificate prompt; this is intended for a LAN box, not public exposure. Env: MXLRC_TLS_SELF_SIGNED.

When TLS is on, the session cookie's Secure flag is set automatically. An optional redirect_http listen address (e.g. ":80", env MXLRC_TLS_REDIRECT_HTTP) runs a plain-HTTP listener that 301-redirects every request to the HTTPS address. A contradictory configuration (self_signed combined with a cert/key, or only one of cert_file/key_file) is a fatal startup error. ACME/Let's Encrypt is a planned follow-up.

Credits

  • Privacy Policy - what data leaves your machine during a lyrics lookup and what does not.
  • Code Signing Policy - SignPath attribution, team roles, and release approval process.

License

GPL-3.0. This project is a fork of fashni/mxlrc-go, which is MIT-licensed; the original MIT copyright and permission notice are retained in NOTICE.

Directories

Path Synopsis
cmd
genlib command
Command genlib generates a synthetic music library: tagged .mp3 files (ID3v2.4/UTF-8) with optional embedded USLT lyrics and optional .lrc sidecars, for load- and concurrency-testing canticle against a #131-style large library without touching real music.
Command genlib generates a synthetic music library: tagged .mp3 files (ID3v2.4/UTF-8) with optional embedded USLT lyrics and optional .lrc sidecars, for load- and concurrency-testing canticle against a #131-style large library without touching real music.
mxlrcgo-svc command
vocalcalib command
Command vocalcalib calibrates the sung-vocal-peak threshold used by the instrumental detector's three-gate decision (internal/detector.Instrumental).
Command vocalcalib calibrates the sung-vocal-peak threshold used by the instrumental detector's three-gate decision (internal/detector.Instrumental).
internal
app
backoff
Package backoff provides shared retry-delay formulas used by the worker, the durable queue, and the legacy fetch loop.
Package backoff provides shared retry-delay formulas used by the worker, the durable queue, and the legacy fetch loop.
circuit
Package circuit provides a concurrency-safe circuit breaker that models a single provider lane's rate-limit / throttle response.
Package circuit provides a concurrency-safe circuit breaker that models a single provider lane's rate-limit / throttle response.
db
detector
Package detector provides an optional audio-based instrumental detection sidecar.
Package detector provides an optional audio-based instrumental detection sidecar.
ffmpeg
Package ffmpeg resolves an ffmpeg executable for the verification and instrumental-detection sidecars, auto-provisioning a checksum-pinned static build when ffmpeg is neither configured nor on PATH.
Package ffmpeg resolves an ffmpeg executable for the verification and instrumental-detection sidecars, auto-provisioning a checksum-pinned static build when ffmpeg is neither configured nor on PATH.
identityrepair
Package identityrepair re-derives the stored artist identity of existing scan_results (and their coupled work_queue rows) by re-reading each file's tags, correcting rows ingested before the multi-value ID3v2.4 artist fix (issue #466).
Package identityrepair re-derives the stored artist identity of existing scan_results (and their coupled work_queue rows) by re-reading each file's tags, correcting rows ingested before the multi-value ID3v2.4 artist fix (issue #466).
instrumentalbackfill
Package instrumentalbackfill classifies work_queue rows the audio detector has never scored, writing an instrumental marker where it agrees.
Package instrumentalbackfill classifies work_queue rows the audio detector has never scored, writing an instrumental marker where it agrees.
instrumentalrecalib
Package instrumentalrecalib re-decides vocal-gate rejections from stored telemetry, without re-scanning audio.
Package instrumentalrecalib re-decides vocal-gate rejections from stored telemetry, without re-scanning audio.
langguard
Package langguard classifies and filters lyric text by Unicode script so a configured allowlist can reject unwanted-language results (e.g.
Package langguard classifies and filters lyric text by Unicode script so a configured allowlist can reject unwanted-language results (e.g.
lrcbackfill
Package lrcbackfill rewrites existing .lrc sidecars that carry compressed multi-timestamp lines into the expanded, one-cue-per-line form, backing up the pristine original alongside each rewrite.
Package lrcbackfill rewrites existing .lrc sidecars that carry compressed multi-timestamp lines into the expanded, one-cue-per-line form, backing up the pristine original alongside each rewrite.
lrcnormalize
Package lrcnormalize expands compressed multi-timestamp LRC lines into one cue per timestamp and classifies [key:value] ID-tag lines distinctly from real cues.
Package lrcnormalize expands compressed multi-timestamp LRC lines into one cue per timestamp and classifies [key:value] ID-tag lines distinctly from real cues.
pathutil
Package pathutil provides path-containment checks used to confine filesystem targets to configured roots.
Package pathutil provides path-containment checks used to confine filesystem targets to configured roots.
petitlyrics
Package petitlyrics implements a lyrics provider adapter for petitlyrics.com.
Package petitlyrics implements a lyrics provider adapter for petitlyrics.com.
prune
Package prune reconciles the durable work queue and scan-result cache against the filesystem: rows whose source audio file no longer exists on disk are deleted so a renamed/merged/deleted track cannot leave a permanently-failing or wedged row behind (#453).
Package prune reconciles the durable work queue and scan-result cache against the filesystem: rows whose source audio file no longer exists on disk are deleted so a renamed/merged/deleted track cannot leave a permanently-failing or wedged row behind (#453).
realign
Package realign re-attaches orphaned lyric sidecars (.lrc/.txt left behind when an audio file was renamed) to their audio via a four-tier confidence resolver: exact (provenance ISRC/MBID match), heuristic (single-candidate filesystem pairing gated by a name-similarity guard), ambiguous (multiple/zero candidates, reported and skipped), and conflict (contradictory signals or an existing destination, reported and skipped).
Package realign re-attaches orphaned lyric sidecars (.lrc/.txt left behind when an audio file was renamed) to their audio via a four-tier confidence resolver: exact (provenance ISRC/MBID match), heuristic (single-candidate filesystem pairing gated by a name-similarity guard), ambiguous (multiple/zero candidates, reported and skipped), and conflict (contradictory signals or an existing destination, reported and skipped).
reports
Package reports provides read-only, run-on-demand reports over the existing SQLite data (work_queue, scan_results, provider_outcomes).
Package reports provides read-only, run-on-demand reports over the existing SQLite data (work_queue, scan_results, provider_outcomes).
scanfail
Package scanfail persists files that consistently fail audio metadata read so the scanner can skip re-reading (and re-warning about) malformed files until they change on disk.
Package scanfail persists files that consistently fail audio metadata read so the scanner can skip re-reading (and re-warning about) malformed files until they change on disk.
secrets
Package secrets provides an encrypted-at-rest store for the small set of recoverable runtime secrets (the Musixmatch API token and the serve-mode webhook API key).
Package secrets provides an encrypted-at-rest store for the small set of recoverable runtime secrets (the Musixmatch API token and the serve-mode webhook API key).
servetls
Package servetls implements optional TLS for the serve-mode HTTP listener (issue #204, Area 4).
Package servetls implements optional TLS for the serve-mode HTTP listener (issue #204, Area 4).
testutil
Package testutil provides helpers for generating synthetic tagged audio files used by load/concurrency tests and the genlib tool.
Package testutil provides helpers for generating synthetic tagged audio files used by load/concurrency tests and the genlib tool.
trustnet
Package trustnet implements the client-IP resolution and trusted-network allowlist primitive shared by the serve-mode HTTP surface (issue #204, Area 2).
Package trustnet implements the client-IP resolution and trusted-network allowlist primitive shared by the serve-mode HTTP surface (issue #204, Area 2).
vocalcalib
Package vocalcalib re-thresholds stored per-track detector scores to calibrate the sung-vocal gate.
Package vocalcalib re-thresholds stored per-track detector scores to calibrate the sung-vocal gate.
watcher
Package watcher provides an optional filesystem watcher that triggers targeted library scans when files change under configured library roots.
Package watcher provides an optional filesystem watcher that triggers targeted library scans when files change under configured library roots.
web
Package web serves the serve-mode web UI: a fixed-sidebar shell with a Reports placeholder and a read-only Config view.
Package web serves the serve-mode web UI: a fixed-sidebar shell with a Reports placeholder and a read-only Config view.
webauth
Package webauth owns browser-based authentication for the serve-mode web UI: Argon2id password hashing, an admin user store, a server-side session store (raw tokens are hashed at rest), and a Service tying them together.
Package webauth owns browser-based authentication for the serve-mode web UI: Argon2id password hashing, an admin user store, a server-side session store (raw tokens are hashed at rest), and a Service tying them together.
web
static
Package static embeds the serve-mode web UI's static assets (compiled CSS and self-hosted fonts) into the binary at build time, so the single binary serves the UI offline without needing the web/static directory on disk.
Package static embeds the serve-mode web UI's static assets (compiled CSS and self-hosted fonts) into the binary at build time, so the single binary serves the UI offline without needing the web/static directory on disk.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL