Python 3.13 CLI for converting audio rips into a clean tagged library, browsing and playing it via a Textual TUI, and streaming it over Tailscale via a Subsonic-compatible HTTP server.
The lowest-friction way is uvx — it downloads, caches, and runs the latest published musickit in one step. No install step required:
uvx musickit --helpFor daily / persistent use (PATH-installed, no per-run network check):
uv tool install musickit
musickit --helpYou'll also need ffmpeg and ffprobe on $PATH for the convert pipeline:
brew install ffmpeg # macOS
sudo apt install ffmpeg # Debian / Ubuntuuvx musickit convert ./input ./output # convert
uvx musickit library audit ./output # audit
uvx musickit tui ./output # TUI
uvx musickit serve ./output # Subsonic server
uvx musickit playlist gen ./output --seed <track> --minutes 60 # auto-generate a mixThe TUI — artist browser on the left, drilled into an album, 48-band visualizer at the top:
Fullscreen visualizer (f):
The bundled browser UI tracks the same visual language — bordered panels with floating titles, same palette and KeyBar:
Internet radio mode (Stations panel + ICY metadata in the title):
More screenshots in the TUI guide and serve guide.
Full docs are at docs/ — built with MkDocs Material. Run them locally:
make docs-serve # http://127.0.0.1:8000Or jump straight to:
- Architecture — how all the pieces fit together (process model, data flow, audio subprocess, SQLite index, FFT visualizer)
- Quickstart — end-to-end walkthrough including iPhone + Tailscale + Amperfy
- musickit convert — codec / bitrate / enrichment matrix
- musickit library — audit rules + auto-fix + SQLite index
- musickit tui — TUI: local + radio + Subsonic-client + AirPlay
- musickit serve — Subsonic API + Tailscale + clients
- musickit playlist — auto-generated
.m3u8mixes anchored to a seed track - Desktop apps — Tauri + Electron generic Subsonic clients
- Mobile (Subsonic) — play:Sub / Amperfy / Symfonium / DSub / Tempo
- Edge cases — every weirdness encountered on real rips
- Roadmap — what's next
- Development — directory layout + test patterns + commit style
v0.13.0 · browser UI tracks the TUI's visual language (bordered panels, palette, keybinds for repeat / shuffle / volume / seek, slide-in help, command palette via Cmd/Ctrl+P, internet radio via the existing radio.toml) — ruff + mypy + pyright clean, full pytest suite green. Six top-level commands — convert, library, inspect, tui, serve, playlist — with library carrying the read / mutate / manage subcommands (tree, audit, fix, cover, cover-pick, retag, lyrics, index) and playlist carrying gen / list / show. The TUI ships local-library playback, internet radio, Subsonic-client mode (with persistent token-auth credentials), AirPlay output (incl. pause + volume routing), mDNS discovery, ReplayGain normalisation, a diacritic-folded /-filter, in-place tag editing (e for track / album-wide), auto-generated Mixes (g to create, browseable view of saved .m3u8), a 48-band FFT visualiser with f / v toggles, synced lyrics via l (parsed [mm:ss.xx] markers, active line bolded as playback advances), and click-to-seek on the progress bar. Audio decoder + sounddevice callback run in a separate process so UI work in the main interpreter can't stall playback. The server is OpenSubsonic-compatible (multipleGenres, transcodeOffset, songLyrics extensions), backs heart / star buttons with a persistent <root>/.musickit/stars.toml, returns sub-ms FTS5-ranked /search3 results, promotes LRC lyrics to synced: true, and is tested against Symfonium / Amperfy / play:Sub / Feishin clients on iOS / Android / desktop. A persistent SQLite library index at <root>/.musickit/index.db makes cold starts skip the filesystem walk + tag read; the filesystem watcher does per-album incremental rescans.
See LICENSE in the repo root.

