Enforcing Consistent Elm Style With elm-format
How elm-format eliminates style debates in Elm projects through deterministic, zero-config formatting and CI integration.
14 Jul 2025, 08:17 UTC

The Cost of Manual Formatting in Elm Reviews
In many Elm projects, code reviews can devolve into bike-shedding—spending disproportionate time debating trailing commas, indentation levels, or where to place a closing parenthesis. When formatting relies on individual preference, git diffs accumulate whitespace changes that obscure the actual logic modifications, making auditing and merging a chore. The Elm ecosystem provides a built-in solution: elm-format.
This article explores how elm-format works, how to integrate it across editor and CI environments, and what trade-offs teams should consider before adopting it. The tool processes each file independently, applying a consistent set of rules derived from the Elm language specification, which means the output is fully reproducible across different machines and operating systems.
Deterministic Canonical Layout
elm-format is a deterministic, zero-configuration tool that rewrites Elm source files into a single canonical layout. It normalizes spacing around operators, handles line breaks for long function signatures, and enforces consistent indentation—all while preserving the original semantics of the code. Because it requires no configuration file, there is no ongoing maintenance of style toggles, and new developers immediately match the project standard. The tool respects Elm’s syntactic rules, ensuring that formatting changes do not alter behavior.
Integration Across the Development Flow
Editor Integration
Most Elm developers use editors with official plugin support, such as VS Code or IntelliJ. Enabling format-on-save ensures that code is automatically rewritten to the canonical layout before commit, reducing the friction of the tool's opinionated nature and giving developers immediate feedback within their workflow.
CI Enforcement with --check
To prevent unformatted code from reaching a repository's default branch, elm-format can be invoked in Continuous Integration pipelines with the --check flag. This command checks whether all source files match the canonical layout without modifying them. If every file is already formatted, the command exits with status 0. If any file deviates, it outputs a diff and exits with a non-zero status, causing the build to fail until formatting issues are resolved. Because the check operates on the entire source set, a single unformatted file can block a merge, which encourages teams to address formatting as part of their regular development cycle rather than as a separate cleanup step.
| Scenario | Command | Expected Outcome |
|---|---|---|
| Local formatting pass | elm-format src/Main.elm | File is rewritten in place to match canonical style. |
| CI compliance check | elm-format --check src/Main.elm | Exits 0 if formatted; exits non-zero with diff if changes are needed. |
Trade-offs and Limitations
The primary limitation of elm-format is its lack of fine-grained customization. It does not support aligning multi-line function arguments to a specific column or ignoring blocks of code for readability reasons. This opinionated rigidity is intentional: by removing the ability to customize, the tool removes the possibility of style-related team conflict. Projects requiring specific formatting exceptions must adapt their code to the formatter's default style. Additionally, because elm-format rewrites files in place, teams must ensure that generated code is committed and that any manual formatting exceptions are avoided to prevent merge conflicts. Some teams initially resist the fixed style, but many report that the reduction in review friction and the consistency gained across a large codebase outweigh the adjustment period.
Getting Started and Verification
To adopt elm-format, install the package (typically via npm install elm-format or your project's package manager), enable format-on-save in your editor plugin, and add a elm-format --check step to your CI configuration. Verify the integration by running the check on a sample Elm file and confirming that the exit code reflects the file's formatting state: exit 0 means the file is already canonical, while a non-zero exit indicates required changes.
For a practical check, create an Elm file with intentional spacing inconsistencies and run elm-format --check Path/To/File.elm. The tool should output a diff showing the adjustments it would apply, confirming that the enforcement mechanism is active. After the initial integration, periodic runs of elm-format --check on the full repository help catch formatting drift early, especially as new files are added or existing ones are refactored.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.