Configuration
badness is configured through a badness.toml file. All keys are optional and
spelled in kebab-case; an unknown key or section is a hard error, not a silent
no-op. Run badness init to write a commented starter file showing every key at
its default.
# Gitignore-style patterns to skip during directory discovery.
# exclude = [".git/"]
# extend-exclude = []
[format]
# line-width = 80
# indent-width = 2
# wrap = "reflow" # reflow | sentence | semantic | preserve
[lint]
# select = ["..."] # if set, only these rules run
# ignore = [] # rules to disable
Discovery
For each input, badness walks from the file’s directory upward and uses the
first badness.toml it finds. The walk stops at a directory containing a .git
entry (the repository root), so a config outside your repository is never picked
up. If no file is found, built-in defaults apply.
Two global CLI flags override discovery:
--config <PATH>uses that file instead of discovering one.--no-configignores any discovered file and uses built-in defaults.
CLI flags for individual options (--line-width, --wrap, --select, …)
override the corresponding config values for a single run.
Top level
exclude
Gitignore-style patterns to exclude from directory discovery, resolved relative
to the directory containing the badness.toml. Excludes apply to both format
and lint, which share one file walk, so this is a top-level key rather than a
[format] option.
When set, this replaces the built-in default set ([".git/"]); use
extend-exclude to add patterns without restating the
defaults. Patterns given with the --exclude CLI flag are always added on top.
Default value: [".git/"]
Type: array of strings
Example:
exclude = ["vendor/", "old-drafts/"]
extend-exclude
Gitignore-style patterns added in addition to the base set selected by
exclude (the built-in defaults when exclude is unset). Use this
to skip a few extra paths without replacing the defaults.
Default value: []
Type: array of strings
Example:
extend-exclude = ["build/"]
[format]
Options for badness format. Each mirrors a CLI flag of the same name, which
takes precedence for a single run.
line-width
Maximum line width before the formatter breaks a line. Must be between 1 and 1000.
Default value: 80
Type: integer
Example:
[format]
line-width = 100
indent-width
Spaces per indent step. Must be between 1 and 1000.
Default value: 2
Type: integer
Example:
[format]
indent-width = 4
wrap
How the formatter lays out line breaks inside a paragraph. It does not affect structure—only where soft line breaks fall.
| Mode | Behavior |
|---|---|
reflow | Greedy fill: pack words up to line-width, breaking only where the next word would overflow. |
preserve | Leave the authored line breaks untouched. |
sentence | One sentence per line. Line width is ignored—a long sentence stays on one line. |
semantic | Semantic line breaks: keep the author’s soft breaks and add a break after each sentence. |
Both sentence and semantic split a paragraph at sentence boundaries, one
sentence per line. Boundary detection is a small per-language rule engine over
the words: a ., !, or ? ends a sentence unless the word is a known
abbreviation (e.g., Fig., Dr., …), an ellipsis (..., …), or a
contextual abbreviation whose following word signals that the sentence continues
(U.S. Government stays together, U.S. However splits). The abbreviation
profile is chosen by lang and extended by
no-break-abbreviations.
semantic additionally preserves the author’s own line breaks on top of the
sentence breaks (the sembr convention). It does not detect
clause boundaries itself—a break after a comma or and survives only where the
author placed a newline. A run-on sentence on a single source line is still
sentence-split.
When omitted, the formatter uses each file kind’s default: .tex and .bib
files reflow, while code-heavy .sty, .cls, .dtx, and .ins files preserve
authored line breaks. Setting wrap applies the same mode to every file kind.
Default value: unset (per file kind: .tex/.bib → reflow,
.sty/.cls/.dtx/.ins → preserve)
Type: "reflow" | "sentence" | "semantic" | "preserve"
Example:
[format]
wrap = "sentence"
lang
Document language as a BCP-47-style code (en, de, pt-BR, …), used by the
sentence and semantic wrap modes to pick the sentence-boundary abbreviation
profile. Built-in profiles cover English (default), Czech, German, Spanish, and
French; the region subtag is folded away, and an unknown or unset language falls
back to English. (Automatic detection from babel/polyglossia is not yet
implemented.)
Default value: unset (English)
Type: string
Example:
[format]
lang = "de"
no-break-abbreviations
User-supplied no-break abbreviations for the sentence and semantic wrap
modes, keyed by language code or the literal default bucket (applied to every
document). An abbreviation listed here never ends a sentence, so no line break
is inserted after it. Merged on top of the built-in per-language lists.
Default value: {}
Type: table of string arrays, keyed by language code or default
Example:
[format.no-break-abbreviations]
default = ["ibid."] # applied to every document
de = ["bzw.", "Abb."] # applied only when lang resolves to German
[lint]
Rule selection for badness lint, shared by the LaTeX and
BibTeX rule sets. Every rule is on by default. An unknown
rule id is reported at lint time, not rejected at config-parse time.
select
Explicit allowlist of rule ids. When set, only these rules run.
Default value: unset (all rules run)
Type: array of strings
Example:
[lint]
select = ["deprecated-command", "dollar-display-math"]
ignore
Rule ids to disable, applied on top of either select or the default
rule set.
Default value: []
Type: array of strings
Example:
[lint]
ignore = ["missing-nonbreaking-space"]
[build]
Where the TeX compiler leaves its artifacts. Read by the language server
only, which pulls resolved label and section numbers from the .aux files for
hover and document symbols; never by the formatter or linter.
aux-dir
Directory holding the build’s .aux files (latexmk’s -auxdir/-outdir),
resolved relative to the root document’s directory when not absolute. When
unset, each document’s .aux is expected next to it, as in plain
latex/pdflatex runs.
Default value: unset (sibling .aux files)
Type: path
Example:
[build]
aux-dir = "out"
Note: TEXMF-tree discovery (the former
[texmf]section) is configured through your editor’s LSP settings, notbadness.toml. Where a TeX installation lives is a fact about the machine, not the project, so it does not belong in a file shared across contributors. See Editor Setup.