Skip to content

Instantly share code, notes, and snippets.

@cmungall
Created April 3, 2026 02:09
Show Gist options
  • Select an option

  • Save cmungall/64ba8a4c9ee4201972a3e99f3298c86b to your computer and use it in GitHub Desktop.

Select an option

Save cmungall/64ba8a4c9ee4201972a3e99f3298c86b to your computer and use it in GitHub Desktop.

Normalizing YAML Formatting: yamlfix vs Prettier and the State of Standards

Executive summary

There is no broadly accepted, tool‑independent "canonical YAML formatting profile" comparable to Black for Python or gofmt for Go; each formatter defines its own style, and these styles are not standardized across tools. yamlfix and Prettier both provide opinionated YAML formatting, but they differ significantly in scope, defaults, configuration model, and how aggressively they normalize YAML constructs, meaning switching between them will generally cause large diffs rather than clean no‑ops. Some tools (e.g., Google’s yamlfmt and Carvel’s yamlfmt) describe their output as a "canonical form", but this is a per‑tool convention, not a YAML‑spec profile that other tools target. As a result, the practical way to avoid spurious diffs today is to pick a single formatter, standardize on its configuration across the repo, and wire it into pre‑commit/CI; changing formatter families later will almost certainly reformat the entire corpus once.[1][2][3][4][5][6][7]

yamlfix: focus and behavior

yamlfix is a Python‑based, "simple opinionated YAML formatter" whose explicit design goal is to normalize YAML while preserving comments. By default it performs a series of transformations: it adds a --- document header, normalizes truthy/falsey scalars (e.g. 'True' to true, 'no' to false), removes unnecessary quotes, "corrects" comments, enforces a single trailing newline, wraps long lines, converts short lists to flow style, and converts long lists to block style, while respecting Jinja2 templating syntax. These transformations go beyond whitespace and indentation and into semantic normalization of scalar representations, which is useful for consistency but makes yamlfix’s output quite specific to yamlfix.[8][1]

yamlfix discovers configuration using the maison library so that settings can be provided in standard config locations and via environment variables. Its configuration surface includes aspects like line width and list formatting, but the project is explicitly marketed as "opinionated", meaning many choices are not user‑tunable and are intended to remain stable defaults. Because it is implemented in Python and distributed via pip and Homebrew, it integrates naturally into Python‑centric toolchains and pre‑commit hooks for projects that already depend on Python.[1][8]

Prettier: general‑purpose, multi‑language formatter

Prettier is a general‑purpose formatter for many languages and data formats (JavaScript/TypeScript, JSON, Markdown, YAML, etc.) with a strong philosophy of being opinionated and offering only a small set of configuration options. YAML support was added in Prettier 1.14 using the yaml package by eemeli, with an implementation described as "highly compliant with the YAML spec". For YAML, Prettier focuses on layout: consistent indentation (default two spaces), wrapping of long lines, and formatting of lists and mappings, and it also has special behavior such as word‑wrapping prose in string blocks in a similar way to Markdown when this does not change meaning.[9][4][10][6][11]

Prettier’s configuration is intentionally limited to generic options like printWidth, tabWidth, useTabs, and proseWrap, rather than detailed, YAML‑specific knobs. Its maintainers emphasize that Prettier is "not a kitchen‑sink code formatter that attempts to print your code in any way you wish", and that users cannot configure it to arbitrary styles such as zero‑indented sequences that diverge from its chosen conventions. Prettier preserves YAML comments in general, but there are open issues where comments are moved or stripped in certain edge cases (e.g. in front matter blocks or adjacent to particular syntax elements), which can matter if comments are semantically important.[4][10][12][13][14]

Direct comparison: yamlfix vs Prettier for YAML normalization

The tools differ in several dimensions that matter for diff stability and long‑term maintainability.

Aspect yamlfix Prettier (YAML)
Primary scope YAML‑only formatter (Python ecosystem) General multi‑language formatter (Node ecosystem)
Design goal Opinionated YAML normalization with comment preservation and some semantic cleanup Opinionated, stable formatting across many languages, minimal config, YAML included as one language
Semantic normalization Normalizes booleans ('True'true, 'no'false), removes unnecessary quotes, enforces --- header and single trailing newline by default Focuses mainly on layout; uses YAML parser/emitter but does not aggressively canonicalize scalar representations beyond what the parser/emitter does
Lists Converts short lists to flow style and long lists (beyond line width) to block style Formats sequences with consistent indentation and wrapping, but does not advertise flow/block switching heuristics as a key feature
Comments Explicitly designed to keep comments and to "correct" them, respecting Jinja2 syntax Preserves most comments but has known issues where comments can be moved or removed in certain cases (e.g. front matter, comments near brackets)
Configuration Uses maison to discover configuration; exposes formatter options but remains generally opinionated Limited set of global formatting options (printWidth, tabWidth, etc.); little YAML‑specific configurability
Ecosystem integration Natural fit for Python tooling and pre‑commit hooks; packaged via pip and Homebrew Widely used across JS/TS ecosystems; easy to standardize one formatter for many file types (YAML, JSON, Markdown, code)

[10][12][13][6][14][11][9][8][4][1]

Because yamlfix performs more semantic normalization (boolean representations, header insertion, quoting rules) while Prettier aims for consistent layout with minimal semantics‑changing rewrites, the two tools will typically produce different outputs even for already‑formatted files. Switching a repository from one to the other will therefore trigger extensive diffs the first time the new formatter is run, and there is no shared notion of "profile X" that makes their outputs converge.[2][6][1]

Are there standard YAML formatting profiles?

The YAML 1.2.2 specification defines a concept of canonical form, but this is scoped to scalar equality: each scalar tag must define a canonical Unicode character string representation so that scalar values can be compared, not a canonical layout of entire documents (indentation, header presence, flow vs block, comment placement, etc.). The spec also intentionally leaves many presentational aspects optional—such as whether a leading --- document start marker is used—which leads to divergent tooling behavior. The absence of a full document‑level canonicalization in the spec means that formatters are free to choose their own styles.[3][2]

There has been explicit discussion in the YAML spec repository about defining a "documented normalized YAML style" to give the ecosystem a canonical reference for formatters and linters. That proposal calls out exactly the problem you describe: without a canonical style, reviewers argue about optional features like document start markers, and tools make incompatible choices. As of the latest discussion, this issue remains open and there is no ratified, spec‑level style profile for YAML formatting beyond scalar canonicalization.[2]

Tool‑specific "canonical" styles (yamlfmt and others)

In practice, some tools define their own internal notion of a canonical YAML form, but these are not standardized across implementations.

  • Google’s yamlfmt describes itself as formatting YAML "into a canonical form", with properties such as sorted mapping keys, two‑space indentation, lists that are not indented, and always‑present --- document separators. It also offers options like sorting sequences and maps, with explicit warnings that some options can break anchors and aliases, underlining that this is a pragmatic convention rather than a safe, spec‑mandated canonicalization.[7][15]
  • Carvel’s yamlfmt package similarly states that it "implements the fmt command — formatting YAML (preserving comments) into a canonical form", again using "canonical" in a tool‑local sense.[5]
  • Other formatters, including Prettier and yamlfix, are described as opinionated rather than canonical, emphasizing stability of style over cross‑tool equivalence.[6][1]

A survey of YAML formatters by xkyle.com emphasizes that different tools make materially different formatting choices: for example, some homogenize horizontal whitespace and aggressively rewrite multiline strings, while Prettier tends to preserve multiline string forms but normalize indentation and spacing. The survey’s overall conclusion is that there is no formatter whose behavior is both universally desirable and aligned across tools, reinforcing that "canonical" today means "canonical for this specific formatter".[6]

Implications for avoiding diff noise

Because there is no cross‑tool canonical YAML style, targeting a hypothetical profile X and expecting multiple independent tools to conform to it is not realistic today. Instead, stability is achieved by standardizing on a single formatter (and configuration) for a repository and ensuring that all contributors and CI use exactly that formatter.[3][2][6]

The common pattern in active YAML‑heavy projects is to:

  • Choose one formatter (e.g. yamlfix, Prettier, or a yamlfmt flavor) whose behavior and ecosystem fit the project’s needs.[7][1][6]
  • Configure it once (e.g. line width, indentation width, whether to add document start markers) and codify that configuration in the repo via pre-commit hooks or CI checks so every change is normalized the same way.[16][15]
  • Accept that switching formatter families later will cause a one‑time, repo‑wide reformat that is best done in a dedicated commit or PR to isolate the diff from semantic changes.[6]

When combining tools, projects often disable overlapping formatting responsibilities: for example, teams using Prettier for YAML will disable conflicting YAML formatters in IDE extensions, or configure yamllint to only lint, not auto‑fix, to avoid fighting with Prettier’s output. Where YAML is generated by code, some teams instead generate JSON and then feed it through a single YAML emitter/formatter to ensure formatting is centralized in one component, again to avoid divergent styles.[14][17][4][6]

Practical guidance for future toolchain changes

For a project that wants to minimize diff noise yet keep the option of later changing tools, the most practical approach today is:

  • Pick a single formatter now (yamlfix or Prettier) and treat its style as authoritative; wire it into pre‑commit and/or CI.
  • Keep non‑trivial formatting‑affecting options in a small, documented configuration file so that if another tool later wants to emulate that style, the desired properties are explicit (e.g. 2‑space indent, require ---, sorted keys, flow vs block rules).
  • If a future formatter advertises explicit compatibility with your current tool’s style (for example, a new formatter that implements "yamlfmt‑style" or "Prettier‑style" profiles), evaluate it on a sample of files and compare diffs; absent such a compatibility claim, assume a repo‑wide one‑time reformat will be necessary.

Given today’s ecosystem and the lack of a YAML‑spec canonical profile, toolchain‑independent, diff‑free switching is not achievable; stability instead comes from committing to one formatter and isolating any future formatter switch into a deliberate, repository‑wide reformat.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment