{"id":45897006,"url":"https://github.com/naarvent/spotify-tui","last_synced_at":"2026-02-27T21:03:53.815Z","repository":{"id":321088127,"uuid":"1084430999","full_name":"naarvent/Spotify-TUI","owner":"naarvent","description":"A terminal-based Spotify client built with Python, Spotipy and Textual. It provides a keyboard-driven TUI for searching, browsing and controlling Spotify playback, viewing synced lyrics, managing playlists and devices, and more. It's inspired by Rigellute's \"spotify-tui\".","archived":false,"fork":false,"pushed_at":"2026-01-12T17:06:47.000Z","size":62,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-12T22:54:35.673Z","etag":null,"topics":["cli","english","hotkeys","keyboard","media-control","python","script","spotify","spotify-api","spotify-tui","spotipy","spotipy-api","spotipy-library","terminal","terminal-based"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/naarvent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-27T17:08:06.000Z","updated_at":"2026-01-12T17:07:23.000Z","dependencies_parsed_at":"2025-10-27T19:13:45.497Z","dependency_job_id":"40b059c1-082b-4d36-8c66-8c625dc0e8ef","html_url":"https://github.com/naarvent/Spotify-TUI","commit_stats":null,"previous_names":["naarvent/spotify-from-terminal","naarvent/spotify-tui"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/naarvent/Spotify-TUI","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naarvent%2FSpotify-TUI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naarvent%2FSpotify-TUI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naarvent%2FSpotify-TUI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naarvent%2FSpotify-TUI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/naarvent","download_url":"https://codeload.github.com/naarvent/Spotify-TUI/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naarvent%2FSpotify-TUI/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29913693,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T19:37:42.220Z","status":"ssl_error","status_checked_at":"2026-02-27T19:37:41.463Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","english","hotkeys","keyboard","media-control","python","script","spotify","spotify-api","spotify-tui","spotipy","spotipy-api","spotipy-library","terminal","terminal-based"],"created_at":"2026-02-27T21:03:52.119Z","updated_at":"2026-02-27T21:03:53.806Z","avatar_url":"https://github.com/naarvent.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spotify TUI — SPT (Python) 🎧🐍\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT) [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/) [![Issues](https://img.shields.io/github/issues/naarvent/Spotify-From-Terminal)](https://github.com/naarvent/Spotify-From-Terminal/issues) [![GitHub stars](https://img.shields.io/github/stars/naarvent/Spotify-From-Terminal?style=social)](https://github.com/naarvent/Spotify-From-Terminal/stargazers)\n\n---\n\n### [Demo on YouTube!](https://youtu.be/MJm7DcUdPUs)\n[![Watch the video](https://img.youtube.com/vi/MJm7DcUdPUs/maxresdefault.jpg)](https://youtu.be/MJm7DcUdPUs)\n\n---\n\n## Important: If the app gets stuck on startup, delete the OAuth cache file Documents/naarvent's projects/Spotify_TUI/.cache_spotify_token to force re-authentication.\n\n---\n\nA terminal-based Spotify client built with Python, Spotipy and Textual. It provides a keyboard-driven TUI for searching, browsing and controlling Spotify playback, viewing synced lyrics, managing playlists and devices, and more.\n\n---\n\n## Table of Contents 📚\n\n- [Summary 📝](#summary-)\n- [Features ✨](#features-)\n- [Requirements \u0026 Installation 🛠️](#requirements--installation-️)\n- [Environment \u0026 Credentials 🔐](#environment--credentials-)\n- [How it works (high level) ⚙️](#how-it-works-high-level-️)\n- [APIs \u0026 External Services 🌐](#apis--external-services-)\n- [Keybindings / Controls ⌨️](#keybindings--controls-️)\n- [Configuration \u0026 Cache 📂](#configuration--cache-)\n- [Troubleshooting \u0026 Notes 📝](#troubleshooting--notes-)\n- [License 📄](#license-)\n\n---\n\n## Summary 📝\n\n`spt` is a full-featured TUI for Spotify built using:\n\n- **Textual** for the terminal UI\n- **Spotipy** for the Spotify Web API\n- **Requests** for lyrics and metadata providers\n\nIt supports search, playback, playlists, devices, lyrics, multi-selection workflows, and rich UI panels.\n\n---\n\n## Features ✨\n\n- Full Spotify search (tracks, albums, artists, playlists)\n- Playback control: play / pause / next / previous / seek / shuffle / repeat\n- Synced LRC lyrics when available; plain lyric fallback\n- Multi-review / multi-add batch playlist operations\n- Playlist creation, import, and modification\n- Device selection and playback transfer\n- Real-time playback sync with progress bar\n- Persistent cache + config + OAuth token storage\n- Expandable / collapsible Library \u0026 Playlists panels via keyboard\n\n---\n\n## Requirements \u0026 Installation 🛠️\n\n**Recommended:** Python 3.10+\n\nInstall dependencies:\n\n```bash\npip install spotipy textual requests rich pyfiglet\n```\n\nRun the app:\n\n```bash\npython spt_tui.py\n```\n\n---\n\n## Environment \u0026 Credentials 🔐\n\n`spt` requires Spotify credentials (or it will prompt you to provide them on first run):\n\n- `SPOTIPY_CLIENT_ID`\n- `SPOTIPY_CLIENT_SECRET`\n- `SPOTIPY_REDIRECT_URI`\n\nIf not provided via environment variables, the app will prompt for them and can save them locally in `spt_config.json`.\n\nScopes include playback, playlists, library, and user data as defined in the script.\n\n---\n\n## How it works (high level) ⚙️\n\n- Textual builds a two-column TUI: Search/Library/Playlists (left) and Details/Results/Lyrics (right).\n- Spotipy handles authentication, tokens, and playback/playlist operations.\n- Lyrics are fetched using LRCLib and lyrics.ovh, parsed into synced or pseudo-synced lines.\n- A periodic task syncs playback state and updates the UI.\n- Keyboard shortcuts drive all navigation and actions.\n\n---\n\n## APIs \u0026 External Services 🌐\n\n- **Spotify Web API** — playback, search, library, playlists, devices\n- **LRCLib** — synced LRC lyrics\n- **lyrics.ovh** — plain lyric fallback\n\n---\n\n## Keybindings / Controls ⌨️\n\nBelow are the keybindings as defined in the application (`spt_tui.py`). Use these keys to navigate and control the TUI.\n\n### General / Navigation\n\n- `escape` — Menu\n- `ctrl+q` — Quit\n- `up` — Up\n- `down` — Down\n- `/` — Search (focus search input)\n\n- `left` — Move focus to the left column (sections, library, playlists). When a playlist/album/lyrics view is open in the right panel, pressing `Left` returns focus to the left column and effectively closes or exits the detailed right view so you can navigate other items.\n- `right` — Move focus to the right panel (details, track list, lyrics). From the left column select an item and press `Right` (or `Enter`) to open it in the right panel; the right key focuses that panel for interaction.\n\n### Main / Navigation\n\n- `Esc` — Return to main menu\n- `Ctrl+Q` — Quit\n- `↑ / ↓` — Move between sections and list items\n- `/` — Focus search input\n- `Enter` — Open / Play selected item\n\n### Open / Play / Playback\n\n- `enter` — Open/Play\n- `space` — Play/Pause\n- `n` — Next\n- `p` — Prev/Restart\n- `r` — Repeat (cycle: off → context → track)\n- `Ctrl+S` — Toggle shuffle\n- `c` — Queue (add track to queue)\n\n### Playback Controls\n\n- `Space` — Play / Pause\n- `n` — Next track\n- `p` — Previous / Restart\n- `r` — Cycle repeat (off → context → track)\n- `c` — Add selected track to Queue\n- `Ctrl+S` — Toggle shuffle\n- `- / +` — Volume down / up (uses configured seconds using \"\u003c\")\n- `Ctrl+Left / Ctrl+Right` — Seek back / Seek forward (uses configured seconds using \"\u003c\")\n- `m` — Mute / Unmute\n\n### Shuffle / Volume / Seek / Mute\n\n- `ctrl+s` — Toggle shuffle\n- `-` — Volume down (Vol -)\n- `+` — Volume up (Vol +)\n- `m` — Mute\n- `ctrl+left` — Seek back (uses configured seconds using \"\u003c\")\n- `ctrl+right` — Seek forward (uses configured seconds using \"\u003c\")\n- `\u003c` — Prompt seek settings\n\n### Devices \u0026 Settings\n\n- `d` — Open device manager (transfer playback)\n- `\u003c` — Open seek/volume settings\n\n### Devices, Help \u0026 Views\n\n- `d` — Manage devices\n- `?` — Help\n- `f1` — Help\n- `l` — Toggle lyrics\n- `ctrl+r` — Refresh\n- `ctrl+c` — Open Queue\n\n### Library \u0026 Playlist / Queue Management\n\n- `f` — Toggle Favorite (Like / Unlike selected track)\n- `Ctrl+Shift+P` — Add selected track(s) to a playlist\n- `Ctrl+D` — Delete (playlist or remove item)\n- `Ctrl+R` — Refresh / reload content\n- `Ctrl+C` — Open Queue view\n\n### Multi-Add / Selection Mode\n\n- `Ctrl+L` — Toggle Multi-Add mode\n- In Multi-Add: use movement keys and `Enter` to toggle selection\n- `Ctrl+A` — Confirm selection (when prompted / in multi-add flows)\n- `Ctrl+O` — Add all / confirm add-all action\n\n### Additional / Help / Misc\n\n- `?` or `F1` — Toggle Help view\n- `Left / Right` arrows — Move focus between left column and right panel\n- Log file: `Documents/naarvent's projects/Spotify_TUI/spt_py_textual_spotify.log`\n\n---\n\n## Configuration \u0026 Cache 📂\n\nDefault location for cache, config and logs (created under the user's Documents folder):\n\n```\nDocuments/naarvent's projects/Spotify_TUI/\n```\n\nFiles:\n\n- `spt_config.json` — saved credentials\n- `.cache_spotify_token` — OAuth token cache\n- `spt_py_textual_spotify.log` — log file (rotating)\n\n---\n\n## Search — prefixes \u0026 smart parsing 🔎\n\nThe app supports quick filters by starting the query with a prefix (case-insensitive). These are parsed by the search routine:\n\n- `/ART \u003cquery\u003e` — search artists\n- `/ALB \u003cquery\u003e` — search albums\n- `/TRK \u003cquery\u003e` — search tracks\n- `/PLY \u003cquery\u003e` — search playlists\n- `/PDC \u003cquery\u003e` — search podcasts\n- `/EPS \u003cquery\u003e` — search episodes from podcasts\n\n\nYou can also write natural queries (e.g., `FEEL.`)—the app applies smart parsing and multiple candidate queries to maximize relevant results.\n\n---\n\n## Lyrics — sources \u0026 behavior 🎵\n\n`spt` attempts to provide synced and plain lyrics using multiple external services and local caching:\n\n- LRCLib (`https://lrclib.net`) — primary source for synced LRC lyrics (fetches `.lrc` when available).\n- lyrics.ovh (`https://api.lyrics.ovh`) — fallback for plain lyrics when synced versions are not found.\n- Local lyrics cache stored under the same cache directory to avoid repeated network lookups.\n\nIf synced LRC lyrics are found, the app parses timestamps into a timeline and highlights the current line in sync with playback. If only plain lyrics are available, the app will generate a pseudo-timed timeline to display lines progressively.\n\nIf lyrics aren't showing, try `Ctrl+R` to refresh data or ensure the network and external services are reachable.\n\n---\n\n## Troubleshooting \u0026 Notes 📝\n\n- If playlists don't load: press `Ctrl+R` (Refresh).\n- Lyrics fall back to plain text if synced LRC is not available.\n- Device switching requires an active Spotify client/device.\n- Check `spt_py_textual_spotify.log` for detailed debug output.\n\n---\n\n## License 📄\n\nThis project is licensed under the MIT License — see the `LICENSE` file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnaarvent%2Fspotify-tui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnaarvent%2Fspotify-tui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnaarvent%2Fspotify-tui/lists"}