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.0UI scale multiplier. Use 1.5 or 2.0 on HiDPI screens that the OS doesn’t scale automatically.
scale = 1.5skin_path string (path) default: unset — procedural skinAbsolute 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.0How far the transport skip buttons jump in either direction.
skip_seconds = 30.0art_cache_size integer default: 64Max album cover art images held in memory. Raise on RAM-rich machines with huge libraries; lower on small devices.
art_cache_size = 128scrobble_enabled boolean default: trueGlobal default for sending Subsonic scrobbles. Each server can override this.
scrobble_enabled = falsescrobble_threshold_percent integer 1–100 default: 50Percent of song duration that must play before the scrobble is submitted.
scrobble_threshold_percent = 75license string default: unset — trial modeSigned 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 bgWindow background.
bg = "#0b0a08"surface hex color default: preset surfacePanel / card background.
surface = "#141210"surface_high hex color default: presetElevated surface (hover, popovers).
surface_low hex color default: presetRecessed surface (inset wells).
inset hex color default: presetTrack grooves, sliders.
primary hex color default: preset accentAccent color used for highlights and active state.
primary = "#c8ff3a"primary_dim hex color default: presetFaded accent for backgrounds and ghost states.
tertiary hex color default: presetSecondary accent (warnings, badges).
on_surface hex color default: presetPrimary text color on surfaces.
on_surface_dim hex color default: presetSecondary / dimmed text color.
outline hex color default: presetDividers 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: requiredDisplay 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: requiredAccount username on the server.
password string default: requiredAccount password. Stored in plain text in the file — protect with file permissions.
ticket string default: unsetIroh 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 globalOverride the top-level scrobble_enabled for this server only.
scrobble_threshold_percent integer 1–100 default: inherit globalOverride 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 snapcastPath to a FIFO created with mkfifo. Snapserver must read from the same pipe.
pipe = "/tmp/snapfifo"snapcast.sample_rate integer Hz default: 48000Sample rate written to the pipe. Must match the snapserver source config.
snapcast.channels integer default: 2Channel 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: requiredDisplay name in the Devices tab.
name = "Backup SD card"path string (path) default: requiredDestination folder. Tracks go under <path>/Music/<Artist>/<Album>/, playlists under <path>/Playlists/.
path = "/Volumes/MUSIC"profile string default: auto-detectDevice 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: requiredUnique profile id. Reference this from sync_folders.profile or USB auto-detect.
id = "my_weird_dap"display_name string default: requiredHuman-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: 240Truncate paths that exceed this many bytes (FAT32 limits).
case_sensitive boolean default: falseWhether 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: 192000Max sample rate. Files above this are downsampled.
max_bit_depth integer default: 24Max bit depth.
max_channels integer default: 2Max channel count.
supports_dsd boolean default: falseWhether the device plays DSD natively.
post_sync_marker string default: unsetFilename 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"