Spotify in your terminal — a from-scratch TUI client with real audio visualizers
Project description
Spotify, entirely in your terminal. The official Spotify app never opens.
A from-scratch TUI client: hand-rolled terminal engine (no curses, no TUI
framework), its own OAuth PKCE flow, a raw stdlib Spotify Web API client, and
a real audio visualizer driven by an FFT of the PCM actually playing through
your speakers. Runtime dependencies: numpy and sounddevice. That's it.
┌ 1 now playing │ 2 search │ 3 playlists │ 4 library │ 5 queue │ 6 devices ┐
│ │
│ Midnight City │
│ M83 │
│ Hurry Up, We're Dreaming │
│ │
│ ▂▄▆█▇▅▃▂▁ ▁▂▄▆█▆▄▂ ▁▃▅▇█▇▅▃▁ ▂▄▆▇▆▄▂ ← live FFT of the audio │
│ ▁▃▅▇███▇▅▃▁▂▄▆███▆▄▂▁▃▅▇████▇▅▃▁▂▄▆██▆▄▂ │
│ ██████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
│ Midnight City M83 — Hurry Up, We're Dreaming │
│ ⏮ ⏸ ⏭ [shuffle] [repeat:off] 2:04 / 4:03 vol 80% │
└──────────────────────────────────────────────────────────────────────────┘
How it works
zpotify runs librespot as a subprocess that registers on your account as a Spotify Connect device — used strictly as an audio faucet. Control (search, playlists, play/pause/seek) goes through the Web API with a hand-written PKCE OAuth flow; the raw PCM flows through zpotify, which plays it on your system output and FFTs it for the visualizer. Everything you see and interact with is this codebase.
Requirements
- Spotify Premium (Spotify requirement for playback outside official apps)
- macOS with Homebrew:
brew install librespot - uv
- A free Spotify developer app — the first-run wizard walks you through it
Install & run
Install once as a global command (an isolated venv plus a zpotify shim in
~/.local/bin):
uv tool install zpotify # or: pipx install zpotify
Then from anywhere:
zpotify # first run launches the setup wizard
zpotify doctor # health check when something's off
zpotify auth # redo the Spotify login
Or try it without installing: uvx zpotify.
From source / development: uv tool install --editable /path/to/zpotify
(--editable links src/, so code changes apply without reinstalling; inside
the repo, uv run zpotify works too).
→ Full setup walkthrough, key reference, and troubleshooting: docs/USER_GUIDE.md
Keys
space play/pause · n/b next/prev · ,/. seek ±10s · +/- volume ·
/ floating search from anywhere (enter searches, / or esc closes) ·
1-7 views (7 = settings) · tab/shift+tab cycle tabs · j/k/h/l vim
navigation in views ·
enter play · a queue · s shuffle · r repeat · v visualizer · ? help ·
q quit — plus full mouse support (click rows/tabs/buttons, scroll wheel,
click the progress bar to seek).
Project layout
src/zpotify/
term/ terminal engine: raw mode, diff renderer, key/mouse decoding, widgets
auth.py OAuth 2.0 PKCE against accounts.spotify.com (stdlib only)
api.py Spotify Web API client (urllib), models in models.py
player/ librespot subprocess, PCM ring buffer → sounddevice, FFT analysis
ui/ event loop, seven views, player bar, overlays, theming
tests/ 140+ unit tests: input decoding, rendering, API parsing, audio, FFT
Development
uv run pytest -q # test suite
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zpotify-0.1.0.tar.gz.
File metadata
- Download URL: zpotify-0.1.0.tar.gz
- Upload date:
- Size: 52.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
010061d8f6647292e1b109226131c751a8d18450c6e84f149a42b07376bc2abc
|
|
| MD5 |
c033c2dad785843079957bada498f0f1
|
|
| BLAKE2b-256 |
e332357b29884719422f6f646acb1d002706dec6a90b9cbcef38e6d7c5bed67b
|
File details
Details for the file zpotify-0.1.0-py3-none-any.whl.
File metadata
- Download URL: zpotify-0.1.0-py3-none-any.whl
- Upload date:
- Size: 67.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d590bd3e88ce2c058bcba3d8791b0a7a47e7a7cc24167f9f9a700be30be6f0fe
|
|
| MD5 |
0c34338253cbb8db1b981f77862a6d44
|
|
| BLAKE2b-256 |
53e0a70e6957fb5333d531f97a8ec00ad99968e0a96693bc4c433985df7f1a13
|