A Spotify client for the terminal written in Rust, powered by Ratatui
spotatui is a terminal-based Spotify client written in Rust.
It provides a keyboard-driven interface for controlling Spotify playback,
browsing your library, searching for music, and more, all from your terminal.
Features include native streaming support, audio visualization, Discord Rich Presence,
and media key integration.
Windows 10/11 (64-bit) → Download spotatui-windows-x86_64.zip
Linux (Ubuntu, Arch, Fedora, etc.) → Download spotatui-linux-x86_64.tar.gz
Linux ARM64 (Raspberry Pi 4/5, ARM servers) → Download spotatui-linux-aarch64.tar.gz
Debian/Ubuntu (amd64) → Download .deb
Debian/Ubuntu (arm64) → Download .deb
macOS with Intel CPU → Download spotatui-macos-x86_64.tar.gz
macOS with Apple Silicon (M1/M2/M3) → Download spotatui-macos-aarch64.tar.gz
Or just run the one-line installer: curl -fsSL https://spotatui.com/install.sh | bash (macOS/Linux) or irm https://spotatui.com/install.ps1 | iex (Windows).
Checksums (.sha256) are optional and only needed if you want to verify the download.
The Linux, macOS, and Windows builds include the extra music sources (Local Files, Subsonic, Internet Radio, YouTube, Qobuz). The YouTube source needs yt-dlp installed (ffmpeg recommended).
To update use "spotatui update --install" or use your package manager of choice.
What's Changed
Tokyo Night color scheme by @istipisti113 in #436
fix(streaming): preserve external device handoffs by @shilicioo in #438
Adaptive theme from cover art by @LargeModGames in #439
refactor(core): split app.rs into a src/core/app/ module folder by @LargeModGames in #446
feat(visualizer): add cava visualizer by @LargeModGames in #449
test: add gui-substrate ratchet counters by @LargeModGames in #450
ci: add tui feature and headless leg by @LargeModGames in #451
ci: ratchet gates.count against merge-base by @LargeModGames in #454
refactor(core): move domain types out of tui by @LargeModGames in #455
fix: five small audit fixes by @LargeModGames in #456
refactor: split cover art into store and renderer by @LargeModGames in #457
readme redesign by @istipisti113 in #435
build: switch to published spotatui-librespot crates by @LargeModGames in #458
ci: fix event payload code injection by @LargeModGames in #459
refactor(core): move console I/O behind an onboarding trait by @LargeModGames in #460
refactor: split the crate into a lib and bin shims by @LargeModGames in #462
refactor(core): extract the tick driver from the runner by @LargeModGames in #463
fix(cli): retry player commands on the saved device by @LargeModGames in #465
fix(core): clear api_error instead of latching it by @LargeModGames in #467
feat(tui): fuzzy filter for the settings screen by @LargeModGames in #471
fix(streaming): restart the first track on Previous by @LargeModGames in #473
fix(streaming): queue slot survives track end by @LargeModGames in #474
refactor(app): group presentation state in App.view by @LargeModGames in #475
refactor(core): shared action vocabulary by @LargeModGames in #476
refactor(tui): route global keys through App::apply by @LargeModGames in #477
refactor(tui): route list handlers through App::apply by @LargeModGames in #480
ci(cd): auto release notes and direct download links by @LargeModGames in #481
ci: add Codecov coverage upload by @LargeModGames in #482
fix(dj): scratch dir fallback for unwritable home by @LargeModGames in #483
refactor(tui): route handler tail through App::apply by @LargeModGames in #484
feat(core): typed bootstrap onboarding requests by @LargeModGames in #485
refactor(runtime): extract native-streaming startup by @LargeModGames in #486
feat(sources): add Qobuz by @LargeModGames in #489
fix(core): run without a Spotify session by @LargeModGames in #495
refactor(core): rename AddFriendByUserId to AddFriendById by @LargeModGames in #500
fix(local): scan nested folders so a two-level music library is browsable by @alessandro-zanni in #499
docs: add alessandro-zanni as a contributor for code by @allcontributors[bot] in #501
fix(audio): stop two pump freezes, and enable the alternative sources on macOS by @alessandro-zanni in #498
fix(nix): bump nixpkgs past the crates.io 403 on crate downloads by @LargeModGames in #502
fix(queue): refuse a plugin's repeat while the queue slot owns playback by @LargeModGames in #503
feat(tui): offer what the source and session can do by @LargeModGames in #505
fix(auth): survive a startup 429 on /me and bind the OAuth listener before the browser opens by @LargeModGames in #506
refactor(tui): map every Action to its key surface by @LargeModGames in #508
refactor(app): privatize App fields and cursors by @LargeModGames in #509
fix(network): keep a 429 backoff off the serial pump by @LargeModGames in #510
fix(app): resolve the playing item through the owner by @LargeModGames in #511
fix(config): keep a symlinked config.yml, survive read-only by @LargeModGames in #514
fix(auth): put your own Spotify app first by @LargeModGames in #516
fix(network): gate Spotify transport on the owner by @LargeModGames in #515
fix(network): use the Development Mode endpoints by @LargeModGames in #518
chore(release): v0.42.0 by @LargeModGames in #520
fix(cd): list the .deb assets explicitly so the gui shim is not packaged by @LargeModGames in #521
New Contributors
@alessandro-zanni made their first contribution in #499
Full Changelog: v0.41.0...v0.42.0