# cljfmt [](https://github.com/weavejester/cljfmt/actions/workflows/test.yml) [](https://dl.circleci.com/status-badge/redirect/gh/weavejester/cljfmt)
cljfmt is a tool for detecting and fixing formatting errors in
[Clojure][] code.
Its defaults are based on the [Clojure Style Guide][], but it also has
many customization options to suit a particular project or team.
It is not the goal of the project to provide a one-to-one mapping
between a Clojure syntax tree and formatted text; rather the intent is
to correct formatting errors with minimal changes to the existing
structure of the text.
If you want format completely unstructured Clojure code, the [zprint][]
project may be more suitable.
[clojure]: https://clojure.org/
[clojure style guide]: https://github.com/bbatsov/clojure-style-guide
[zprint]: https://github.com/kkinnear/zprint
## Breaking Changes in 0.11.x
The `--indents` and `--alias-map` keys have been removed from the CLI,
in favor of using a configuration file instead.
The `:indents` key has been split into `:indents` and `:extra-indents`.
The `:indents` key **replaces** all default indents, while the
`:extra-indents` key will **append** to the default indents.
If you need to retain backward compatibility with an older version of
cljfmt, then you can add the `:legacy/merge-indents?` key to your
configuration:
```edn
{:legacy/merge-indents? true
:indents {example.core/foo [[:inner 0]]}}
```
This will treat `:indents` as if it were `:extra-indents`. i.e. it is
equivalent to:
```edn
{:extra-indents {example.core/foo [[:inner 0]]}}
```
## Usage
cljfmt integrates with many existing build tools, or can be used as a
library. As an end user, you have the choice of:
### Standalone
The fastest way to run cljfmt is via a precompiled binary. If you're using
Linux or MacOS, you can run the following command to install the binary into
`/usr/local/bin`:
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/weavejester/cljfmt/HEAD/install.sh)"
```
You can also run this command to update cljfmt to the latest version.
Alternatively, you can install cljfmt via [Homebrew][]. If you do, it's
**highly recommended** that you use the `weavejester/brew` tap. This
will be much more performant than the Homebrew core `cljfmt` package.
```bash
brew install weavejester/brew/cljfmt
```
If you're using Windows, there's a [zipped up binary][] you can download and
extract manually.
To use cljfmt to check for formatting errors in your project, run:
```bash
cljfmt check
```
And to fix those errors:
```bash
cljfmt fix
```
Use `--help` for a list of all the command-line options.
For persistent configuration, you can use a [configuration file][].
[homebrew]: https://brew.sh/
[zipped up binary]: https://github.com/weavejester/cljfmt/releases/download/0.16.4/cljfmt-0.16.4-win-amd64.zip
[configuration file]: #configuration
### Clojure Tools
The official Clojure CLI supports installation of thirdparty [tools][].
To install cljfmt as a tool, run:
```bash
clj -Ttools install io.github.weavejester/cljfmt '{:git/tag "0.16.4"}' :as cljfmt
```
To use the tool to check for formatting errors in your project, run:
```bash
clj -Tcljfmt check
```
And to fix those errors:
```bash
clj -Tcljfmt fix
```
[tools]: https://clojure.org/reference/deps_and_cli#tool_install
### Leiningen
[Leiningen][] is a popular Clojure build tool. To use cljfmt with
Leiningen, add the following plugin to your `project.clj` file:
```clojure
:plugins [[dev.weavejester/lein-cljfmt "0.16.4"]]
```
To use the plugin to check code for formatting errors, run:
```bash
lein cljfmt check
```
And to fix those errors:
```bash
lein cljfmt fix
```
To configure it, put a `:cljfmt` key and a map of options in your
project file. See the [configuration][] section for more details.
[leiningen]: https://github.com/technomancy/leiningen
[configuration]: #configuration
### Library
cljfmt can be run as a library that formats a string of Clojure code or
recursively checks / fixes paths like the CLI tool.
First, add the dependency:
```edn
{:deps {dev.weavejester/cljfmt {:mvn/version "0.16.4"}}}
```
Then use the library:
#### Checking strings of code:
```clojure
(require '[cljfmt.core :as fmt])
(fmt/reformat-string "(defn sum [x y]\n(+ x y))")
;; => "(defn sum [x y]\n (+ x y))"
```
To load the configuration for the current directory:
```clojure
(require '[cljfmt.config :as cfg])
(fmt/reformat-string "(+ x\ny)" (cfg/load-config))
;; => "(+ x\n y)"
```
#### Checking / fixing paths recursively
Be sure to set the report fn to the clojure one as shown below. Otherwise the
`check` and `fix` fns will assume they're running in console mode and will
call `System/exit`, print to stdout, etc.
```clojure
(require '[cljfmt.tool :as fmt]
'[cljfmt.report :as report])
(fmt/check {:paths ["/path/to/check"], :report report/clojure})
```
Or to recursively fix paths:
```clojure
(require '[cljfmt.tool :as fmt]
'[cljfmt.report :as report])
(fmt/fix {:paths ["/path/to/fix"], :report report/clojure})
```
### Babashka
cljfmt can also be used from [Babashka][], either as a library or as a tool that
you define in your `bb.edn` file like so:
```edn
{:deps {dev.weavejester/cljfmt {:mvn/version "0.16.4"}}
:tasks {fmt {:doc "Check formatting with cljfmt"
:requires ([cljfmt.tool :as fmt])
:task (fmt/check {})}}}
```
[babashka]: https://babashka.org/
### Editor Integration
You can also use cljfmt via your editor. Several Clojure editing
environments have support for cljfmt baked in:
* [Calva](https://github.com/BetterThanTomorrow/calva) (Visual Studio Code)
* [CIDER](https://github.com/clojure-emacs/cider) (Emacs)
* [clojureVSCode](https://github.com/avli/clojureVSCode) (Visual Studio Code)
* [vim-cljfmt](https://github.com/venantius/vim-cljfmt) (Vim)
## Configuration
In most environments, cljfmt will look for the following configuration
files in the current and parent directories:
* `.cljfmt.edn`
* `cljfmt.edn`
The configuration file should contain a map of options.
Since 0.16.0, only `.edn` configuration files are loaded by default.
You can enable reading of `.clj` configuration files with the
`--read-clj-config-files` flag:
* `.cljfmt.clj`
* `cljfmt.clj`
If a `.clj` configuration file is detected without this flag, a warning
is printed.
### Leiningen
In Leiningen, the configuration is found in on the `:cljfmt` key in the
project map:
```clojure
:cljfmt {}
```
In order to load the standard configuration file from Leiningen, add the
`:load-config-file?` key to the `:cljfmt` map:
```clojure
:cljfmt {:load-config-file? true}
```
### Formatting Options
* `:alias-map` -
a map of namespace alias to fully qualified namespace names. May be
symbols or strings. This option is unnecessary in most cases, because
cljfmt will parse the `ns` declaration in each file. See [INDENTS.md][].
* `:refer-map` -
a map of referred symbol names to fully qualified namespace names. May be
symbols or strings. This option is unnecessary in most cases, because
cljfmt will parse the `ns` declaration in each file to extract `:refer`
mappings. Used for indentation rules when unqualified symbols need to be
matched against qualified indent rules. See [INDENTS.md][].
* `:aligned-forms` -
a map of symbols to indexes that tell cljfmt where to expect forms it
should align. For example, `{let #{0}}` indicates that the first
argument of let (the binding vector) should be aligned. This option
will **replace** the default aligned forms. Used by
`:align-form-columns?`. **Experimental.**
* `:align-form-columns?` -
true if cljfmt should align the symbols and values within certain
forms (such as `let`) so that they line up in columns. The forms are
defined via the `:aligned-forms` and `:extra-aligned-forms` options.
Defaults to false. **Experimental.**
* `:align-map-columns?` -
true if cljfmt should align the keys and values of maps such that they
line up in columns. Defaults to false. **Experimental.**
* `:align-single-column-lines?` -
true if cljfmt should include lines with single columns (where the
value is on the next line) when calculating column alignment. When
false, forms with wrapped values won't cause excessive horizontal
padding in other lines. Only applies when `:align-form-columns?` or
`:align-map-columns?` is true. Defaults to false. **Experimental.**
* `:max-column-alignment-gap` -
a positive integer that sets the maximum number of spaces allowed
between a key and its aligned value. When alignment would produce
more spaces than this limit on a given row (e.g. due to a long
destructuring key), that row falls back to a single space instead.
Rows with shorter keys are still aligned normally. Useful for
preventing `:align-map-columns?` from producing excessive horizontal
padding in maps that contain outlier keys such as destructuring
forms. Defaults to nil (no limit). **Experimental.**
```clojure
;; Input:
{{:keys [several things here]} :sub-map
{:keys [several things]} :sub-map2
:keys [direct values]
:as everything}
;; With :align-map-columns? true and :max-column-alignment-gap 10:
{{:keys [several things here]} :sub-map ;; 1 space, aligned
{:keys [several things]} :sub-map2 ;; 6 spaces, still aligned (6 ≤ 10)
:keys [direct values] ;; 25 spaces, falls back to 1 space
:as everything} ;; 27 spaces, falls back to 1 space
```
* `:blank-lines-separate-alignment?` -
true if cljfmt should treat blank lines as separators when aligning
columns. When enabled, alignment groups are separated by blank lines,
allowing independent alignment within each group. Defaults to false.
**Experimental.**
* `:blank-line-forms` -
a map of symbols that tell cljfmt which forms are allowed to have
blank lines inside of them. The value may be either `:all`, which
means blank lines are allowed between all elements in the form, e.g.
`{cond :all}` to allow blank lines between any of the elements
inside `cond`; or it may be a set of element indexes that are allowed
to have blank lines, e.g. `{let #{0}}`, to allow blank lines in the
binding of a `let` form. This option will **replace** the default
blank line forms; use `:extra-blank-line` forms to add additional
ones. Used by `:remove-blank-lines-in-forms?`. **Experimental.**
* `:extra-aligned-forms` -
the same as `:aligned-forms`, except that this will **append** to the
default aligned forms. **Experimental.**
* `:extra-blank-line-forms` - the same as `:blank-line-forms`, except that this
will **append** to the default blank line forms. **Experimental.**
* `:extra-indents` -
the same as `:indents`, except that this will **append** to the
default indents.
* `:function-arguments-indentation` -
- `:community` if cljfmt should follow the [community style recommendation][]
to indent function/macro arguments by a single space when there
are no arguments on the same line as the function name.
- `:cursive` if two spaces should be used instead, unless the first
thing in the list (not counting metadata) is a data structure
literal. This should replicate Cursive's default behaviour.
- `:zprint` if two spaces should be used instead if the first thing
in the list is a symbol or keyword. This should replicate zprint's
default behaviour.
Defaults to `:community`
* `:indent-line-comments?` -
true if cljfmt should align whole-line `;;` comments with the code.
Defaults to false.
* `:indentation?` -
true if cljfmt should correct the indentation of your code.
Defaults to true.
* `:indents` -
a map of var symbols to indentation rules, i.e. `{symbol [& rules]}`.
See [INDENTS.md][] for a complete explanation. This will **replace**
the default indents.
* `:normalize-newlines-at-file-end?` -
true if cljfmt should ensure files end with exactly one newline
character. This will remove multiple trailing blank lines and ensure
a final newline exists. Defaults to false.
* `:remove-blank-lines-in-forms?` - whether to remove blank lines inside forms
per the [community style recommendation][no-blank-lines]. By default, this
does not remove blank lines in pairwise constructs like `cond` or within
binding vectors; configure these with `:blank-line-forms` and/or
`:extra-blank-line-forms`. Defaults to false. **Experimental**.
* `:remove-consecutive-blank-lines?` -
true if cljfmt should collapse consecutive blank lines. This will
convert `(foo)\n\n\n(bar)` to `(foo)\n\n(bar)`. Defaults to true.
* `:insert-missing-whitespace?` -
true if cljfmt should insert whitespace missing from between
elements. This will convert `(foo(bar))` to `(foo (bar))`.
Defaults to true.
* `:remove-multiple-non-indenting-spaces?` -
true if cljfmt should remove multiple non indenting spaces. For
example, this will convert {:a 1 :b 2}
to `{:a 1 :b 2}`. Defaults to false.
* `:remove-surrounding-whitespace?` -
true if cljfmt should remove whitespace surrounding inner
forms. This will convert ( foo ) to `(foo)`.
Defaults to true.
* `:remove-trailing-whitespace?` -
true if cljfmt should remove trailing whitespace in lines. This will
convert (foo) \n to `(foo)\n`. Defaults to true.
* `:sort-ns-references?` -
true if cljfmt should alphanumerically sort the requires, imports and
other references in the `ns` forms at the top of your namespaces.
Defaults to false.
* `:split-keypairs-over-multiple-lines?` -
true if cljfmt should break hashmaps onto multiple lines. This will
convert `{:a 1 :b 2}` to `{:a 1\n:b 2}`. Defaults to false.
[indents.md]: docs/INDENTS.md
[community style recommendation]: https://guide.clojure.style/#one-space-indent
[no-blank-lines]: https://guide.clojure.style/#no-blank-lines-within-def-forms
### Runtime Options
* `:file-pattern` -
a regular expression to decide which files to scan. Defaults to
`#”\.clj[csx]?$”`. **Note:** if your configuration is defined in an
edn file, you will need to use a string with the `#re` tag. For
example: `#re "\\.clj[csx]?$"`.
* `:parallel?` -
true if cljfmt should process files in parallel. Defaults to false.
* `:read-clj-config-files?` -
true if cljfmt should read `.clj` config files. For security reasons,
`.clj` config files are ignored by default, as they can execute arbitrary
code. Set this to true to enable reading `.clj` config files. Defaults to false.
* `:paths` -
determines which files and directories to recursively search for
Clojure files. Defaults to checking `src` and `test`, except in
Leiningen where the `:source-paths` and `:test-paths` keys are used
instead.
Paths can also be passed as command line arguments. If the path is
`-`, then the input is STDIN, and the output STDOUT.
## License
Copyright © 2026 James Reeves
Distributed under the Eclipse Public License either version 1.0 or (at
your option) any later version.