config.toml reference

Every option Moosic reads from config.toml. Click the gear icon in Moosic to open the file in your editor, or find it at the path Moosic prints to its log on startup.

Top-level

Plain keys at the root of the file.

scale number default: 1.0

UI scale multiplier. Use 1.5 or 2.0 on HiDPI screens that the OS doesn’t scale automatically.

scale = 1.5
skin_path string (path) default: unset — procedural skin

Absolute path to a .wsz skin file. On Windows use forward slashes.

skin_path = "/Users/you/skins/base-2.91.wsz"
skip_seconds number default: 15.0

How far the transport skip buttons jump in either direction.

skip_seconds = 30.0
art_cache_size integer default: 64

Max album cover art images held in memory. Raise on RAM-rich machines with huge libraries; lower on small devices.

art_cache_size = 128
scrobble_enabled boolean default: true

Global default for sending Subsonic scrobbles. Each server can override this.

scrobble_enabled = false
scrobble_threshold_percent integer 1–100 default: 50

Percent of song duration that must play before the scrobble is submitted.

scrobble_threshold_percent = 75
license string default: unset — trial mode

Signed license string from your purchase email. Removes trial friction and unlocks premium features.

license = "eyJ...sig"

[palette]

Modern UI color palette. Pick a preset and override any individual color. Colors are hex strings (#rrggbb or #rrggbbaa).

preset string default: "dark"

Base palette. Valid: "dark", "light", "high_contrast". Any color set below this overrides the preset.

preset = "light"
bg hex color default: preset bg

Window background.

bg = "#0b0a08"
surface hex color default: preset surface

Panel / card background.

surface = "#141210"
surface_high hex color default: preset

Elevated surface (hover, popovers).

surface_low hex color default: preset

Recessed surface (inset wells).

inset hex color default: preset

Track grooves, sliders.

primary hex color default: preset accent

Accent color used for highlights and active state.

primary = "#c8ff3a"
primary_dim hex color default: preset

Faded accent for backgrounds and ghost states.

tertiary hex color default: preset

Secondary accent (warnings, badges).

on_surface hex color default: preset

Primary text color on surfaces.

on_surface_dim hex color default: preset

Secondary / dimmed text color.

outline hex color default: preset

Dividers and borders.

[[servers]]

One block per Subsonic-compatible server (Navidrome, Fugue, etc.). Add as many as you want — Moosic shows a server picker.

name string default: required

Display name in the server picker.

name = "Home Navidrome"
url string (URL) default: required (unless ticket)

Base URL of the server. Include scheme and port. Leave empty when using an Iroh ticket.

url = "http://192.168.1.42:4533"
username string default: required

Account username on the server.

password string default: required

Account password. Stored in plain text in the file — protect with file permissions.

ticket string default: unset

Iroh P2P ticket for connecting via QUIC instead of HTTP. Format: "FriendName:base64ticket". When set, url is ignored and traffic goes peer-to-peer.

ticket = "Anna:eyJp...dfQ"
scrobble_enabled boolean default: inherit global

Override the top-level scrobble_enabled for this server only.

scrobble_threshold_percent integer 1–100 default: inherit global

Override the top-level threshold for this server only.

[sink]

Where decoded audio is sent. Defaults to local speakers (cpal). For Snapcast streaming, write to a FIFO pipe.

kind string default: "cpal"

Audio sink kind. "cpal" = local speakers. "snapcast" = stream to a Snapcast server via FIFO.

kind = "snapcast"
snapcast.pipe string (path) default: required for snapcast

Path to a FIFO created with mkfifo. Snapserver must read from the same pipe.

pipe = "/tmp/snapfifo"
snapcast.sample_rate integer Hz default: 48000

Sample rate written to the pipe. Must match the snapserver source config.

snapcast.channels integer default: 2

Channel count written to the pipe.

[[sync_folders]]

Folder destinations shown alongside auto-detected USB devices in the Devices tab. Use for SD cards, NAS shares, dev simulators.

name string default: required

Display name in the Devices tab.

name = "Backup SD card"
path string (path) default: required

Destination folder. Tracks go under <path>/Music/<Artist>/<Album>/, playlists under <path>/Playlists/.

path = "/Volumes/MUSIC"
profile string default: auto-detect

Device profile id ("snowsky_echo", "generic_msc", or a custom id). When omitted, the registry picks the best match.

profile = "snowsky_echo"

[[device_profile]]

Custom DAP profile defined in config alone — no rebuild. Use when a device is close to the generic layout and only the folder names, codec list, or USB IDs differ.

id string default: required

Unique profile id. Reference this from sync_folders.profile or USB auto-detect.

id = "my_weird_dap"
display_name string default: required

Human-readable name shown in the Devices tab.

vendor string default: ""

Vendor name. Cosmetic.

usb array of {vid,pid} default: []

USB vendor/product IDs that should auto-match this profile.

usb = [{ vid = 0x1234, pid = 0x5678 }]
mount_markers array of strings default: []

Filenames that confirm the device when found at a mount root.

mount_markers = [".mydap"]
volume_label_hints array of strings default: []

Volume labels (case-insensitive) that should auto-match.

music_root string default: "Music"

Folder under the mount root where tracks are written.

playlist_root string default: "Playlists"

Folder under the mount root where playlists are written.

playlist_format string default: "m3u8"

Playlist file format. One of: "m3u8", "m3u", "wpl", "pls".

path_template string default: "{album_artist}/{album}/{track:02} {title}.{ext}"

Per-track path template. Placeholders: {album_artist} {artist} {album} {track} {disc} {title} {ext}.

path_max_len integer default: 240

Truncate paths that exceed this many bytes (FAT32 limits).

case_sensitive boolean default: false

Whether path comparison is case-sensitive on this device.

forbidden_chars string default: \/:*?"<>|

Characters stripped from generated paths.

artwork string default: "embedded"

Artwork strategy. One of: "embedded", "sidecar_folder", "sidecar_match", "none".

codecs array of strings default: ["flac","mp3","aac","ogg","wav"]

Codecs the device can decode. Other formats are transcoded before copy.

max_sample_rate integer Hz default: 192000

Max sample rate. Files above this are downsampled.

max_bit_depth integer default: 24

Max bit depth.

max_channels integer default: 2

Max channel count.

supports_dsd boolean default: false

Whether the device plays DSD natively.

post_sync_marker string default: unset

Filename written under the mount root after a successful sync. Triggers a library rescan on devices that watch for one.

post_sync_marker = ".rescan"

Full example

Every option set at once. Copy, then delete what you don't need.

Show complete config.toml
# ─── Top-level ────────────────────────────────────────────────────────
scale = 1.0
skin_path = "/Users/you/skins/base-2.91.wsz"
skip_seconds = 15.0
art_cache_size = 64
scrobble_enabled = true
scrobble_threshold_percent = 50
license = "eyJ...sig"

# ─── Modern UI palette ────────────────────────────────────────────────
[palette]
preset = "dark"
primary = "#c8ff3a"
bg = "#0b0a08"
surface = "#141210"

# ─── Servers ──────────────────────────────────────────────────────────
[[servers]]
name = "Home Navidrome"
url = "http://192.168.1.42:4533"
username = "anna"
password = "navidrome-password"
# Per-server overrides:
# scrobble_enabled = false
# scrobble_threshold_percent = 75

# Fugue over Iroh P2P (url ignored when ticket is set):
[[servers]]
name = "Friend's Fugue"
url = ""
username = "guest"
password = "shared-pw"
ticket = "Anna:eyJp...dfQ"

# ─── Audio sink ───────────────────────────────────────────────────────
# Default is local speakers. To stream to Snapcast via FIFO:
#   mkfifo /tmp/snapfifo
[sink]
kind = "snapcast"
[sink.snapcast]
pipe = "/tmp/snapfifo"
sample_rate = 48000
channels = 2

# ─── Device sync ──────────────────────────────────────────────────────
[[sync_folders]]
name = "Dev simulator"
path = "/Users/you/dev/fake-echo"
profile = "snowsky_echo"

[[sync_folders]]
name = "Backup SD card"
path = "/Volumes/MUSIC"

# ─── Custom DAP profile ───────────────────────────────────────────────
[[device_profile]]
id = "my_weird_dap"
display_name = "My Weird DAP"
vendor = "Acme"
usb = [{ vid = 0x1234, pid = 0x5678 }]
mount_markers = [".mydap"]
volume_label_hints = ["WEIRD"]
music_root = "Audio"
playlist_root = "Lists"
playlist_format = "m3u8"
path_template = "{album_artist}/{album}/{track:02} {title}.{ext}"
path_max_len = 240
case_sensitive = false
forbidden_chars = "\\/:*?\"<>|"
artwork = "embedded"
codecs = ["flac", "mp3", "ogg"]
max_sample_rate = 96000
max_bit_depth = 24
max_channels = 2
supports_dsd = false
post_sync_marker = ".rescan"