-
-
Notifications
You must be signed in to change notification settings - Fork 189
Configuration
A configuration file is located at ~/.config/spotatui/config.yml.
Note: This is not to be confused with
client.yml, which handles Spotify authentication.
You can point spotatui at a different file with spotatui --config /path/to/config.yml.
Every field is optional; omitted values use the built-in defaults. Simple values (numbers, toggles, icons, positions) can also be changed live in the in-app Settings screen. Structured config — format: templates, tables: columns, and playbar_control_labels — is file-only.
Safe by default: a typo in config.yml never prevents the app from starting. Structural mistakes — an unknown sort field, a bad template placeholder, an invalid column id, an icon that is too wide — are logged as warnings and the affected value falls back to its built-in default. Warnings go to the log file whose path is printed at startup. Only YAML syntax errors and a few out-of-range numerics (volume_increment outside 0–100, a zero tick rate, an unparseable auto_update_delay) are fatal.
# Colours can be an rgb string of the form "255, 255, 255" or a terminal colour
# name: Reset, Black, Red, Green, Yellow, Blue, Magenta, Cyan, Gray, DarkGray,
# LightRed, LightGreen, LightYellow, LightBlue, LightMagenta, LightCyan, White.
theme:
preset: "Default (Cyan)" # named preset; set to Custom to use the colours below
active: Cyan # current playing song in list
banner: LightCyan # the "spotatui" banner on launch
error_border: Red # error dialog border
error_text: LightRed # error message text
hint: Yellow # hint text in errors
hovered: Magenta # hovered pane border
inactive: Gray # borders of inactive panes
playbar_background: Reset # background of progress bar
playbar_progress: LightCyan # filled-in part of the progress bar
playbar_progress_text: White # song length and time indicator
playbar_text: Reset # artist name in player pane
selected: LightCyan # selected pane border, hovered item, track title
text: Reset # text in panes
header: Reset # header text in panes
background: Reset # pane background
highlighted_lyrics: LightCyan # current line in the lyrics view
behavior:
seek_milliseconds: 5000
volume_increment: 10
volume_percent: 100 # startup volume
# Lower = higher FPS for audio visualization (but more expensive)
tick_rate_milliseconds: 250
animation_tick_rate_milliseconds: 16 # refresh cadence for animated views
enable_text_emphasis: true
show_loading_indicator: true
enforce_wide_search_bar: false
enable_global_song_count: true
disable_mouse_inputs: false
set_window_title: true
shuffle_enabled: false # persist shuffle state across sessions
stop_after_current_track: false
keepawake_enabled: true # prevent the system sleeping while playing
# Timing constants
status_message_ttl_percent: 100 # 10..=1000; 200 = status messages last twice as long
playback_poll_seconds: 5 # min 1; playback-state poll interval
table_scroll_padding: 5 # rows kept visible below the selection while scrolling
like_animation_frames: 10 # min 1; length of the heart burst when liking a track
# Startup
startup_behavior: continue # continue | play | pause
startup_route: home # which screen opens at launch (see below)
disable_auto_update: false
auto_update_delay: "0" # 0, 30s, 10m, 2h, 7d ...
# Default sorting per screen ("<field>" or "<field>:desc", see below)
default_sort_playlist_tracks: default
default_sort_saved_albums: default
default_sort_saved_artists: default
default_sort_recently_played: default
# Discord Rich Presence
enable_discord_rpc: true
# discord_rpc_client_id: "..." # optional: override the built-in app id
# In-app announcements
enable_announcements: true
# announcement_feed_url: "..." # optional: override the feed
# Audio visualizer
visualizer_style: Equalizer # Equalizer | BarGraph
# Listening Party
relay_server_url: "wss://spotatui-party.spotatui.workers.dev/ws"
# sync_token: "..." # spotatui.com token (for the Friends feature)
# Layout (percentages also adjustable live with { } ( ) and | )
sidebar_position: left # left | right | hidden (auto-reveals when focused)
playbar_position: bottom # bottom | top
sidebar_width_percent: 20
playbar_height_rows: 6
library_height_percent: 30
small_terminal_width: 150 # wide-layout breakpoint (columns)
small_terminal_height: 45 # margin breakpoint (rows)
# Cover art (requires the `cover-art` build feature)
draw_cover_art: true
draw_cover_art_forced: false
playbar_cover_art_size_percent: 100
# Icons (some require a patched nerd font; see Icons section below)
liked_icon: ♥
shuffle_icon: 🔀
repeat_track_icon: 🔂
repeat_context_icon: 🔁
playing_icon: ▶
paused_icon: ⏸
gauge_filled_icon: ⣿
gauge_unfilled_icon: ⣉
active_source_icon: ●
episode_played_icon: ✔
sort_ascending_icon: ↑
sort_descending_icon: ↓
list_highlight_icon: ▶
# Playbar button labels (all keys optional; see below)
# playbar_control_labels:
# play_pause: "[PLAY/PAUSE]"
keybindings:
back: "q"
jump_to_album: "a"
jump_to_artist_album: "A"
manage_devices: "d"
decrease_volume: "-"
increase_volume: "+"
toggle_playback: " "
seek_backwards: "<"
seek_forwards: ">"
next_track: "n"
previous_track: "p"
copy_song_url: "c"
copy_album_url: "C"
help: "?"
shuffle: "ctrl-s"
repeat: "ctrl-r"
search: "/"
audio_analysis: "v"
jump_to_context: "o"
lyrics_view: "B"
add_item_to_queue: "z"
show_queue: "Q"
like_track: "F"
listening_party: "ctrl-p"
open_settings: "alt-,"
# Bind keys to Lua plugin commands (see the Lua Plugins page)
plugin_commands:
# my_command: "ctrl-h"
# Status line & window title templates (see Format Templates below)
format:
playbar_status: "{state} ({device} | Shuffle: {shuffle} | Repeat: {repeat} | Volume: {volume}%){party}"
playbar_status_source: "{state} ({source}{queue} | Volume: {volume}%)"
window_title: "{title}{artist}"
# Table columns: reorder / remove / rename / resize (see Table Columns below)
tables:
songs:
- { id: liked }
- { id: title, width_percent: 40 }
- { id: artist, header: "Band", width_percent: 30 }
- { id: album }
- { id: length }See Keybindings for the full list of rebindable actions and their defaults.
| Field | Default | Purpose |
|---|---|---|
seek_milliseconds |
5000 |
How far to seek per keypress |
volume_increment |
10 |
Volume step per keypress |
volume_percent |
100 |
Startup volume |
tick_rate_milliseconds |
250 |
Normal UI refresh cadence |
animation_tick_rate_milliseconds |
16 |
Refresh cadence for animated views |
status_message_ttl_percent |
100 |
Scales how long status messages stay visible (10–1000) |
playback_poll_seconds |
5 |
Playback-state poll interval (min 1; near track end the app polls faster regardless) |
table_scroll_padding |
5 |
Rows kept visible below the selection before a table scrolls (clamped to half the table height) |
like_animation_frames |
10 |
Length of the heart burst when liking a track (min 1) |
enable_text_emphasis |
true |
Bold/italic text styling |
show_loading_indicator |
true |
Show spinner while loading |
enforce_wide_search_bar |
false |
Always show the wide search bar |
enable_global_song_count |
true |
Anonymous global play-counter increment |
disable_mouse_inputs |
false |
Disable mouse click/scroll |
set_window_title |
true |
Set terminal title to the current track |
shuffle_enabled |
false |
Persist shuffle across sessions |
stop_after_current_track |
false |
Pause after the current track ends |
keepawake_enabled |
true |
Prevent system sleep while playing |
startup_behavior |
continue |
continue / play / pause on launch |
startup_route |
home |
Which screen opens at launch (see below) |
default_sort_* |
default |
Per-screen default sorting (see below) |
disable_auto_update |
false |
Skip the auto-update check |
auto_update_delay |
"0" |
Delay before applying an available update |
enable_discord_rpc |
true |
Discord Rich Presence |
discord_rpc_client_id |
built-in | Override the Discord application id |
enable_announcements |
true |
Show in-app announcements |
announcement_feed_url |
built-in | Override the announcement feed |
visualizer_style |
Equalizer |
Equalizer or BarGraph
|
relay_server_url |
spotatui worker | Listening Party WebSocket relay |
sync_token |
(none) | spotatui.com token for Friends |
sidebar_position |
left |
left / right / hidden (see below) |
playbar_position |
bottom |
bottom / top
|
sidebar_width_percent |
20 |
Sidebar width (% of terminal); 0 hides it |
playbar_height_rows |
6 |
Playbar height (rows); 0 hides it |
library_height_percent |
30 |
Library pane height (% of sidebar) |
small_terminal_width |
150 |
Wide-layout breakpoint (columns) |
small_terminal_height |
45 |
Margin breakpoint (rows) |
draw_cover_art |
true |
Cover art in the playbar (cover-art feature) |
draw_cover_art_forced |
false |
Force cover art without terminal image support |
playbar_cover_art_size_percent |
100 |
Cover art size (clamped 25–200) |
startup_route picks which screen opens at launch. Its data is fetched automatically, so the screen arrives populated. Only context-free screens are valid:
| Value | Screen | Alias |
|---|---|---|
home (default) |
Home | |
recently_played |
Recently Played | recent |
podcasts |
Podcasts | |
discover |
Discover | |
artists |
Followed Artists | library |
album_list |
Saved Albums | albums |
Each sortable screen can start pre-sorted. The value is "<field>" for ascending or "<field>:desc" for descending (e.g. default_sort_saved_albums: date_added:desc).
| Setting | Valid fields |
|---|---|
default_sort_playlist_tracks |
default, name, date_added, artist, album, duration
|
default_sort_saved_albums |
default, name, date_added, artist
|
default_sort_saved_artists |
default, name
|
default_sort_recently_played |
default, name, artist, album
|
default keeps the order the API returns (playlist order, date saved, play order).
-
sidebar_position: hiddengives the content the full width, but the sidebar auto-reveals while the Library or Playlists panel has keyboard focus or is hovered, so it never becomes unreachable. -
small_terminal_width/small_terminal_heightare the responsive-layout breakpoints: at or abovesmall_terminal_widthcolumns the search box moves inside the sidebar (wide layout); below it, it gets its own full-width top row. - Mouse hit-testing follows every arrangement automatically.
All icons live under behavior and can be edited live in the Settings screen's Icons tab.
Free-form (any width): liked_icon, shuffle_icon, repeat_track_icon, repeat_context_icon, paused_icon, active_source_icon (marks the active source in the device picker), list_highlight_icon (cursor prefix in sidebar/menu lists).
Fixed-cell — must be exactly one terminal column wide (wider glyphs fall back to the default with a warning):
| Icon | Where it appears |
|---|---|
playing_icon |
prefixes the playing row in track tables |
gauge_filled_icon / gauge_unfilled_icon
|
progress and volume gauges |
episode_played_icon |
played marker in the episodes table |
sort_ascending_icon / sort_descending_icon
|
sort indicator in table headers |
Ambiguous-width caveat: some glyphs (e.g.
↑ ↓ ● ▶) have Unicode "East Asian Ambiguous" width. Terminals configured to render ambiguous-width characters as wide (common with CJK locales) draw them 2 cells wide, shifting column alignment even though the config validates. If that happens, set your terminal's ambiguous-width option to "narrow" or pick unambiguous glyphs.
The clickable playbar buttons can be relabeled (config-only). Mouse hitboxes resize to fit the labels automatically.
behavior:
playbar_control_labels:
prev: "⏮"
play_pause: "[PLAY/PAUSE]"
next: "⏭"
shuffle: "shfl"
repeat: "rpt"
like: "♥+"
vol_down: "vol-"
vol_up: "vol+"All eight keys are optional; omit a key (or set it to an empty string) to keep that button's built-in label.
format controls the playbar status line and the terminal window title (config-only). Templates use {key} placeholders; write a literal brace as {{ or }}. An unknown key or unbalanced brace falls back to the default template with a warning listing the valid keys. The defaults shown in the sample above reproduce the built-in output exactly.
playbar_status is used for Spotify playback, playbar_status_source for local/Subsonic/Radio/YouTube playback. Both accept the same keys; keys that don't apply to the current mode render empty:
| Key | Renders as | Notes |
|---|---|---|
{state} |
Playing / Paused
|
padded to 7 characters |
{device} |
Spotify device name | Spotify playback only |
{source} |
active source label (e.g. Local, Subsonic) |
source playback only |
{queue} |
| 3/12 queue position, or empty |
source playback only |
{shuffle} |
On / Off
|
padded to 3 characters |
{repeat} |
Off / Track / All
|
padded to 5 characters |
{volume} |
volume percentage number | append your own %
|
{party} |
| Party: 3 listeners / | Party: following <host>, or empty |
includes its own separator |
window_title (applied when set_window_title: true) accepts {title} and {artist}. {artist} comes pre-composed as — <artist> and renders empty when unknown, so the default "{title}{artist}" produces Song — Artist or just Song.
tables reorders, removes, renames, and resizes the columns of every track/album/podcast table (config-only). Omit a table (or the whole section) to keep its built-in columns.
Each column entry supports: id (required), header (display-name override), and width_percent or width in cells (not both; neither means the built-in default width). No zero widths, no duplicate ids, at least one column, and a table's width_percent values may not sum past 100 — violations degrade that table to its defaults with a warning.
| Table | Screen | Default columns | All valid ids |
|---|---|---|---|
songs |
playlists, liked songs, search results | liked, title, artist, album, length |
+ index
|
album_tracks |
an album's track list | liked, index, title, artist, length |
+ album
|
recently_played |
Recently Played | liked, title, artist, length |
+ index, album
|
albums |
Saved Albums | title, artist, date |
+ liked
|
podcasts |
Podcasts | title, publisher |
— |
episodes |
a podcast's episodes | played, date, title, duration |
— |
The ▶ now-playing marker attaches to the title column, or to the first column if you remove title. Sort keyboard shortcuts are unaffected by column layout.
Press Alt-, (macOS: Ctrl-,) to open the Settings screen, where you can customize spotatui
without editing config files. Press Alt-s to save changes back to config.yml.
Saving from Settings rewrites the behavior, theme, and keybindings sections of config.yml, but leaves your format:, tables:, and plugin_commands: sections untouched.
| Category | Description |
|---|---|
| Behavior | Seek, volume, tick rate, timing, startup route, default sorting, layout positions, toggles, sync token |
| Icons | All icon glyphs, with width validation for fixed-cell icons |
| Keybindings | View and rebind keys |
| Theme | Color presets and individual color customization |