Skip to content

allcapsjoe/track-operator

Repository files navigation

Track Operator

A Python terminal UI (TUI) for exploring your Spotify listening data. Built with Rich, Spotipy, and questionary — runs entirely in your terminal with arrow-key navigation, live animations, themed colors, and direct Spotify playback control.


Table of Contents


What It Does

track-operator is a terminal application — launch it, log in with Spotify once, and get an interactive menu with:

  • Your top tracks and top artists across three time windows
  • Your recent listening history
  • Playlist diffing — compare two playlists side by side
  • Live Now Playing screen with a progress bar and full transport controls (play/pause/skip/volume/shuffle/repeat), plus a Matrix rain backdrop mode
  • A Matrix digital rain easter egg with live controls

Prerequisites

To use Track Operator, you need a Spotify Developer App. It takes about 2 minutes to set up:

  1. Log in to the Spotify Developer Dashboard.
  2. Click "Create App":
    • App name: Track Operator (or anything you like)
    • App description: Personal Spotify TUI
    • Redirect URI: http://127.0.0.1:8888/callback (This is critical for local authentication)
  3. Select Web API as the API you are using.
  4. Save the app.
  5. Click "Settings" on your new app to find your Client ID and Client Secret.

Installation & Setup

git clone https://github.com/allcapsjoe/track-operator.git
cd track-operator

# Install the package
pip install -e .

# Run the app
trackop

Automatic Configuration

On your first run, trackop will detect that you haven't configured your credentials yet. It will launch an interactive wizard in your terminal to help you save your Client ID and Client Secret to a .env file automatically.

Manual Configuration

If you prefer to do it yourself, create a .env file in the project root:

CLIENT_ID=your_client_id_here
CLIENT_SECRET=your_client_secret_here
REDIRECT_URI=http://127.0.0.1:8888/callback

Theme and transitions — config.toml

config.toml in the project root controls visual settings:

[palette]
theme = "phosphor_green"   # options: phosphor_green | amber | red_alert

[transitions]
on_boot        = "matrix_rain"   # animation played at startup
on_menu_select = "none"
on_results     = "none"
on_exit        = "none"

All settings are optional — defaults are used if the file is missing or incomplete.


Running

# If installed via pip install -e .
trackop

# Or directly
python -m spotify_tui

On first run, your browser will open a Spotify authorization page. Approve it and the app will continue. Subsequent runs skip this step.


Features

Top Tracks

Fetch your most-played tracks for Last 4 Weeks, Last 6 Months, or All Time. Choose how many (1–50). Export the list as .txt, .md, or .json.

Top Artists

Same as Top Tracks but for artists. Shows each artist's top genres and a popularity bar. Export supported.

Recent Plays

Your listening history for the past week, month, or year. Paginated so it goes beyond the 50-track API limit. Export supported.

Now Playing (requires Spotify Premium for controls)

Live polling view (updates every ~1.5s). Shows:

  • Track name, artists, album
  • Progress bar with elapsed / total time
  • Shuffle state, repeat mode, active device name, volume

Key controls while in this view:

Key Action
p Play / pause
n Next track
b Previous track
+ Volume +5%
- Volume -5%
s Toggle shuffle
r Cycle repeat (off → context → track)
g Toggle Matrix rain backdrop
q or ESC Exit

Rain mode (g): fills the terminal with Matrix rain, with the Now Playing panel centered and fixed. The rain palette automatically matches your app theme (green / amber / red). All transport controls remain active while rain is running.

Playback controls (play, pause, skip, volume, shuffle, repeat) require Spotify Premium. Reading the current track works on free accounts.

Audio Features

Pulls your top tracks and fetches audio feature data from the Spotify API. Displays a table with BPM (tempo), key/mode, energy, valence, and danceability — plus an averages row.

Note: Spotify restricted the audio features API for new developer apps in late 2024. If you see a 403 error on this screen, your app does not have access to this endpoint. See developer.spotify.com/blog/2024-11-27-changes-to-the-web-api.

Playlist Diff

Pick two of your playlists. Renders a three-column table: tracks only in A, tracks shared by both, tracks only in B.

Playlist BPM

  1. Pick any of your playlists
  2. See all tracks sorted by BPM (tempo), with an energy bar per track
  3. Optionally filter by a BPM range (e.g. 120–140)
  4. Preview the filtered list
  5. Optionally save those tracks as a brand-new private Spotify playlist — named by you

Note: Also affected by the Spotify audio features API restriction described above.

Playlist Selector (Diff + BPM)

Both Playlist screens use a shared selector with:

  • Sort options: Spotify order, A→Z, Z→A, Most tracks, Fewest tracks
  • Type-ahead autocomplete: start typing any part of the name to filter the list instantly

Digital Rain

Fullscreen Matrix-style animation. Live controls:

Key Action
d / D Density down / up
s / S Speed down / up
t / T Tail length down / up
c Cycle charsets (Katakana / Latin / Digits / Binary / Symbols)
p Cycle color palettes
q or ESC Exit

Theming

Three built-in color themes set via config.toml:

Theme Color
phosphor_green Classic green terminal (default)
amber Warm orange-amber
red_alert Deep red

The Now Playing rain backdrop automatically uses the palette that matches the active app theme.


Re-authorization / Scope Changes

If you update the app after a scope change (e.g. adding playlist or playback permissions), Spotify's cached token won't have the new scopes. Fix it by deleting the cache and re-running:

rm .cache          # macOS/Linux
del .cache         # Windows CMD

The browser authorization page will open again on next launch.


Legacy Scripts

Two older scripts remain in the root and are no longer the primary interface, but still work:

  • top_tracks.py — argparse CLI with --time-range, --limit, --output flags
  • interactive_top_tracks.py — guided prompts using inquirer + yachalk styling

These predate the TUI and don't use the new scopes or features.


Project Structure

track-operator/
├── spotify_tui/
│   ├── app.py                   # Entry point, main loop
│   ├── config.py                # TOML config loader with defaults
│   ├── spotify_client.py        # All Spotipy API calls
│   │
│   ├── screens/
│   │   ├── main_menu.py         # Arrow-key menu
│   │   ├── top_tracks.py        # Top tracks view + export
│   │   ├── top_artists.py       # Top artists view + export
│   │   ├── recent_plays.py      # Recent plays view + export
│   │   ├── audio_features.py    # BPM / feature fingerprint table
│   │   ├── playlist_diff.py     # Two-playlist diff
│   │   ├── playlist_bpm.py      # Playlist BPM viewer + playlist creator
│   │   ├── now_playing.py       # Live now playing + transport controls + rain mode
│   │   ├── rain.py              # Matrix rain easter egg
│   │   ├── splash.py            # Boot / auth screen
│   │   └── under_construction.py
│   │
│   ├── ui/
│   │   ├── theme.py             # Color palettes and Style factories
│   │   ├── components.py        # Reusable renderers (track_list, etc.)
│   │   ├── panels.py            # Panel/border helpers
│   │   ├── export.py            # Export prompts and formatters
│   │   ├── playlist_select.py   # Shared playlist selector (type-ahead + sort)
│   │   └── logo.py              # Figlet ASCII art logo
│   │
│   └── transitions/
│       ├── manager.py           # TransitionManager (registry pattern)
│       ├── fade.py              # Fade-to-black
│       ├── matrix_rain.py       # Matrix rain (auto-play, no controls)
│       └── none.py              # No-op
│
├── config.toml                  # User config (theme, transitions)
├── pyproject.toml               # Package metadata + entry point
├── requirements.txt             # Legacy dep list
├── FEATURES.md                  # Full feature roadmap with API details
├── TODO.md                      # Bug and feature tracking
├── .env                         # NOT committed — your Spotify credentials
└── .cache                       # NOT committed — Spotify OAuth token cache

Known Caveats

  • Playlist BPM / Audio Features use the /audio-features endpoint which Spotify restricted for new developer apps in late 2024. These screens show a clear error message if your app doesn't have access.
  • Playlist BPM / Diff / Now Playing require the OAuth scopes added in the v2 update. If you get a 403 or scope error, delete .cache and re-authorize.
  • Playback controls silently fail on free Spotify accounts (the API returns 403). The view still works read-only.
  • Local files in playlists (tracks not on Spotify's servers) are automatically skipped — they have no Spotify ID or audio features.
  • The app uses force_terminal=True in Rich so it renders ANSI colors correctly in Git Bash / MINGW64 on Windows. If colors look wrong in another terminal, check your TERM environment variable.
  • The OAuth token cache is pinned to the project root regardless of what directory you run trackop from — no more "Couldn't write cache" warnings when running from other directories.

Created by ALLCAPS with help from Microchip

About

A Python terminal UI (TUI) for exploring your Spotify listening data. Built with Rich, Spotipy, and questionary — runs entirely in your terminal with arrow-key navigation, live animations, themed colors, and direct Spotify playback control.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages