Skip to content

Repository files navigation

Doppler Smart Playlists

A macOS app that uses a local LLM to generate themed playlists from your Doppler music library, then writes them back into Doppler so they sit next to your hand-curated ones.

Everything runs on your machine. Your library never leaves it — the only network calls are to your own LM Studio server and to MusicBrainz for artist genre tags.

The My Doppler tab, showing library stats and the MusicBrainz sync banner


For users

What it does

  • Reads your Doppler library directly and shows you what's in it — counts, recently added, most played, existing playlists.
  • Looks up every artist on MusicBrainz once to learn their genre tags, and caches the result locally.
  • Asks your local model for themed playlist concepts, then fills each one with tracks you actually own — the model only ever picks from a list of your real song titles, so it can't invent music you don't have.
  • Writes a finished playlist into Doppler as a native playlist, or exports it as a .m3u for any other player.

A generated playlist, after Add to Doppler, sitting in Doppler's own sidebar:

A generated playlist open in Doppler

Requirements

  • macOS 15.7 or later (Apple Silicon)
  • Doppler for macOS installed, with at least one song in its library
  • LM Studio running locally with a chat model loaded. Qwen 3 was used during development.
    • Set the model's context length to ≥ 8 K (16 K recommended). The per-theme prompts include your real song titles and won't fit in a 4 K window.
  • Xcode 26 or later to build — there's no pre-built download yet, see Installing below. The project uses an Icon Composer app icon and Xcode 26 build settings, so earlier versions won't open it. Xcode 26 itself runs on macOS 15.6+, so you don't need to upgrade past Sequoia to build.

Installing

Clone the repo and build it:

git clone https://github.com/jbartolozzi/Doppler-Smart-Playlists.git
cd Doppler-Smart-Playlists
./build.sh

That produces (and opens) build/Build/Products/Release/DopplerSmartPlaylists.app. Drag it to /Applications if you want to keep it.

Or open DopplerSmartPlaylists.xcodeproj in Xcode and hit ⌘R.

Signing: no configuration needed. The project ships without a development team, so macOS signs the app ad-hoc ("Sign to Run Locally") and the sandbox entitlements still apply. If you want a real signature — to notarize it, say — open the project in Xcode, go to Signing & Capabilities, and pick your own team.

First run

The Settings window opens automatically the first time. Set up two things:

  1. LLM tab — confirm the LM Studio base URL (default http://localhost:1234), pick your loaded model from the list, and hit Test Connection.
  2. Library tabChoose Library… and select your Library.dopplerdb bundle. It normally lives in ~/Library/Application Support/Doppler/. The picker opens there for you, with hidden files shown so you can navigate into ~/Library.

The Settings window

Then switch to My Doppler. The app immediately starts caching artist metadata from MusicBrainz. This takes roughly 1 second per artist — MusicBrainz rate-limits anonymous users, and the app respects that. A 140-artist library takes a couple of minutes. It only happens once; the results are cached on disk.

The Playlists tab unlocks when that finishes.

Generating playlists

  1. Go to Playlists, choose how many you want with the stepper (1–20, default 9), and hit Generate.
  2. Themes appear first, then each playlist fills in independently as the model works through them — you don't have to wait for all of them.
  3. Click any tile to open its tracklist. From there:
    • Add to Doppler — writes it into your library as a real Doppler playlist. Quit Doppler first (see below). Relaunch Doppler and it's there.
    • Export .m3u — saves an Extended M3U with paths relative to your music folder, so it works in any player.
    • Retry — if one playlist failed (the model returned something unparseable, say), this regenerates just that one, without touching the others.

Tracks the model named but the app couldn't find in your library are shown struck through, and are skipped on both write and export.

Things to know

  • Quit Doppler before Add to Doppler. The app refuses to write while Doppler is running, and tells you why: Doppler holds the database open and would overwrite the change when it quits. Export .m3u is read-only and works either way.
  • There's no automatic backup. The write is wrapped in a single transaction, so you'll never get half a playlist — but if you want to be careful, copy ~/Library/Application Support/Doppler/Library.dopplerdb somewhere safe first.
  • Generated playlists don't survive quitting. They live in memory until you add or export them. Anything already written into Doppler is a normal Doppler playlist and persists normally.
  • The app only ever reads your library until the moment you press Add to Doppler. Browsing, generating and exporting are all read-only.
  • Nothing is uploaded. Prompts go to your local LM Studio server. The only outbound requests are artist-name lookups to MusicBrainz during the initial sync.

Troubleshooting

Symptom Cause
Playlists tab is locked The MusicBrainz sync hasn't finished. Check the banner on My Doppler.
Generation fails immediately LM Studio isn't running, or no model is loaded. Re-run Test Connection in Settings.
Every playlist fails, or output is empty Model context is too small. Raise it to 8 K+ in LM Studio and regenerate.
Add to Doppler is refused Doppler is still running. Quit it fully and try again.
Lots of struck-through tracks The model drifted off the provided song list. Hit Retry on that playlist.
Something else Open the Debug Log (⌘⌥L) — every library, LLM and write operation is logged there.

Windows and shortcuts

  • My Doppler — library stats, recently added, most played, your existing playlists, sync banner.
  • Playlists — the generated grid.
  • Settings — ⌘, — LLM config, library picker, cache stats and reset.
  • Debug Log — ⌘⌥L — filterable in-app log, also mirrored to OSLog.

For developers

Building

# Debug build — the normal inner loop
xcodebuild -project DopplerSmartPlaylists.xcodeproj -scheme DopplerSmartPlaylists \
  -configuration Debug -destination 'platform=macOS' build

# Release build into ./build, then launch it
./build.sh

There are no tests, lint config, or package manifests. There are no third-party dependencies — the app uses only the system SQLite3 C API, SwiftUI, AppKit, Foundation and OSLog.

The Xcode target uses PBXFileSystemSynchronizedRootGroup, so any file added to DopplerSmartPlaylists/ is picked up automatically. Never hand-edit project.pbxproj to add sources.

Build settings worth knowing: MACOSX_DEPLOYMENT_TARGET = 15.7, SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor, SWIFT_APPROACHABLE_CONCURRENCY = YES, app sandbox on.

How it fits together

Doppler access is split in two on purpose. DopplerLibrary.swift is a read-only actor (SQLITE_OPEN_READONLY) that's safe to use while Doppler is running. DopplerLibraryWriter.swift is a separate read-write actor that refuses to open while Doppler is running and re-checks again immediately before writing. Keeping them separate is what makes the dangerous surface obvious — don't merge them.

Generation is two-pass (ShowcaseGenerator.swift): one small call for N themes, then one parallel call per theme that ships only that theme's artists along with their real song titles. This exists because model context is usually tight, and because giving the model actual titles took the library-match rate from ~19 % to ~100 %.

The sandbox (DopplerSmartPlaylists.entitlements) means library access runs through an NSOpenPanel grant persisted as a security-scoped bookmark — see DopplerLibraryLocation.swift.

Everything else:

The "Playlists" tab is called Showcase throughout the code — it's the original name, kept to avoid churn.

CLAUDE.md has the deep detail: Doppler's Core Data schema and the exact write recipe, the EBMK bookmark format used for .m3u export, the artist-name canonicalization contract, and the LM Studio quirks that are easy to rediscover the hard way. Read it before changing the write path or the prompts.

License

MIT.

This is an unofficial third-party tool. It isn't affiliated with or endorsed by Brushed Type, the makers of Doppler. It writes directly to Doppler's database, which is not a documented or supported interface — see the warning above about backing up first.

About

A Helper tool to build playlists for Doppler music player using locally hosted LLMs from LM Studio

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages