Skip to content

Repository files navigation

waxon logo

waxon

A vim-modal Spotify client for the terminal.

Install · Features · Keybindings · Commands

waxon demo

Install

Homebrew (macOS / Linux):

brew trust danfry1/tap        # one-time: trust the third-party tap
brew install danfry1/tap/waxon

Recent Homebrew versions refuse to load formulae from third-party taps until they're trusted. If you see Error: Refusing to load formula ... from untrusted tap, run the brew trust danfry1/tap line above (once) and retry.

Upgrading from ≤ 1.6.0? waxon moved from a formula to a cask. Once: brew uninstall --formula waxon && brew install danfry1/tap/waxon.

Nix (flakes):

nix run github:danfry1/waxon              # run without installing
nix profile install github:danfry1/waxon

Scoop (Windows):

scoop bucket add danfry1 https://github.com/danfry1/scoop-bucket
scoop install waxon

Go:

go install github.com/danfry1/waxon@latest

Linux packages / binaries: every release ships .deb, .rpm and .apk packages plus tar.gz/zip archives (with SHA-256 checksums) for Linux, macOS and Windows on amd64 and arm64.

Quick Start

waxon         # first run walks you through connecting Spotify

Setup asks one question — use your own Spotify app (recommended: no rate limits, two minutes, waxon shows the exact clicks) or the shared one (zero setup, but Spotify throttles it for everyone).

guided setup

Re-run or switch any time:

waxon auth            # guided
waxon auth --own      # set up / switch to your own app
waxon auth --shared   # use the shared app
waxon auth --client-id <ID>

Requires a Spotify Premium account. True-colour terminals get the full look; 256-colour and NO_COLOR terminals are supported with graceful fallbacks.

waxon is a remote control for Spotify Connect: it plays through whatever Spotify client is running (desktop app, phone, speaker). If nothing is active when you press play, waxon picks the only available device for you — or asks which one to use when there are several.

picking a device when none is active

Features

Vim Navigation

Navigate everything without leaving the home row — j/k to move, gg/G to jump, h/l to switch panes.

vim navigation

Small Terminals

Below 80 columns waxon shows one pane at a time — h/l/Tab switch between library and tracks — and the track table drops columns rather than overflowing. Now Playing art scales to fit. Handy for a tmux side pane.

narrow terminal layout

Now Playing

Full-screen album art rendered with Unicode half-blocks, gradient backgrounds, and a vinyl spinning mode.

now playing view

Synced Lyrics

Press l in Now Playing for time-synced lyrics (via lrclib — no account, no API key, nothing to set up). The current line lights up and the rest gently fade as the song plays.

time-synced lyrics

Playlists

o on any track offers Add to Playlist… (type to filter your playlists) and, inside one of your own playlists, Remove from …. Create a new one with :playlist new <name>. Changes show up immediately in the sidebar and the open playlist.

adding a track to a playlist

Upgrading? Playlist editing needs two extra Spotify permissions; waxon will ask you to run waxon auth once.

Search

Find tracks, artists, and albums across Spotify.

search

Artist & Album Browsing

Explore discographies, browse full albums, and navigate with a browser-like back stack.

artist and album browsing

Command Mode

Vim-style commands for volume, shuffle, repeat, device switching, and more.

command mode

Keybindings

Navigation

Key Action
j / k Move down / up
gg Go to top
G Go to bottom
Ctrl+u / Ctrl+d Half page up / down

Panes

Key Action
h / l Focus left / right pane
Tab Cycle pane
1 / 2 Library / queue section

Go-to (g prefix)

Key Action
gl Go to library
gq Go to queue
gc Jump to currently playing track (loads its playlist/album if you've navigated away)
gr Recently played

Playback

Key Action
Space Play / pause
Enter Play selected
n / p Next / previous track
[ / ] Seek -5s / +5s

Actions

Key Action
o Context actions menu
a Add to queue
/ Filter current view
s Spotify search
D Device switcher
: Command mode

Other

Key Action
N Now Playing view
f / a / o Like / queue / actions for the playing track (in Now Playing)
V Toggle vinyl mode (in Now Playing)
l Toggle synced lyrics (in Now Playing)
Backspace / b Go back
? Toggle help overlay
q Quit
Esc Close / cancel

Commands

Enter command mode by pressing :, then type a command.

Command Description
:vol <0-100> Set volume
:shuffle Toggle shuffle
:repeat off|all|one Set repeat mode
:device Open device switcher
:search <query> Search Spotify
:recent Recently played
:theme <name> Switch colour theme (saved to config)
:playlist new <name> Create a playlist
:q Quit

Configuration

waxon reads ~/.config/waxon/config.json ($XDG_CONFIG_HOME respected; waxon config prints the path). Everything is optional:

{
  "theme": "catppuccin-mocha",
  "colors": { "accent": "#F5C2E7" },
  "keys":   { "next": "l,right", "prev": "h,left", "quit": "ctrl+q" }
}

Themes — built in: spotify (default), catppuccin-mocha, catppuccin-latte, gruvbox, tokyonight, nord, dracula, rose-pine (waxon themes lists them; waxon doesn't paint the terminal background, so pick a light theme like catppuccin-latte for a light terminal). Switch live with :theme <name> — it's saved to your config. colors overrides individual palette entries on top of any theme: accent, bg, surface, text, text_sec, text_dim, border, error, mode_search, mode_filter, overlay.

switching themes with :theme

Keyskeys maps an action to a comma-separated list of keys (Bubbletea names: j, down, ctrl+d, space, enter, esc, tab, backspace, f1…). Actions: up down bottom half_up half_down focus_left focus_right cycle_pane enter play_pause next prev seek_fwd seek_back add_queue like actions devices back filter search command help now_playing quit escape section1 section2. The g-prefix motions (gg gl gq gc gr) are fixed. The ? help overlay always shows your live bindings.

Cache — album art is cached under $XDG_CACHE_HOME/waxon/images (or your OS cache dir), capped at 64 MB and pruned on launch, so relaunching paints the library instantly. Delete the directory to clear it.

Colour fallback — colours degrade automatically on 256-colour terminals and are dropped under NO_COLOR; album art uses the 256-colour cube where true colour isn't available and is skipped entirely on monochrome terminals.

Scripting & Status Bars

Every playback action is also a plain subcommand, so waxon slots into tmux, waybar/polybar, hotkey daemons and shell scripts without opening the TUI.

waxon status                      # ▶ Let It Happen — Tame Impala
waxon status --json               # {"playing":true,"title":...,"progress":37,...}
waxon status --waybar             # {"text":"…","alt":"playing","class":"playing",...}
waxon status --format '{icon} {title} [{position}/{duration}]'
waxon play | pause | toggle | next | prev
waxon play daft punk get lucky    # search, then play the first match
waxon seek +10 | seek -10 | seek 1:30
waxon vol 40 | vol +5 | vol -5
waxon shuffle [on|off] | repeat off|all|one
waxon like                        # toggle Liked Songs for the playing track
waxon queue instant crush
waxon devices | device "living room"
waxon search radiohead [--json]

status prints nothing when idle (so bars stay blank) and exits non-zero on errors; --json always emits an object. Placeholders for --format: {title} {artist} {album} {position} {duration} {progress} {state} {icon} {device} {volume} {shuffle} {repeat} {liked} {uri} {id}. If no Spotify device is active, commands activate the only available one automatically, or tell you which ones to choose from.

waxon CLI subcommands

tmux (~/.tmux.conf):

set -g status-right '#(waxon status --format "{icon} {title} — {artist}") | %H:%M'
set -g status-interval 5

waybar (~/.config/waybar/config) — --waybar emits the text/alt/class/tooltip/percentage object waybar expects:

"custom/spotify": {
  "exec": "waxon status --waybar",
  "return-type": "json",
  "format": "{icon} {}",
  "format-icons": {"playing": "", "paused": "", "idle": ""},
  "on-click": "waxon toggle",
  "on-scroll-up": "waxon vol +5",
  "on-scroll-down": "waxon vol -5",
  "interval": 5
}

Hotkeys (skhd on macOS / sxhkd on Linux):

cmd + alt - space : waxon toggle
cmd + alt - right : waxon next
cmd + alt - left  : waxon prev
cmd + alt - l     : waxon like

Using Your Own Spotify App (Recommended if you see rate limits)

waxon works out of the box with no configuration — it ships with a shared client ID used by several open-source Spotify clients. Spotify rate-limits that shared app as a whole, so at busy times you may see Spotify rate limit toasts or sluggish controls. A personal client ID has its own quota and takes two minutes to set up:

  1. Go to the Spotify Developer Dashboard and create an app

  2. Set the redirect URI to http://127.0.0.1:27228/callback

  3. Copy the Client ID and run setup with it:

    SPOTIFY_CLIENT_ID=your_client_id waxon auth
    

The client ID is saved to ~/.config/waxon/config.json automatically, so you only need to set the environment variable once during setup.

Note: new developer apps are in Spotify's development mode, which only allows the current API endpoints. waxon uses those (with legacy fallbacks for older apps), so playback, search, queue, liking and playlist editing all work. The one thing Spotify blocks for development-mode apps with no replacement is an artist's top tracks — artist pages show the discography instead.

Troubleshooting

Symptom Cause / fix
Spotify rate limit / Spotify is rate limiting toasts Spotify is throttling the app. waxon backs off automatically and honours Spotify's Retry-After. If it keeps happening, the shared client ID is busy — use your own.
No active Spotify device Spotify must be open somewhere (desktop, phone, speaker). waxon picks the only available device automatically or asks with D.
Not available with this Spotify app Spotify blocks that endpoint for development-mode (personal) apps — currently only artists' top tracks.
Permission needed — run waxon auth Your saved token predates a feature that needs extra permissions (e.g. playlist editing). Re-run waxon auth once.
Session expired Token revoked or refresh failed. Re-run waxon auth.
Nothing renders / garbled colours Set a true-colour or 256-colour TERM, or NO_COLOR=1 for monochrome. Minimum size is 40×10.

Debug log: WAXON_LOG=/tmp/waxon.log waxon (includes rate-limit Retry-After values).

Environment Variables

Variable Description
SPOTIFY_CLIENT_ID Override the saved Spotify Client ID
WAXON_LOG Path to debug log file (e.g. /tmp/waxon.log)
WAXON_NO_BROWSER Don't launch a browser during waxon auth; just print the URL (SSH)

Acknowledgements

Built with Bubbletea, Bubbles, and Lip Gloss by Charmbracelet. Demo recordings made with VHS. Huge thanks to the Charm team for making terminal UIs a joy to build.

License

This project is licensed under the GNU General Public License v3.0.

About

A vim-modal Spotify client for the terminal

Resources

Stars

49 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages