A native desktop app for saving music from your own TIDAL account for offline listening: search‑first, art‑forward, and built for people who'd rather click than type.
Browse new arrivals and save any track for offline listening in one click.
Search anything, preview an artist in place, and save a whole discography for offline listening.
Waves is a from‑scratch, native desktop app for macOS, Windows, and Linux (Intel/AMD and Apple‑silicon/ARM). Its download engine descends from the proven Tidal‑DL‑NG project (continued by the community as Tidaler) and is maintained and improved here; see Standing on the shoulders of others for the full lineage.
A paid TIDAL plan is required. Waves saves from your own account, for your personal, non‑commercial use, and can only save what your account can play, up to HiRes Lossless / TIDAL MAX (24‑bit, 192 kHz) and Dolby Atmos where available.
- Search TIDAL and, when enabled, Apple Music from one bar. Pasted TIDAL links still open releases directly.
- Browse artist and album pages rich with cover art, quality badges, and dates you can sort and filter.
- Preview a full track (or an artist's top song) right inside the app before you save it.
- Save a track, an album, a playlist, a mix, a music video, or an artist's whole discography for offline listening, in one click.
- Pick exactly what a discography pulls in, and let Waves skip duplicate editions.
- Keep your TIDAL favorites close, however large your library grows.
- Follow everything in flight in a live, grouped queue that says what each one will actually sound like.
- Point Waves at your existing music library and see what you already own, badged right in the search results (new, experimental).
- Write Plex‑friendly tags (ReplayGain volume leveling included), and choose the explicit or clean version.
- Set up FFmpeg with one click, and optionally update Waves from inside the app.
- Keep provider-specific settings together. Apple Music search works without account setup; a cookies export unlocks AAC 256 and Atmos downloads, the setup wizard walks the full tier, and each provider card offers sign-out so you can switch accounts in place.
- Control Apple runtime setup from Settings. Deliberate Stop stays disconnected until Reconnect, user-managed services remain under your control, setup transfers are cancellable, and approved compatible managed updates retain rollback. Settings reports lite session observations separately from qualification; lite account admission remains pending native artifact approval.
- Run native on macOS, Windows, and Linux, at quality up to HiRes Lossless and Dolby Atmos.
Waves exists because of a chain of people who built and kept alive a tool a lot of us love. None of this is mine alone, and I want that to be the first thing you read, not a footnote.
- exislow created Tidal‑DL‑NG, the project everything here descends from. The original repository and account disappeared from GitHub, and as far as I know exislow never returned. The work was, and is, excellent. Thank you.
- After that, members of the community picked it up and kept it running. Some of those forks were taken down too, or wound down over time. Everyone who spent their own hours keeping this alive has my gratitude.
- Today it lives on as Tidaler, maintained by maya-doshi in their spare time. Waves began as a front end built directly on Tidaler, and its engine descends from Tidaler's (more on that below). Thank you, maya‑doshi, for keeping the lights on.
- And underneath TIDAL support sits tidalapi. Every TIDAL search, login, and saved track goes through it. Tidal‑DL‑NG began by wrapping it, and Tidaler and Waves still rely on it. Apple Music catalog search uses gamdl, whose client gets the public developer token from Apple Music's web app.
I'm a sucker for a beautiful graphical interface and tend to avoid the command line, but I seem to be in the minority, so the GUI side of tools like Tidaler doesn't get as much attention as the engine underneath. Waves is my way of giving back in a way that's genuinely useful (and, honestly, scratches my own itch): a polished, native GUI that doesn't touch what already works so well.
Waves is, and always will be, open source under the same license as Tidal‑DL‑NG and Tidaler (see License).
The single most important design rule of Waves: don't break what works, but never stop improving what can be. Both halves carry equal weight. The parts that already earned their keep in Tidal‑DL‑NG (and live on in Tidaler), TIDAL authentication, the multithreaded / multi‑chunk transfer engine, metadata tagging, quality handling, and configuration, descend from that upstream code, used as‑is wherever it still does its job well. The other half is just as deliberate: where that same code hit a real limit (a slow write to a network drive, a handshake storm pegging the CPU, a file that could be left half‑written), Waves improves it in place rather than leaving it be. Nothing is rewritten for its own sake, and nothing that meets a genuine problem is left untouched just because it came from upstream.
Concretely, Waves is a self‑contained UI package (waves/desktop/) that imports the engine's objects (Settings, Tidal, Download, search) and presents them through a Qt Quick interface. The engine code descends from the upstream Tidaler code, kept intact apart from a handful of small, surgical changes: a six‑line tweak so an in‑progress segment can be aborted mid‑chunk (Waves stops/quits instantly instead of waiting on a network read); an optional keep_album flag on the per‑track download so the "best of both" edition merge can tag a borrowed track under a chosen edition, together with writing that file's item id as the edition it was filed under rather than the one it streamed from, so a later save recognizes Waves' own file instead of writing a duplicate beside it; a hardened final move that swaps each finished file into place atomically, so an interrupted download can never leave a half‑written file in your library; pooled, reused connections so track segments stop paying a fresh encrypted handshake each (the fix for downloads pegging the CPU); a post‑download container repair so segmented tracks report their real length in strict players; large batched writes with retry, so a network drive sees a few big writes per track instead of hundreds of tiny ones; a rate‑limit pause that does what its settings say (after every N songs, for the set number of seconds), so a long run paces itself instead of asking TIDAL for too much at once; a playlist run that finishes what it can, skipping and counting a song TIDAL has taken down, waiting out a slow‑down request instead of failing the song, and carrying on past one song that goes wrong so the rest still arrive; and some defensive security hardening. Everything else is used as‑is.
To be just as plain about what is new: it's mine. I wrote the interface, the in-app updater, the managed ffmpeg install, and the packaging that ships it all as a signed desktop app, and that comes to about two thirds of the code in this repository. The rest is the engine that Tidal-DL-NG built and Tidaler carried forward, now maintained here, with the surgical improvements described above.
Current highlights from the unreleased section of CHANGELOG.md — the What Waves can do list above stays the stable feature record:
- 📦 Linux gains a Flatpak bundle (issue #316; install instructions live in Install).
- 🎛️ Settings has a Providers area: TIDAL session state plus an Apple Music section behind an enable switch, with search, setup and downloads arriving with the Apple Music rollout (issue #25).
- 🍎 Apple Music downloads land in the cookies tier: one click downloads an Apple album, playlist or song in AAC 256 (Dolby Atmos where asked and carried) through the normal queue, ownership and library machinery (issue #28).
- 🔊 With "Download Dolby Atmos" on, one click saves the stereo and Dolby Atmos versions as separate rows with their own ownership, progress, cancel and retry (issue #29).
- 🍎 Apple Music results open full pages: albums, artists and playlists render with tracks and artwork, pasted links resolve, and the preview button plays Apple's 30-second clip (issue #27).
Privacy is the foundation of this application. Waves collects nothing about you and has no way of knowing how the application is used: no telemetry, no analytics, no tracking. By default it makes no unsolicited outbound connections at all. It talks to each enabled provider only when you ask it to. There are four optional, user‑controlled exceptions, and none of them sends any of your data (each is a plain request that carries nothing about you):
- Clicking the FFmpeg button downloads a build from the open‑source FFmpeg host.
- Turning on automatic update checks (off by default) lets Waves ask the public GitHub releases page whether a newer version exists. The check only ever notifies you; nothing downloads until you choose to update.
- With lyrics enabled (off by default), each track you save also asks LRCLIB, an open community lyrics database, for that track's lyrics. The request carries only the track's artist, title, album and length, never anything about you or your account, and the "Prefer LRCLIB lyrics" switch in Settings turns it off.
- With the library scan's MusicBrainz check on (off by default), an album the scan cannot settle on its own is asked about at MusicBrainz, the open music encyclopedia. The request carries only that artist and album title, never anything about you or your account; requests go out at most one per second, and answers are cached locally.
Your credentials and your saved music stay on your machine, and on macOS and Linux the files Waves keeps for itself (your settings, your sign‑in and its caches) are created readable by your account only, not by every account on the machine. The same principle carries into the optional diagnostic logger below: nothing leaves your machine unless you export a report yourself.
Most apps make a bug report cost you your privacy: either describe the problem badly, or hand over a raw log full of your username, file paths, and account details. Waves closes that gap by redacting at the source. Identity information never reaches the log in the first place, so there is nothing to leak, whether you export a report or not.
- Off by default. Only warnings and errors are kept until you ask for more. In Settings → Diagnostics, turn on Verbose diagnostics, reproduce the problem, then click Export report for one text file ready to attach to an issue.
- Redacted at the source, not the export. Every log handler shares the same filter: usernames, file paths (every OS's forms), hostnames, IP/MAC addresses, emails, session tokens, and your TIDAL account id are replaced with placeholders the instant they would otherwise be written, verbose mode or not. There's no code path left that can write them to disk unredacted.
- A breadcrumb trail, always on. Waves keeps the last ~250 activity events in memory at no disk cost. The moment something goes wrong, that trail is written to the log automatically, so even a first-time crash arrives with the events that led up to it.
- An optional second layer. "Also hide titles and searches" additionally hashes what you searched for and any track, album, or artist names in the export, for anyone who'd rather not share that either.
The log lives at waves_dev.log, next to crash.log, in the Waves config folder (~/Library/Application Support/Waves on macOS, %APPDATA%\Waves on Windows, ~/.config/Waves on Linux). It's plain text; read it yourself any time you like. Clicking Export report doesn't send anything anywhere: it writes a separate, timestamped copy of that redacted data into the same folder, and Show file opens it in your file manager so you can move it, attach it, or send it yourself, wherever you want.
Logs are never transmitted off your device, unless you do it yourself.
- A paid TIDAL plan and a one‑time sign‑in (Waves walks you through the browser login on first launch and reuses the cached token afterwards).
- On macOS: macOS 12 Monterey or newer, on Intel and Apple silicon alike. The regular macOS builds need macOS 15 Sequoia; on Monterey through Sonoma, grab the
legacybuild instead (same app, an older bundled Qt). Homebrew and the in‑app updater pick the right one for your machine automatically. - On Linux: glibc 2.35 or newer (Ubuntu 22.04, Debian 12, Fedora 36 or anything newer) on x64, and glibc 2.39 or newer (Ubuntu 24.04, Debian 13, Fedora 40 or anything newer) on ARM64.
- Python 3.12, 3.13 or 3.14 (if running from source).
- FFmpeg is used for in‑app previews and a few conversions (e.g. some video / hi‑res cases). Waves can install it for you with one click (see above).
Grab the build for your platform from the latest release:
Releases ship from iamprivacy/Waves. This fork is a development line. It publishes no releases and holds no signing key. A fork build checks that repository for updates, so updating one replaces it with a build from iamprivacy/Waves, which has no Apple Music engine.
| OS | Intel / AMD (x64) | ARM (Apple silicon, etc.) |
|---|---|---|
| macOS 15+ | waves_macos-intel.zip |
waves_macos-apple-silicon.zip |
| macOS 12 through 14 | waves_macos-intel_legacy.zip |
waves_macos-apple-silicon_legacy.zip |
| Windows | waves_windows-x64.zip |
waves_windows-arm64.zip |
| Linux | waves_linux-x64.zip |
waves_linux-arm64.zip |
Unzip and run: on macOS drag waves.app to Applications (first launch needs a one‑time approval in System Settings, see the note below); on Windows run Waves.exe from the unzipped folder; on Linux run Waves from the unzipped folder. Every asset ships with a SHA‑256 checksum, and the release carries a signed SHA256SUMS manifest; the expected hash of every asset is printed on the release page, and Verify a download has the copyable steps.
macOS via Homebrew:
brew tap iamprivacy/waves
brew install --cask wavesWaves then knows it's Homebrew‑managed: the in‑app "Update & restart" button runs brew upgrade for you instead of downloading a new build itself.
Linux via AppImage: download waves_linux-x64.AppImage (or -arm64) from the release, mark it executable (chmod +x), and run it directly, no unzip, no install step. The in‑app updater keeps it current in place.
Linux via Flatpak: download waves_linux-x64.flatpak (or -arm64) from the release and install it:
flatpak install --user waves_linux-x64.flatpakThe bundle runs in a minimal sandbox (network, your home folder, GPU, audio) and never updates itself: the in‑app updater defers to flatpak update. Each .flatpak ships with a .sha256 sidecar covered by the release's signed SHA256SUMS manifest. A music library on a NAS or external drive needs a one‑time flatpak override --filesystem=...; see packaging/flatpak/README.md.
Prefer to run from source?
# from a clone of this repository
mise run install # pins Python/uv via mise.toml and the locked env (https://mise.jdx.dev)
mise run appWaves is GUI‑first and does not ship a command‑line interface. If you prefer the command line, use the upstream Tidaler project directly; it provides a maintained, CLI‑focused build (tidaler / tdn) of the same engine Waves is built on.
A note on macOS Gatekeeper: the builds are not yet Apple‑notarized, so macOS quarantines a freshly downloaded
waves.app. On first launch macOS shows a warning with no way to proceed; click Done, then go to System Settings → Privacy & Security, scroll down, and click Open Anyway next to the Waves entry. Confirm once and macOS remembers the choice from then on. (The old right‑click → Open shortcut no longer works on macOS 15 Sequoia and later.)A note on Windows SmartScreen: the builds are not yet code‑signed, so the first launch may show a Microsoft Defender SmartScreen prompt ("Windows protected your PC"). Click More info, then Run anyway. SmartScreen is a reputation check on new, unsigned software, not a malware detection; it fades on its own as a release accumulates clean installs.
Optional, for anyone who wants to check a download before the first launch. Every release carries two small files next to the builds: SHA256SUMS, one line per asset with its SHA‑256, and SHA256SUMS.sig, an Ed25519 signature over that file made with the Waves release key. The release page also prints each asset's hash in its Verify section. The public half of the release key, compiled into every build and checked by the in‑app updater before it installs anything:
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAcetggrhiqyMN5HsBCi/f2gJL75FVPOYGU/sd4dI5b+0=
-----END PUBLIC KEY-----
macOS or Linux, from a folder holding the zip, SHA256SUMS and SHA256SUMS.sig. The signature step needs OpenSSL 3: most current Linux distributions ship it, and on macOS the built-in openssl is LibreSSL, which cannot check it, so install OpenSSL 3 with brew install openssl@3 and run the third command with $(brew --prefix openssl@3)/bin/openssl in place of openssl:
printf '%s\n' '-----BEGIN PUBLIC KEY-----' 'MCowBQYDK2VwAyEAcetggrhiqyMN5HsBCi/f2gJL75FVPOYGU/sd4dI5b+0=' '-----END PUBLIC KEY-----' > waves-release.pem
base64 --decode < SHA256SUMS.sig > SHA256SUMS.sig.bin
openssl pkeyutl -verify -pubin -inkey waves-release.pem -rawin -in SHA256SUMS -sigfile SHA256SUMS.sig.bin
grep -v '^#' SHA256SUMS | tr -d '\r' | shasum -a 256 --ignore-missing -c -The third command must print Signature Verified Successfully and the last one <asset>: OK for the zip you downloaded (on a system without shasum, use sha256sum in its place). Any other output means the file does not match this release: delete it and download again.
Windows (PowerShell), from the same folder, with waves_windows-x64.zip replaced by the zip you downloaded:
(Get-FileHash .\waves_windows-x64.zip -Algorithm SHA256).Hash.ToLower()
Select-String -Path SHA256SUMS -Pattern waves_windows-x64.zipThe two hashes must be identical. To also check the signature on Windows, run the macOS/Linux commands in Git Bash, which ships OpenSSL.
Waves is open source, and that means you can check the code for yourself. If reading the source is not something you are capable of doing, you can upload the downloaded zip to VirusTotal and have it checked for viruses before you even extract it. Your privacy and security are important to me. Trust, but verify.
Waves is the first piece of software I've ever released. I've spent a couple of decades in and out of tech, most of it on the other side of the fence, beta‑testing, filing bug reports, and helping developers polish their games and software. Building something and putting my own name on it is new to me, and so is everything that comes after a release: the maintaining, the issue‑tracking, the keeping‑the‑lights‑on side of running a project. This is a side project built in spare time, so I won't always be fast, and I'm certain I'll get some things wrong as I learn the developer's half of all this.
None of that changes the welcome. If something breaks, behaves oddly, or just feels off, please open an issue, however small, and I'll genuinely read it and do my best to reply. Giving feedback is the thing I know how to do best, and I'm grateful to now be on the receiving end of it. Thank you for trying Waves.
Waves is only possible because of a lot of excellent open‑source work.
The project Waves descends from
- Tidaler by maya-doshi, the project Waves' engine descends from.
- Tidal‑DL‑NG by exislow (where it all started), and everyone who maintained it in between.
Core libraries (all credit to their authors and maintainers)
- tidalapi: the TIDAL API client at the heart of the engine
- PySide6 / Qt for Python: the GUI toolkit Waves is drawn with
- mutagen: audio metadata tagging
- python‑ffmpeg, m3u8, pycryptodome: streaming, playlist parsing, update signature verification
- requests, dataclasses‑json, pathvalidate
- Rich, Typer, coloredlogs: used by the inherited CLI
FFmpeg
- FFmpeg © the FFmpeg project, the tool itself.
- The one‑click installer downloads (never redistributes) prebuilt static binaries from:
- macOS & Linux (all architectures) → ffmpeg.martin-riedl.de (build scripts): native per‑architecture builds; the macOS builds are signed & notarized. Thank you, Martin Riedl.
- Windows → BtbN/FFmpeg‑Builds. Thank you, BtbN.
Lyrics
- LRCLIB: the open, community‑driven synced‑lyrics database Waves asks first, run free of charge, with no key and no strings attached. Thanks to everyone who contributes lyrics to it.
- LRCGet by tranxuanthang, who built both LRCGet and LRCLIB itself and keeps the service running for everyone. Waves' lyrics support follows the path LRCGet paved. Thank you.
Type
- JetBrains Mono is bundled for the interface, under the SIL Open Font License.
Icons
- Phosphor Icons: the interface glyphs (play, pause, download, search, and the rest) are bundled from Phosphor, under the MIT License.
If I've missed anyone, it's an oversight, not an intent. Please open an issue and I'll fix the credit.
Waves is licensed under the GNU Affero General Public License v3.0 (AGPL‑3.0), the same license as Tidal‑DL‑NG and Tidaler. See LICENSE for the full text. Because Waves is a derivative work, it stays AGPL‑3.0, and so must anything built on it.
Copyright (C) 2026 iamprivacy. Waves is free software: you can redistribute it and/or modify it under the terms of the AGPL‑3.0.
Waves is an independent project and is not affiliated with, endorsed by, or sponsored by TIDAL. TIDAL is a trademark of its owner, used here only to identify the service Waves works with.
Waves is a personal, non-commercial tool for your own TIDAL account, using your own credentials. It can only save what your account can already play: it cannot reach anything the account cannot reach, it does not remove or bypass any encryption or copy protection, and it is not a way around a subscription. If TIDAL will not serve a stream to your account, Waves cannot save it.
You are solely responsible for how you use it. Do not use it to infringe copyright or to reproduce, distribute, or pirate content. Your use may violate TIDAL's Terms of Service, and you accept that risk, including any consequences to your account.
The software is provided "as is", without warranty of any kind, and to the fullest extent permitted by law its developers and contributors accept no liability for any damages arising from it. See sections 15 and 16 of the AGPL-3.0. By using Waves you agree to indemnify and hold harmless its developers and contributors against any claim arising from your use of it or your breach of these terms.
Waves collects no information and its developer has no way of knowing how the application is used. That is a deliberate privacy design, not an excuse: anyone using Waves to infringe copyright does so in breach of these terms and without the developer's knowledge or consent.
Full terms: https://getwaves.dev/terms/. Questions reach the project through GitHub issues.
Please respect the artists and rights-holders whose work this plays.
Start with DEVELOPER.md for setup and validation, the domain map to find a feature and its tests, and the documentation index for provider rules and architecture decisions.
