nikaia fmt Writes One Style With No Options, Keeps Every Comment, and Never Changes What a Program MeansStatus: Accepted
Date: October 8, 2026 (#101)
Answers: what the formatter Part III 13.2 names does, and what it may
change
Related:
ADR-132 D2 (} else if cond { on one line; a chain is never
unfolded and nested blocks are never folded into one);
ADR-307 D4 (a run of /// before an item is its documentation)
Is .nika formatted in one style that cannot be configured, and what does
the formatter promise about a file it rewrites?
A formatter is only useful if every file in every project looks the same, and
only safe if what it writes means what was there. Without an answer, the first
implementation decides by accident: which options exist, whether a comment
survives, what happens to a dsl block’s SQL.
| Tool | Its answer | Source |
|---|---|---|
gofmt |
one style, no options; a tab per level, spaces only to align; comments kept | from memory, not checked |
zig fmt, elm-format, gleam format |
one style, no options | from memory, not checked |
rustfmt |
one default style, many options in rustfmt.toml; width 100 |
from memory, not checked |
| Prettier | a few options, “opinionated” by design | from memory, not checked |
What transfers: every formatter that ended style debates did it by having
nothing to configure. rustfmt’s options are what a language with a long
history before its formatter needs; Nikaia has none. Go shows that a tab per
level and no options work together at the scale of a whole ecosystem; most
other languages (Python’s PEP 8, Rust, JavaScript) indent with spaces, which
is the habit a newcomer brings.
| Who pays | If it is wrong | |
|---|---|---|
| A — one style, no options | nobody configures; a taste that differs is not served | an option can be added later; one taken away breaks every project that set it |
| B — a default with options | every project that sets one, and every reader who meets two styles | options cannot be withdrawn |
A, because it is the one that can still become B, and because the language already has one spelling per thing (D36 of ADR-286).
No nikaia.toml key and no flag changes the output. One tab per level of
indentation, and nothing else at the start of a line; { at the end of the
line that opens it; no ;; } else if cond { (ADR-132 D2); a line broken at
100 columns, counting a tab as four, after a , or before an operator, with a
trailing , where a list, an argument list or a literal is broken over lines;
at most one blank line in a row.
Nothing is aligned. No line lines up with a column of the line above: a broken argument list goes one level deeper on lines of its own, and a comment at the end of a line follows its code after one space. So the file reads the same at every tab width.
What is read is tolerant, what is written is strict. Indentation is not
part of the syntax, so a file indented with spaces, as an editor without a
tab key writes it, is read like any other; nikaia fmt writes it back with
tabs.
Against it, and the answer. A newcomer from Python, Rust or JavaScript
meets tabs where they expect spaces; the formatter, run on save by the editor
extension, writes them without anyone typing one. A keyboard without a tab
key, on a phone or in a web form, writes spaces, which are read (above). A
viewer that does not know the file’s tab width shows eight columns; the
repository’s .editorconfig says four, which editors and GitHub read.
A // comment and a /// run keep their text and their place: on its own line
before the code it was before, or at the end of the line it ended. The
formatter reads the comments the parser skips; a file that would lose one is
not written. Neither a comment nor a string literal is broken or re-wrapped.
The formatter changes whitespace, line breaks and the trailing , of D1, and
nothing else: no name, no order, no parentheses. A file is lowered before and
after, and a difference in what it lowers to is an error of the formatter, not
written. Formatting a formatted file changes nothing.
dsl block’s body is kept as written.What stands between a dsl header and eod is another language’s text, and
the formatter does not touch it. A grammar is Nikaia and is formatted.
nikaia fmt rewrites, nikaia fmt --check reports.nikaia fmt formats every .nika file of the package in place, or the files
it is given. --check writes nothing, names each file that would change, and
fails where one would, for CI.
--check can join CI’s other format checks.