ytm-player

Configuration

ytm-player reads configuration from TOML files in ~/.config/ytm-player/ (respects $XDG_CONFIG_HOME):

File Purpose
config.toml General settings, playback, cache, UI, integrations
keymap.toml Custom keybinding overrides (full key list: docs/keybindings.md)
theme.toml App-specific color overrides on top of the active Textual theme
auth.json YouTube Music credentials (auto-generated by ytm setup)

Open the config directory in your editor:

ytm config

config.toml

Every section is optional — anything you don't set falls back to defaults.

[general]

[general]
startup_page = "library"     # library, search, browse
playback_bar_position = "bottom"  # "bottom" or "top"
brand_account_id = ""        # YouTube Brand Account ID (21-digit; find at myaccount.google.com/brandaccounts)
check_for_updates = true     # check PyPI once per 24h, surface a one-time toast on new version

[playback]

[playback]
audio_quality = "high"       # high, medium, low
prefer_audio = true          # prefer audio-only streams over video (audio uses less bandwidth)
default_volume = 80          # 0-100
autoplay = true              # auto-play next on track end
gapless = true               # preload the next track for gapless transitions
seek_step = 5                # seconds per +/- seek
api_timeout = 15             # seconds for ytmusicapi calls before failover
resume_on_launch = true      # restore last-playing track + position on app start; press space to continue

resume_on_launch (added v1.7.0) stages the last-playing track + position into the playback bar on startup. Press space to continue from where you were. Set to false to start fresh every time.

[cache]

[cache]
enabled = true
max_size_mb = 1024           # 1GB default LRU audio cache
prefetch_next = true         # resolve next track's stream URL in background for instant skip
location = ""                # blank = default cache dir; set a path to override

[yt_dlp]

[yt_dlp]
cookies_file = ""            # Optional: path to yt-dlp Netscape cookies.txt
ca_bundle = ""               # Optional: path to a custom CA cert bundle for SSL-inspecting
                             # corporate proxies (Zscaler, Netskope, etc.)
remote_components = ""       # Optional: ejs:npm/ejs:github (enables remote JS component downloads)
js_runtimes = ""             # Optional: bun, bun:/path/to/bun, node, quickjs, etc.
[search]
default_mode = "music"       # "music" (songs only) or "all" (all result types)
max_history = 500            # number of past search queries to remember
predictive = true            # show search suggestions as you type

[ui]

[ui]
theme = "ytm-dark"           # startup default Textual theme; runtime changes are saved in session.json
album_art = true             # show colored half-block album art in playback bar
progress_style = "block"     # block or line
sidebar_width = 30
col_index = 4                # 0 = auto-fill width
col_title = 0                # 0 = auto-fill
col_artist = 0               # 0 = auto-fill
col_album = 0                # 0 = auto-fill
col_duration = 8
bidi_mode = "auto"           # auto, reorder, passthrough — RTL text handling
region = "ZZ"                # ISO 3166-1 alpha-2 (or "ZZ" = Global, default) — Browse → Charts. 68 regions selectable; locale-style codes like "ES-ES" auto-normalise to "ES".
home_shelves = 3             # number of recommendation shelves on Browse → For You (1–25)
show_selection_info = true   # show focused-item full name in the row above the playback bar
sidebar_overflow = "truncate"  # "truncate" (1-row + ellipsis) or "wrap" (multi-line names)
show_queue_source = true     # show "Generated from: …" header on radio/discovery queues

theme is the startup default. Changing theme from Textual's command palette (Ctrl+PTheme) updates the current session and is saved in session.json, not config.toml. To make the active theme the new default, run Ctrl+PSet Current Theme as Default.

Per-playlist Shuffle lock state (set via the Shuffle lock toggle in the Library page playlist header) is persisted separately to ~/.config/ytm-player/shuffle_prefs.json. There's nothing to configure in config.toml for it.

[notifications]

[notifications]
enabled = true
timeout_seconds = 5
format = "{title} — {artist}"  # template for the now-playing notification body

[mpris]

[mpris]
enabled = true

[discord]

[discord]
enabled = false              # requires `pip install ytm-player[discord]`
client_id = ""               # blank uses the bundled app; set your own
                             # Discord application ID to publish under it

[lyrics]

[lyrics]
transliteration = false      # transliterate non-Latin lyrics to ASCII (requires
                             # `pip install ytm-player[transliteration]`)

[lastfm]

[lastfm]
enabled = false              # requires `pip install ytm-player[lastfm]`
api_key = ""
api_secret = ""
session_key = ""
username = ""

[logging]

[logging]
level = "WARNING"            # DEBUG, INFO, WARNING, ERROR, CRITICAL
max_bytes = 5242880          # 5 MB per log file before rotation
backup_count = 3             # number of rotated logs to keep
keep_crashes = 10            # max number of crash files to retain in crashes/

theme.toml

Base colors (primary, background, etc.) come from the active Textual theme. Choose the startup default with [ui] theme, switch the current session with Ctrl+PTheme, and use theme.toml for app-specific color overrides:

[colors]
playback_bar_bg = "#1a1a1a"
selected_item = "#2a2a2a"
progress_filled = "#ff0000"
progress_empty = "#555555"
lyrics_played = "#999999"
lyrics_current = "#ff4e45"   # defaults to the theme accent if unset
lyrics_upcoming = "#aaaaaa"
active_tab = "#ffffff"
inactive_tab = "#999999"

The lyrics_current color falls back to the active theme's accent (and then to #ff4e45 red as the absolute last-resort default). Override only if you want something different from your theme's accent.

keymap.toml

For custom keybinding overrides, see docs/keybindings.md for the full key list and the customization syntax.