Skip to content

Configure Treefmt

The treefmt.toml configuration file consists of a mixture of global options and formatter sections:

excludes = ["*.md", "*.dat"]

command = "elm-format"
options = ["--yes"]
includes = ["*.elm"]

command = "gofmt"
options = ["-w"]
includes = ["*.go"]

command = "black"
includes = ["*.py"]

# use the priority field to control the order of execution

# run shellcheck first
command = "shellcheck"
includes = ["*.sh"]
priority = 0    # default is 0, but we set it here for clarity

# shfmt second
command = "shfmt"
options = ["-s", "-w"]
includes = ["*.sh"]
priority = 1

Global Options

  • excludes - an optional list of glob patters used to exclude certain files from all formatters.

Formatter Options

  • command - the command to invoke when applying the formatter.
  • options - an optional list of args to be passed to command.
  • includes - a list of glob patterns used to determine whether the formatter should be applied against a given path.
  • excludes - an optional list of glob patterns used to exclude certain files from this formatter.
  • priority - influences the order of execution. Greater precedence is given to lower numbers, with the default being 0.

Same file, multiple formatters?

For each file, treefmt determines a list of formatters based on the configured includes / excludes rules. This list is then sorted, first by priority (lower the value, higher the precedence) and secondly by formatter name (lexicographically).

The resultant sequence of formatters is used to create a batch key, and similarly matched files get added to that batch until it is full, at which point the files are passed to each formatter in turn.

This means that treefmt guarantees only one formatter will be operating on a given file at any point in time. Another consequence is that formatting is deterministic for a given file and a given treefmt configuration.

By setting the priority fields appropriately, you can control the order in which those formatters are applied for any files they both happen to match on.

Supported Formatters

Here is a list of all the formatters we tested. Feel free to send a PR to add other ones!


An opinionated code formatter that supports many languages.

command = "prettier"
options = ["--write"]
includes = [


A python formatter.

command = "black"
includes = ["*.py"]


A tool to format C/C++/Java/JavaScript/Objective-C/Protobuf/C# code.

command = "clang-format"
options = [ "-i" ]
includes = [ "*.c", "*.cpp", "*.cc", "*.h", "*.hpp" ]

Note: This example focuses on C/C++ but can be modified to use with other languages.


command = "elm-format"
options = ["--yes"]
includes = ["*.elm"]


command = "gofmt"
options = ["-w"]
includes = ["*.go"]


Haskell formatter. Make sure to use ormolu as older versions don't adhere to the spec.

command = "ormolu"
options = [
    "--ghc-opt", "-XBangPatterns",
    "--ghc-opt", "-XPatternSynonyms",
    "--ghc-opt", "-XTypeApplications",
    "--mode", "inplace",
includes = ["*.hs"]


Another Haskell formatter.

command = "stylish-haskell"
options = [ "--inplace" ]
includes = [ "*.hs" ]


Nix code formatter.

command = "nixpkgs-fmt"
includes = ["*.nix"]


command = "rustfmt"
options = ["--edition", "2018"]
includes = ["*.rs"]


Rufo is an opinionated ruby formatter. By default it exits with status 3 on file change so we have to pass the -x option.

command = "rufo"
options = ["-x"]
includes = ["*.rb"]

cargo fmt

cargo fmt is not supported as it doesn't follow the spec. It doesn't allow to pass arbitrary files to be formatted, which treefmt relies on. Use rustfmt instead (which is what cargo fmt uses under the hood).


A shell code formatter.

command = "shfmt"
options = [
  "2",  # indent 2
  "-s",  # simplify the code
  "-w",  # write back to the file
includes = ["*.sh"]


terraform fmt only supports formatting one file at the time. See

Released under the MIT License.