Skip to main content

A boring Spotify CLI client

Project description

Spotidry

Tests Publish to PyPI PyPI version Python 3.10+

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.

Spotidry demo

What it does well

  • 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.

Installation

Install from PyPI with uv:

uv tool install spotidry
spotidry --setup

Or install with pip:

pip install --user spotidry
spotidry --setup

Spotidry is tested on Linux across Python 3.10 through 3.14.

Spotify setup

Run spotidry --setup to create the config file interactively. The command opens the Spotify Developer Dashboard and prompts you for the values it needs.

  1. Create a Spotify app at My Dashboard.
  2. Make sure the app has Web API enabled.
  3. Set a redirect URI such as http://127.0.0.1:9999.
  4. 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: 5

On the first normal run, Spotidry opens a browser window so you can authorize access to your Spotify account.

Configuration

Output placeholders

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}

Caching and rate limits

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 0 to 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.

Usage

Common commands:

spotidry
spotidry --save
spotidry --play
spotidry --next
spotidry --previous
spotidry --volume-show
spotidry --volume-up
spotidry --volume-down
spotidry --setup

CLI 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.

Tmux integration

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.

Polybar integration

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 = 1

This 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.

Polybar screenshot

Development

Set up a local development environment:

git clone https://github.com/mikeboiko/spotidry.git
cd spotidry
uv sync --extra test

The 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 --help

Release automation

GitHub Actions handles validation and publishing:

  • Tests runs on every push, pull request, and manual dispatch.
  • Publish to PyPI runs after a successful Tests run on master.
  • A release is only created when spotidry/__init__.py changes 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:

  1. Create and push the matching Git tag.
  2. Build the source distribution and wheel.
  3. Validate the package with twine check.
  4. Create a GitHub Release with the built artifacts.
  5. Publish the package to PyPI.

Make sure the repository has a PYPI_API_TOKEN secret configured.

Contributing

Issues and pull requests are welcome.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spotidry-0.0.12.tar.gz (42.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spotidry-0.0.12-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file spotidry-0.0.12.tar.gz.

File metadata

  • Download URL: spotidry-0.0.12.tar.gz
  • Upload date:
  • Size: 42.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for spotidry-0.0.12.tar.gz
Algorithm Hash digest
SHA256 1bce581943d3ae136015d49019f9eaf81b0d190c355495351653396f061c7f93
MD5 697cbcf496bb6650a8b4d5f7a8c5b7ab
BLAKE2b-256 d16c04a6a3ee257ddb519746e7311135841506e85378affb6f7ef39b95b2f90b

See more details on using hashes here.

File details

Details for the file spotidry-0.0.12-py3-none-any.whl.

File metadata

  • Download URL: spotidry-0.0.12-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for spotidry-0.0.12-py3-none-any.whl
Algorithm Hash digest
SHA256 e3b3a4ed2c6f3d313f9e35a6f7065d617e4053ccb428427c626c9269bdfe95ab
MD5 638d1c2716c17b5801869598ac1e310c
BLAKE2b-256 2b1a8973581f9944f24f65af2f41a36ad9c5ee5cba318dfd27e44ad79f46e4ab

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page