Skip to content
LargeModGames edited this page Jul 9, 2026 · 4 revisions

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.

Sample Configuration

# 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.

Behavior Reference

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

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

Default Sorting

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).

Layout

  • sidebar_position: hidden gives 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_height are the responsive-layout breakpoints: at or above small_terminal_width columns 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.

Icons

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.

Playbar Control Labels

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 Templates

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.

Table Columns

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.

In-App Settings

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.

Settings Categories

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

Clone this wiki locally