beetbox / beetbox/beets

Autogenerate config file with schema

Open
#5,971 2 comments 0 reactions 0 assignees View on GitHub
feature
Dominant language
Python
Stars
15.7k
Forks
2.1k
Avg merge
4d 21h
Merged PRs (30d)
31

Description

### Proposed solution

When you first run beets (or run `beets config`), then always generate an empty config file in the default location if missing. also set up the yaml schema for the configuration somewhere on the website / store it locally.

### Objective

Allow editors to have LSP support to make sure there are no errors in the file.

Image

Here is a YAML schema I generated using AI (it has issues. but it's a good starting point I think)

```yaml
type: object
properties:
library:
type: string
description: Path to the beets library file (e.g., library.db).
directory:
type: string
description: The destination directory for imported music files.
plugins:
type: array
items:
type: string
description: A list of plugin module names to load.
include:
type: array
items:
type: string
description: A list of extra configuration files to include.
pluginpath:
type: [string, array]
items:
type: string
description: A single path or a list of paths to search for plugins.
ignore:
type: array
items:
type: string
description: A list of glob patterns for files/directories to ignore during import.
default: [".*", "*~", "System Volume Information", "lost+found"]
ignore_hidden:
type: boolean
description: Whether to ignore hidden files when importing.
replace:
type: object
additionalProperties:
type: string
description: A map of regular expressions to replacement strings for filenames.
path_sep_replace:
type: string
description: A string to replace the OS-native path separator in generated filenames.
default: "_"
asciify_paths:
type: boolean
description: If true, converts all non-ASCII characters in paths to ASCII equivalents.
default: false
art_filename:
type: string
description: The template for the album art filename (without extension).
default: "cover"
threaded:
type: boolean
description: Whether the autotagger should use multiple threads for faster processing.
default: true
format_item:
type: string
description: The format string for displaying individual items (tracks).
default: "$artist - $album - $title"
format_album:
type: string
description: The format string for displaying albums.
default: "$albumartist - $album"
sort_item:
type: string
description: The default sort order for items.
default: "artist+ album+ disc+ track+"
sort_album:
type: string
description: The default sort order for albums.
default: "albumartist+ album+"
sort_case_insensitive:
type: boolean
description: If true, sorting of text fields is case-insensitive.
default: true
original_date:
type: boolean
description: If true, sets year/month/day fields to the original release date.
default: false
overwrite_null:
type: object
properties:
album:
type: array
items: { type: string }
track:
type: array
items: { type: string }
description: Defines which fields can be overwritten with a null value.
artist_credit:
type: boolean
description: If true, uses the "artist credit" string instead of the main artist.
per_disc_numbering:
type: boolean
description: If true, track numbering restarts for each disc in a multi-disc release.
default: false
aunique:
type: object
properties:
keys:
type: array
items: { type: string }
disambiguators:
type: array
items: { type: string }
bracket:
type: string
description: Options for generating a unique string to disambiguate albums.
sunique:
type: object
properties:
keys:
type: array
items: { type: string }
disambiguators:
type: array
items: { type: string }
bracket:
type: string
description: Options for generating a unique string to disambiguate singletons.
terminal_encoding:
type: string
description: The text encoding for console input and output.
clutter:
type: array
items:
type: string
description: Glob patterns for ignorable files (e.g., .DS_Store) in otherwise empty directories.
default: ["Thumbs.DB", ".DS_Store"]
max_filename_length:
type: integer
description: The maximum number of characters allowed in a filename.
id3v23:
type: boolean
description: If true, writes ID3v2.3 tags instead of the default ID3v2.4.
default: false
va_name:
type: string
description: The albumartist name used for various-artist compilations.
default: "Various Artists"
ui:
type: object
description: Options for customizing the console user interface.
properties:
color:
type: boolean
description: If true, enables color in the console output.
colors:
type: object
additionalProperties:
type: array
items:
type: string
description: A mapping of UI elements to their desired colors and styles.
terminal_width:
type: integer
description: The width of the terminal in characters, for line wrapping.
default: 80
length_diff_thresh:
type: number
description: Threshold in seconds for highlighting track length differences.
default: 10.0
import:
type: object
properties:
indentation:
type: object
properties:
match_header: { type: integer }
match_details: { type: integer }
match_tracklist: { type: integer }
layout:
type: string
enum: [column, newline]
import:
type: object
description: Options that control the import command.
properties:
write:
type: boolean
description: If true, writes metadata tags to music files.
default: true
copy:
type: boolean
description: If true, copies files into the library directory.
default: true
move:
type: boolean
description: If true, moves files into the library directory (overrides copy).
default: false
link:
type: boolean
description: If true, creates symbolic links instead of copying/moving.
default: false
hardlink:
type: boolean
description: If true, creates hard links instead of copying/moving.
default: false
reflink:
type: string
enum: [yes, no, auto]
description: If true, uses copy-on-write reflinks instead of copying/moving.
default: "no"
resume:
type: string
enum: [yes, no, ask]
description: Controls whether to resume interrupted imports.
default: "ask"
incremental:
type: boolean
description: If true, skips previously imported directories.
incremental_skip_later:
type: boolean
description: If true, skipped directories are not recorded and can be imported later.
default: false
from_scratch:
type: boolean
description: If true, discards existing metadata from files when matching.
default: false
quiet:
type: boolean
description: If true, never asks for user input, taking the best guess or skipping.
default: false
quiet_fallback:
type: string
enum: [skip, asis]
description: What to do in quiet mode when there's no strong recommendation.
default: "skip"
none_rec_action:
type: string
enum: [ask, asis, skip]
description: What to do in interactive mode when there is no recommendation.
default: "ask"
timid:
type: boolean
description: If true, asks for confirmation on every autotagger match.
default: false
log:
type: string
description: Path to a file for logging importer activity.
default_action:
type: string
enum: [apply, skip, asis, none]
description: The default action to take when prompted during import.
default: "apply"
languages:
type: array
items: { type: string }
description: A list of preferred language codes for metadata (e.g., 'en').
ignored_alias_types:
type: array
items: { type: string }
description: A list of alias types from MusicBrainz to ignore.
detail:
type: boolean
description: If true, shows detailed track information for every match candidate.
default: false
group_albums:
type: boolean
description: If true, groups tracks into albums based on metadata instead of directories.
default: false
autotag:
type: boolean
description: If false, disables the autotagging process entirely.
default: true
duplicate_keys:
type: object
properties:
album:
type: array
items: { type: string }
item:
type: array
items: { type: string }
description: Fields used to detect duplicate albums and items.
duplicate_action:
type: string
enum: [skip, keep, remove, merge, ask]
description: Action to take when a duplicate is found.
default: ask
duplicate_verbose_prompt:
type: boolean
description: If true, shows detailed track info when a duplicate is found.
default: false
bell:
type: boolean
description: If true, rings the terminal bell when input is needed.
default: false
set_fields:
type: object
additionalProperties:
type: string
description: A map of field names to values to set on all imported music.
singleton_album_disambig:
type: boolean
description: If true, adds the album name to the disambiguation string for singletons.
default: true
musicbrainz:
type: object
description: Options for connecting to the MusicBrainz service.
properties:
host:
type: string
description: The hostname of the MusicBrainz server.
default: "musicbrainz.org"
https:
type: boolean
description: Whether to use HTTPS for custom MusicBrainz servers.
default: false
ratelimit:
type: integer
description: Web service requests per second (do not change for public server).
default: 1
enabled:
type: boolean
description: Set to false to disable MusicBrainz as a metadata source.
default: true
searchlimit:
type: integer
description: The number of matches to return from MusicBrainz searches.
default: 5
extra_tags:
type: array
items:
type: string
enum: [year, catalognum, country, media, label]
description: A list of additional tags to use when querying MusicBrainz.
genres:
type: boolean
description: If true, uses MusicBrainz genres to populate the genre tag.
default: false
external_ids:
type: object
properties:
discogs: { type: boolean }
spotify: { type: boolean }
bandcamp: { type: boolean }
beatport: { type: boolean }
deezer: { type: boolean }
tidal: { type: boolean }
description: If true for a source, imports linked external IDs from MusicBrainz.
match:
type: object
description: Options to configure the autotagger's matching logic.
properties:
strong_rec_thresh:
type: number
description: Distance threshold below which a match is a "strong recommendation".
default: 0.04
medium_rec_thresh:
type: number
description: Distance threshold below which a match is a "medium recommendation".
rec_gap_thresh:
type: number
description: Distance threshold between the best and second-best match.
max_rec:
type: object
additionalProperties:
type: string
enum: [none, low, medium, strong]
description: Maximum recommendation level for matches with specific penalties.
preferred:
type: object
properties:
countries:
type: array
items: { type: string }
media:
type: array
items: { type: string }
original_year:
type: boolean
description: Preferred countries, media types, and original release year for matches.
ignored:
type: array
items: { type: string }
description: A list of penalties that will cause a match to be completely ignored.
required:
type: array
items: { type: string }
description: A list of tags that must be present in a match.
ignored_media:
type: array
items: { type: string }
description: A list of media types to ignore during matching (e.g., DVD-Video).
ignore_data_tracks:
type: boolean
description: If true, audio files on data tracks are ignored.
default: true
ignore_video_tracks:
type: boolean
description: If true, video tracks are ignored.
default: true
paths:
type: object
description: Configuration for the directory and file naming structure.
additionalProperties:
type: string
properties:
default:
type: string
description: The path format for standard album releases.
default: "$albumartist/$album%aunique{}/$track $title"
singleton:
type: string
description: The path format for non-album tracks.
default: "Non-Album/$artist/$title"
comp:
type: string
description: The path format for various-artist compilations.
default: "Compilations/$album%aunique{}/$track $title"

```

Contributor guide

Open the contributing guide

Research direction

Start with the `beets` first-run and `beets config` entry points, then trace how the default configuration path is selected and how missing files are handled. Compare the proposed YAML schema with the project’s actual configuration options and decide where the schema belongs. Done means a missing config is generated and editors can use an accurate schema for validation.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, developer-experience
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.