Configuration

A project configures Ur in .ur/ur.toml, in a .ur directory at its root. Ur reads the nearest one at or above each file, up to the repository’s root, and only that one.

Without an ur.toml, each style reads its formatter’s own configuration the way that formatter finds it, such as Prettier’s .prettierrc, Black’s pyproject.toml, rustfmt.toml, .rubocop.yml, .sqlfluff, and .editorconfig. With one, ur.toml decides, and Ur warns about each setting in those files that disagrees with it.

target = ["python-3.11", "typescript-5.9"]

[format]
width = 100
indent = { width = 4, style = "spaces" }
trailing-comma = { add = "multiline", forces-break = true }

[format.javascript]
quotes = "single"
prettier = { arrow-parens = "avoid" }

[format.sql]
style = "river"

[[format.overrides]]
files = ["**/*.test.ts"]
width = 120

[lint]
files = { exclude = ["vendor/"] }

[lint.long-file]
max-lines = 800

target

The language versions the code targets, as Ur’s profiles name them, such as python-3.11 or sql-postgres-18. Every command reads it: Ur parses each file as the newest profile its language targets, and a style that formats differently by version, as Black does, formats for the versions targeted. A profile names its language, so one list covers a project’s languages. ur format --profile sets it for one run.

[format]

How ur format lays files out. The options in [format] apply to every language; the shared options below are the same for every style, so width = 100 sets Prettier’s printWidth, Black’s line-length, and rustfmt’s max_width alike.

A language’s table

[format.<language>], such as [format.python] or [format.sql], sets options for that language alone, over [format]. Its style chooses the style that formats the language, where it has more than one, as SQL has sqlfluff and river. ur format --style chooses it for one run.

A style’s own options

A table named for a style sets its own options, in [format] or in a language’s table: [format.prettier], or prettier = { arrow-parens = "avoid" }. Options are written as ur.toml names them: Prettier’s and rustfmt’s in kebab case, such as arrow-parens for arrowParens, and the others as the tool writes them. A style that groups its options, as RuboCop does by cop, takes a table for each group, such as "Layout/DotPosition" = { EnforcedStyle = "trailing" }. Each style’s page lists its options.

files

files = { include = [...], exclude = [...] } chooses the files ur format formats, in [format] or in a language’s table. Each entry is a glob: one with a / matches a path from the project’s root, and covers everything under a directory it matches; one without matches a file or directory name anywhere. exclude wins over include, and when include is set, a file must match one of its globs.

[[format.overrides]]

Each [[format.overrides]] table sets options for the files its files globs match, over everything else. Later overrides win over earlier ones.

[lint]

What ur lint and ur check add to their rules for a project.

The text rules

A table for one of the rules that read files as text turns that rule on: [lint.long-file], [lint.deep-nesting], [lint.stray-emoji], [lint.stray-todo], [lint.hardcoded-color], [lint.inline-svg], [lint.hardcoded-font], and [lint.ad-hoc-motion]. Each takes exclude, globs of the files it leaves out, such as generated data or the theme file that defines a project’s colours. [lint.long-file] takes max-lines, 1500 unless it says, and [lint.deep-nesting] takes max-depth.

The rules were renamed so that each name says what is wrong, and a table may still go by its rule’s old name: [lint.file-length], [lint.emoji], [lint.color], [lint.inline-font], [lint.motion], and [lint.env-file] still work. --rule and ur-allow comments take the old names too.

[check]

Where ur check expects a project’s working notes and shell scripts, relative to the directory it checks.

The shared options

Every style takes these, in [format], a language's table, or an override, under the same names whatever its formatter calls them.

OptionValuesWhat it does
widtha numberThe line width code is fitted within, in columns, measured as the style's reference formatter measures it.
indent.widtha numberThe columns each level of indentation adds.
indent.style"spaces", "tabs"Whether indentation is written with spaces or tabs.
line-ending"lf", "crlf", "cr", "auto", "native"The line ending written at the end of each line.
trailing-comma.add"never", "multiline", "always", "es5", "preserve"When a trailing comma is added after the last item of a broken list.
trailing-comma.forces-breaktrue or falseWhether a trailing comma already in a list keeps the list broken across lines, as Black's magic trailing comma does.
quotes"double", "single", "preserve"The quotes strings are written with, where the language lets either do.
targeta list of profiles, such as "python-3.11"The language versions the code targets, as Ur's profiles name them, such as python-3.11: Ur parses with the newest, and a style that formats differently by version, as Black does, formats for them.

Each style's own options

A style's own options go in a table named for it. Each style's page lists them, with its defaults for the shared options. Options that only change how its formatter runs, such as --check, are left out.

StyleFormatsOptions
blackPython8
google-java-formatJava6
mathlibLeanNone of its own
prettierJavaScript, TypeScript, Markdown22
riverSQL1
rubocopRuby226
rustfmtRust22
sqlfluffSQL135
tla2toolsTLA+None of its own