sptfy is a command-line interface for Spotify.
The executable is sptfy; package-manager listings use spotify-cli.
brew install --cask open-cli-collective/tap/spotify-cli
winget install OpenCLICollective.spotify-cli
choco install spotify-cliAfter configuring the Open CLI Collective
APT or RPM repository,
install package spotify-cli; both formats provide /usr/bin/sptfy.
sudo apt install spotify-cli
sudo dnf install spotify-cliCreate a Spotify Development Mode application in the Spotify developer dashboard. The app owner must have Spotify Premium, and every dedicated test account must be added under the app's Users Management page. Note the client ID and add this exact redirect URI to the app's allowlist:
http://127.0.0.1/callback
Then authorize the CLI with the application's client ID. sptfy uses
Authorization Code with PKCE; it does not accept a client secret.
sptfy init --client-id YOUR_CLIENT_ID
sptfy meinit opens the authorization page when possible and stores the resulting
OAuth token in the configured credential backend. Setup messages and the
authorization URL go to stderr. me writes the authenticated identity and
granted scopes to stdout.
Authorization requests user-library-modify, user-library-read, and
user-read-private. Replace older credentials with sptfy init --overwrite.
For a prompt-free setup, supply --non-interactive. Use --no-browser to
open the printed URL yourself, or --auth-code-stdin to paste the complete
redirected URL back into the command.
The default credential backend is the native store for the current OS. Select
one explicitly with the global --backend flag: keychain (macOS), wincred
(Windows), secret-service (Linux), file, pass, op, op-connect, or
op-desktop. Selection precedence is flag, SPOTIFY_CLI_KEYRING_BACKEND,
config, then OS default. The encrypted file backend prompts for a passphrase
on a TTY; automation can set SPOTIFY_CLI_KEYRING_PASSPHRASE without placing
the OAuth credential itself in configuration or a runtime environment value.
Search tracks, albums, or artists with one Spotify query. Track and album output includes relationship IDs as breadcrumbs:
sptfy search track 'artist:"Björk"' --max 10
sptfy search album 'artist:"Björk"' --max 10
sptfy search artist 'Björk' --max 10ID | TRACK | ARTIST_IDS | ARTISTS | ALBUM_ID | ALBUM | DURATION
ID | ALBUM | ARTIST_IDS | ARTISTS | RELEASE_DATE | TOTAL_TRACKS
ID | ARTIST
Spotify development-mode search is limited to 10 results per page. When more
results exist, sptfy writes an opaque --next-page-token hint to stderr;
table rows remain on stdout. --id emits one resource ID per line and overrides
all other shape flags. --extended widens the default columns, --fields
replaces the selection, and --include-artwork adds Spotify-hosted image
dimensions and URLs. Resource search intentionally has no JSON mode.
To keep every result on one line, carriage returns, newlines, and the reserved
| separator sequence inside Spotify text are replaced with one space.
Get one track, album, or artist from a raw Spotify ID, matching Spotify URI, or
canonical open.spotify.com URL:
sptfy tracks get 11dFghVXANMlKmJXsNCbNl
sptfy albums get spotify:album:4aawyAB9vmqN3uQ7FjRGTy
sptfy artists get https://open.spotify.com/artist/0TnOYISbd1XYRBk9myaseg
sptfy albums tracks list spotify:album:4aawyAB9vmqN3uQ7FjRGTy
sptfy artists albums list https://open.spotify.com/artist/0TnOYISbd1XYRBk9myaseg11dFghVXANMlKmJXsNCbNl Cut To The Feeling
Artist IDs: 6sFIWsNpZYqfjUpaCgueju Artists: Carly Rae Jepsen
Album ID: 0tGPJ0bkWOUmH7MEOR77qc Album: Cut To The Feeling
Duration: 3:27
Catalog reads are text-only. --id emits only the fetched ID and overrides
--extended, --fields, and --include-artwork. Selected identity fields
remain in the stable identity header instead of being duplicated below it.
Relationship lists accept the same parent references. Normal output prints the
parent ID once before the child table; --id prints only child IDs.
Album-track pages support 1–50 results and expose no album or artwork columns.
Artist-album pages support 1–10 results and can include album artwork metadata.
Both default to 10 and write opaque continuation hints to stderr.
sptfy library tracks list
sptfy library tracks check 11dFghVXANMlKmJXsNCbNl spotify:track:0VjIjW4GlUZAMYd2vXMi3b
sptfy library tracks add https://open.spotify.com/track/11dFghVXANMlKmJXsNCbNl
sptfy library tracks remove 11dFghVXANMlKmJXsNCbNlLists default to 10 and allow 1–50 results. Normal output begins with
ADDED_AT; --id emits only track IDs. Checks emit
REFERENCE | ID | SAVED in first-seen unique order. Mutations validate and
deduplicate the complete batch before making requests, then print only
added<TAB>N or removed<TAB>N after every chunk succeeds.
sptfy library albums list
sptfy library albums check 4aawyAB9vmqN3uQ7FjRGTy spotify:album:2up3OPMp9Tb4dAKM2erWXQ
sptfy library albums add https://open.spotify.com/album/4aawyAB9vmqN3uQ7FjRGTy
sptfy library albums remove 4aawyAB9vmqN3uQ7FjRGTyLists default to 10 and allow 1–50 results. Normal output begins with
ADDED_AT and preserves every credited artist ID and name; --id emits only
album IDs. Album checks and mutations follow the same complete-batch
validation, first-seen deduplication, compact output, and 40-item request
chunking as saved tracks.
Requires Go 1.26 or newer.
make check
make snapshot
go run ./cmd/sptfy --helpShared CLI behavior and repository conventions come from
open-cli-collective/cli-common.
The live smoke uses a dedicated Spotify app/account and a temporary encrypted file store. It pins all supported OS state-directory variables under one temporary root and removes that root on exit; it never uses normal CLI state or an OS keychain. It is opt-in and is not part of ordinary CI:
SPOTIFY_CLI_LIVE=1 \
SPOTIFY_CLI_LIVE_DEDICATED_ACCOUNT=1 \
SPOTIFY_CLIENT_ID=your_client_id \
make live-smokeThe harness is interactive because Spotify authorization opens a browser. It exercises setup, identity, refresh, search/pagination shapes, catalog gets and relationship traversals, replacement, clear, and re-initialization without exporting the stored OAuth credential.
MIT