Explo: ListenBrainz Recommendations Piped Into Navidrome, Jellyfin, Plex and MPD
Spotify's "Discover Weekly" for self-hosted music systems
At a glance
- What is it?
- Explo is a Go service that pulls weekly and daily playlists from ListenBrainz, tries to acquire the missing tracks through YouTube, Soulseek or Lidarr, tags them, and writes the result back as a playlist in your self-hosted music system. The idea is sound and the integration list is long, but the acquisition path is the part you have to accept before adopting it.
- Who is it for?
- Adopt Explo if you already run a Subsonic-compatible server or MPD, you have a ListenBrainz account with listening history, and you are comfortable with downloads arriving from YouTube or Soulseek rather than only from your own collection. Do not adopt it if your library is curated and you cannot tolerate mislabeled or duplicate files, or if you have no interest in running yt-dlp, FFmpeg and a Soulseek client alongside your media server.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap Explo fills between ListenBrainz and your own shelves
Self-hosted music servers solve playback and library management. They do not solve discovery. Once your collection stops growing, a Navidrome or Jellyfin instance becomes a well-organized archive of things you already chose. Spotify's Discover Weekly works because it sits on top of a recommendation engine fed by everyone's listening data; a personal server has no such engine and no catalogue to draw from.
Explo's answer is to borrow someone else's engine. It uses the ListenBrainz recommendation engine to retrieve personalized tracks, then imports them into your music library. The target user is specific: someone who already scrobbles to ListenBrainz, already runs one of the supported servers, and wants a recurring playlist that contains music they do not own yet. The README lists Weekly Exploration, Weekly Jams and Daily Jams as the three recommendation playlists it can fetch, which maps directly onto ListenBrainz's own playlist types rather than an Explo-invented format.
The second half of the problem is acquisition. A recommendation is useless if the track is not in your library, and self-hosters rarely have a legal storefront wired into their server. Explo's answer is to request playlist tracks from YouTube and Soulseek, or albums through Lidarr, then add metadata to downloaded tracks and create playlists in your music system. That is the whole product in one sentence, and it is also where every serious objection lives.
How a recommendation becomes a file on disk
The data flow implied by the README runs in four stages. First, Explo authenticates against ListenBrainz and pulls one of the three recommendation playlists. Second, it compares those tracks against what your music system already holds. Third, for anything missing, it dispatches an acquisition request: a track-level search against YouTube or Soulseek, or an album-level request through Lidarr when you would rather have the full release than a single file. Fourth, it writes metadata onto whatever arrives and creates a playlist in your music system, optionally keeping previous playlists for later listening.
The Go dependency list confirms the mechanism rather than just hinting at it. goutubedl is a Go wrapper for yt-dlp, so YouTube acquisition shells out to yt-dlp. ffmpeg-go wraps FFmpeg, which is what you would use to transcode or remux whatever yt-dlp returns into a format your server indexes. ytmusicapi is described in the acknowledgements as an unofficial YouTube Music API, so some lookups go through YouTube Music metadata rather than plain YouTube search. gocron provides internal cron scheduling, which is how the weekly and daily cadence is implemented without an external scheduler. notify handles outbound notifications, so a failed run can reach you somewhere other than the log.
Two design consequences follow. The service is stateful in the sense that it must track which playlists it created and which tracks it already fetched, otherwise a weekly run would re-download the same missing tracks. And it is a pipeline, not a library manager: Explo does not scan, index or serve your music, it hands finished files to a system that does.
Getting it running: Docker, Helm, and the .env file
The README points to a Quick Start wiki page for getting Explo running with docker, and the repository ships a Helm chart for Kubernetes. The chart install is given verbatim:
helm repo add explo https://lumepart.github.io/Explo && helm repo update helm install explo explo/explo --namespace explo --create-namespace
The chart's own README lives at charts/explo/README.md, which is where the values file keys would be documented. The repository layout also includes a visual/ directory holding the dashboard screenshot, which tells you the Web UI is a real surface and not a stub.
Configuration comes from environment variables and flags. The README links a Configuration Parameters wiki page described as an environment variable and flag reference, and godotenv is listed among the dependencies, so a .env file is a supported way to supply those values. The README does not reproduce the variable names, and I will not guess them. What the feature list implies you will need to configure: ListenBrainz credentials, at least one music system endpoint, at least one acquisition backend (YouTube, Soulseek or Lidarr), and a schedule for the playlist types you want.
The Web UI is where setup, scheduling and playlist import management happen, according to the feature list. For a first run, that means the practical sequence is install, open the UI, connect ListenBrainz and your server, pick which of Weekly Exploration, Weekly Jams or Daily Jams to schedule, and only then enable acquisition. Turning on downloads before the recommendation side is verified is the fastest way to fill a library with tracks you did not ask for.
Where the acquisition pipeline will bite you
The honest limitation is not a bug list. It is the nature of the sources. YouTube and Soulseek return files whose metadata, mastering and even artist attribution are whatever the uploader decided. Explo adds metadata to downloaded tracks, but tagging is a repair step, not a guarantee: it can normalize what it receives, it cannot verify that the audio matches the recommendation. A Weekly Exploration playlist built from YouTube rips will contain tracks that your server displays correctly and that sound wrong, and you will not find out until you listen.
The second limitation is that this is a downloader at heart, and downloaders fail in ways that are outside the project's control. yt-dlp breaks when YouTube changes its delivery; Soulseek depends on peers being online and sharing the track you want; Lidarr depends on your indexers having a release. Any of those can fail on a given week, and the README's System Notes page is explicitly framed as known issues and system-specific tips, which is the right place to check before assuming a failure is your misconfiguration.
The third is scope. Explo is the wrong tool if your goal is to discover music without acquiring it. If you want a playlist of recommendations that you audition on a streaming service and then buy, Explo's entire second half is dead weight, and you would be better served by reading the ListenBrainz playlists directly. Likewise, if your library is small and legally sourced, the acquisition half will produce more cleanup work than listening pleasure.
How Explo differs from Beets and from the servers themselves
The closest well-known tool in this space is Beets, the Python library manager. The difference in approach is fundamental. Beets works on files you already have: it queries MusicBrainz, rewrites tags, moves files into a directory scheme, and can fetch album art. It has no recommendation engine and no downloader in its core design; acquisition is left to plugins and to you. Explo starts from the other end. It decides what you should hear, then goes and gets it, then tags it. If you already run Beets, the two are complementary rather than competing: Explo produces candidate files, Beets is where you would enforce a consistent library. Explo's own metadata step is lighter than a Beets import, and it does not claim otherwise.
The other comparison is with the music servers Explo targets. Navidrome, Jellyfin, Plex, Emby, Airsonic and MPD all index and serve a library. None of them generate a weekly playlist from an external recommendation engine, and none of them download missing tracks. That is why Explo exists as a separate process with its own scheduler and its own Web UI, rather than as a plugin. The cost of that separation is another service to run, another set of credentials to store, and another thing that can silently stop working between weekly runs.
Maintenance cost, licensing and what to check before you commit
Explo is MIT licensed, which is permissive: you can run it, modify it and redistribute it, provided the copyright notice and permission notice are preserved. That covers Explo's own code. It does not cover what the pipeline pulls in. yt-dlp, FFmpeg, Lidarr, Soulseek clients and the music servers each carry their own licences and, in the case of downloading from YouTube or Soulseek, their own legal and terms-of-service questions. The README does not address any of that, and I am not going to pretend it does. If you are deploying this somewhere with a compliance review, the acquisition backends are the part that needs one.
Maintenance cost has two components. The application side looks routine: releases v1.1.2 in June 2026, v1.1.3 in July, and v1.2.0 in September, with the default branch named dev, which suggests active development and a branch you should probably not deploy from directly. The dependency side is the heavier one. yt-dlp needs frequent updates to keep working against YouTube, and a Go wrapper around it does not change that. FFmpeg needs to be present and recent enough for the formats involved. Lidarr and any Soulseek client are separate services with their own upgrade cycles. Budget for the pipeline, not just the container.
Before adopting, verify four things. Read the Configuration Parameters wiki page and confirm every required variable is one you can supply. Read System Notes for your specific server, since the README frames that page around system-specific tips. Check the Helm chart README if you are deploying to Kubernetes, because the install command above does not show what the chart configures by default. And decide the playlist retention question up front: the feature list says Explo can optionally keep previous playlists for later listening, and that option is the difference between a bad recommendation week being recoverable and being overwritten.
Editorial conclusion
Adopt Explo if you already run a Subsonic-compatible server or MPD, you have a ListenBrainz account with listening history, and you are comfortable with downloads arriving from YouTube or Soulseek rather than only from your own collection. Do not adopt it if your library is curated and you cannot tolerate mislabeled or duplicate files, or if you have no interest in running yt-dlp, FFmpeg and a Soulseek client alongside your media server. Before installing, read the Configuration Parameters and System Notes wiki pages, confirm which of the three playlist types you want scheduled, and decide whether previous playlists should be kept, because that setting determines whether a bad week of recommendations overwrites good ones.
Community notes