Spotidry is a deliberately minimal Spotify CLI for status bars, hotkeys, and quick playback control.
It prints the current track in a compact one-line format, lets you toggle the current song in your Liked Songs, and exposes the playback controls you need without turning your terminal into a full music client.
- Print the current Spotify status in a customizable format.
- Toggle the current track in your Liked Songs with a single command.
- Control playback with play/pause, next, and previous actions.
- Scroll long artist/title strings cleanly in narrow status bars.
- Reuse recent playback data to keep 1 Hz status lines responsive and avoid unnecessary Spotify requests.
Install from PyPI with uv:
uv tool install spotidry
spotidry --setupOr install with pip:
pip install --user spotidry
spotidry --setupSpotidry is tested on Linux across Python 3.10 through 3.14.
Run spotidry --setup to create the config file interactively. The command opens the Spotify Developer Dashboard and prompts you for the values it needs.
- Create a Spotify app at My Dashboard.
- Make sure the app has Web API enabled.
- Set a redirect URI such as
http://127.0.0.1:9999. - Paste the Client ID, Client Secret, and Redirect URI into the setup prompt.
If you prefer to create the config manually, write this file to ~/.config/spotidry/spotidry.yaml:
client_id: '<ID>'
client_secret: '<SECRET>'
redirect_uri: 'http://127.0.0.1:9999'
output_format: '{play_symbol} {artist_song} {liked_symbol}'
# Optional: scrolling for long titles (useful for 1 Hz status lines)
max_width: 30
scroll_speed: 0.5
scroll_gap: ' '
# Optional: reuse recent playback data between CLI invocations
status_cache_seconds: 5On the first normal run, Spotidry opens a browser window so you can authorize access to your Spotify account.
output_format supports these placeholders:
{artist}: artist name{song}: track title{artist_song}:"{artist} - {song}", including scrolling when enabled{play_symbol}: playback indicator (▶or⏸){liked_symbol}: liked indicator (❤or♡)
The default output format is:
{play_symbol} {artist_song} {liked_symbol}
status_cache_seconds controls how often Spotidry asks Spotify for fresh playback data. The default of 5 works well for 1 Hz status bars while keeping API traffic low.
- Increase it if your status line refreshes frequently and you still hit rate limits.
- Set it to
0to fetch fresh data on every invocation.
Recent playback data is cached at ~/.cache/spotidry/status_cache.json. If Spotify temporarily replies with 429 Too Many Requests, Spotidry can keep showing the most recent cached status instead of waiting on a long retry window.
Common commands:
spotidry
spotidry --save
spotidry --play
spotidry --next
spotidry --previous
spotidry --volume-show
spotidry --volume-up
spotidry --volume-down
spotidry --setupCLI help:
usage: spotidry [-h] [-v] [-s] [-S] [-p] [-n] [--previous] [--volume-show]
[--volume-up] [--volume-down]
Spotify CLI client
options:
-h, --help show this help message and exit
-v, --version show program's version number and exit
-s, --save toggle liked track status
-S, --setup setup spotidry configuration
-p, --play play/pause track
-n, --next play next track
--previous play previous track/skip to beginning of current track
--volume-show print current device volume
--volume-up increase current device volume by 10%
--volume-down decrease current device volume by 10%
The volume commands print only the current volume. They do not add volume to the default spotidry status line.
If you need to re-authorize Spotify, delete the auth cache at ~/.cache/spotidry.json and run Spotidry again. If you are upgrading from an older release, re-authorizing may be necessary for the new playback-state scope used by the volume commands.
Example for the popular .tmux config:
tmux_conf_theme_status_right='#(flock -n /tmp/spotidry.lock spotidry 2>/dev/null; sleep 1) #{prefix}#{pairing} #{?battery_status, #{battery_status},}#{?battery_bar, #{battery_bar},}#{?battery_percentage, #{battery_percentage},} , %R , %d %b | #{username}#{root} | #{hostname} 'This redraws once per second for smooth scrolling. With the default status_cache_seconds: 5, Spotify is still refreshed only about once every 5 seconds.
If you do not need 1 Hz scrolling, increase the shell sleep to reduce API traffic even further.
Add this module to ~/.config/polybar/config.ini:
[module/spotidry]
type = custom/script
exec = ~/.local/bin/spotidry
exec-if = test -f ~/.local/bin/spotidry
click-left = ~/.local/bin/spotidry --next 2> /dev/null
click-middle = ~/.local/bin/spotidry --save 2> /dev/null
click-right = ~/.local/bin/spotidry --play 2> /dev/null
interval = 1This uses interval = 1 for smooth scrolling. With the default cache settings, Spotify is still refreshed only about once every 5 seconds.
To reduce API traffic further, either raise status_cache_seconds or increase the Polybar interval.
Set up a local development environment:
git clone https://github.com/mikeboiko/spotidry.git
cd spotidry
uv sync --extra testThe repository pins the local development interpreter to Python 3.14 via .python-version, so uv will pick that version automatically when available.
Useful development commands:
uv run pytest -q
uv run basedpyright spotidry
uv run spotidry --helpGitHub Actions handles validation and publishing:
- Tests runs on every push, pull request, and manual dispatch.
- Publish to PyPI runs after a successful
Testsrun onmaster. - A release is only created when
spotidry/__init__.pychanges and the version is bumped.
Routine commits should leave spotidry/__init__.py and CHANGELOG.md alone. Update them together only when preparing an actual release.
When a release is triggered, GitHub Actions will:
- Create and push the matching Git tag.
- Build the source distribution and wheel.
- Validate the package with
twine check. - Create a GitHub Release with the built artifacts.
- Publish the package to PyPI.
Make sure the repository has a PYPI_API_TOKEN secret configured.
Issues and pull requests are welcome.

