spotify-cli
A terminal-first Spotify control surface.
This started as a small experiment: mostly to learn Rust, partly out of boredom, slightly to smooth over a minor workflow annoyance, and a little bit because it felt easier than not doing it at all.
The result is a CLI that lets you control Spotify without switching context — and that can be composed, scripted, or wired into other tools however you like.
What this is
spotify-cli is a small, scriptable interface to Spotify that exposes common actions — playback, search, library, and playlist management — as plain shell commands.
It doesn’t try to replace Spotify’s UI, and it doesn’t assume how you want to use it. It just runs commands and prints output.
What this is for
This tool is intentionally flexible.
Some things you might use it for:
- Controlling Spotify without switching windows
- Driving playback from shell scripts
- Wiring commands into editors, window managers, or launchers
- Powering status bars or small widgets
- Chaining with tools like
jq,fzf, orawk - Automating playlists and library actions
- Treating Spotify as something you can script
You don’t need to be a “power user” to use it — but if you are one, it probably fits in nicely.
What this isn’t
This tool is deliberately modest in scope.
It is not:
- A replacement for Spotify’s desktop or mobile apps
- A full-featured Spotify client
- A background daemon or always-on service
- A UI or TUI with its own interaction model
- An attempt to reimplement Spotify features
- Opinionated about how you should use it
spotify-cli focuses on being a small, composable command-line tool.
If you want a UI, a long-running service, or an all-in-one solution, this probably isn’t it —
but you might be able to use this to help build one, and that’s kind of the point.
Disclaimer
This is provided as-is.
It is over-engineered relative to the problem it solves, and probably under-engineered in places where it could be more polished.
It exists primarily because it was interesting to build.
Use it if it’s useful to you.
Install
Local release build
Cargo install
Authentication
Spotify app setup (Client ID)
- Create a Spotify app at https://developer.spotify.com/dashboard
- Copy the Client ID
- Add a Redirect URI
Default:
http://127.0.0.1:8888/callback - Either keep the Client ID handy or export it as
SPOTIFY_CLIENT_ID
A note about Spotify APIs
Spotify’s APIs can be unpredictable.
Endpoints, scopes, and behavior sometimes change with little notice or explanation. Things that work today may stop working tomorrow, or behave slightly differently.
This tool does its best to adapt, but it ultimately sits on top of Spotify’s APIs and inherits their quirks.
Auth flow (PKCE OAuth — no client secret)
Notes:
auth loginprints an authorization URL and starts a local callback listener- Redirect URI can be overridden with
--redirect-uri <uri> - Tokens and metadata are cached (
metadata.jsonunder the cache root)
Global flags
These apply to all commands:
--jsonoutput machine-readable JSON-v,--verboseshow confirmations and now-playing info--width Ncap table column width--no-truncdisable truncation
Command reference
auth
player
|||
track
search
||||
album
artist
playlist
|||
device
system
||
help
hidden / internal
||
||
||
Design philosophy
This started with a small bit of friction: wanting to like tracks or add them to playlists without switching context while working.
Turning it into a CLI wasn’t a grand architectural choice — it was simply the most straightforward way to experiment, learn Rust, and end up with something reusable.
By keeping it CLI-first:
- Scripts can use it
- Editors and tools can shell out to it
- Output can be piped or parsed
- The tool stays small and understandable
No daemon. No custom UI. No assumptions about how it should be used.
Examples
Some common commands:
||||
Shell completions
Automation
Cache & settings
- Cache root:
~/.cache/spotify-cliOverride withSPOTIFY_CLI_CACHE_DIR - Settings:
spotify-cli cache country <code>spotify-cli cache user "<name>"
- For cached playlist and device completions, run:
Notes
playlist addadds the currently playing track to the chosen playlist- The playlist must be writable (owned or collaborative)
- Pins are local shortcuts, not Spotify objects
--usersearch prefers cached playlists and pins first
Future plans
This project is CLI-first, and that is unlikely to change.
Planned or likely:
-
Hardening the CLI surface
- More consistent
--jsonoutput - Clearer errors and exit codes
- Better stability at the command boundary
- Improve fuzzy logic
- More consistent
-
Small workflow refinements
- Improvements to interactive flows (
--pick, fuzzy search) - Quality-of-life tweaks based on real usage
- Improvements to interactive flows (
Possible, if there’s interest:
- Thin, optional integrations
- Example configs or reference wrappers
Not planned:
- A persistent daemon
- A full Spotify client or UI
- Reimplementing Spotify features
- Turning this into an ecosystem
Contributions
Contributions are welcome.
Bug fixes, small improvements, and quality-of-life changes are appreciated — especially if they improve reliability or clarity.
The project is intentionally CLI-first and relatively opinionated, so large architectural changes or major expansions may not be a good fit. If you’re unsure, opening an issue or discussion first is always fine.