treefmt combines file formatters for
multiple programming languages so that you can format all your project files
with a single command. With treefmt-nix you can specify treefmt build
options, dependencies and config in one place, conveniently managed by
Nix.
treefmt-nix automatically installs and configures the desired formatters as
well as treefmt for you and integrates nicely into your Nix development
environments. It comes with sane, pre-crafted
formatter-configs
maintained by the community; each config corresponds to a section that you would
normally add to the treefmt config file treefmt.toml.
Take a look at the already supported formatters for Python, Rust, Go, Haskell and more.
To run treefmt-nix with nix-classic, import the repo using
niv:
$ niv add numtide/treefmt-nix
Alternatively, you can download the source and run nix-build in the project
root directory:
$ nix-build
The command will return the helper functions which will be later used to produce
a derivation from the specified treefmt-nix configuration.
After you installed treefmt-nix, specify the formatter configuration. For instance, this one is for formatting terraform files:
# myfile.nix
{ system ? builtins.currentSystem }:
let
nixpkgsSrc = builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/refs/heads/nixos-unstable.tar.gz";
treefmt-nixSrc = builtins.fetchTarball "https://github.com/numtide/treefmt-nix/archive/refs/heads/master.tar.gz";
nixpkgs = import nixpkgsSrc { inherit system; };
treefmt-nix = import treefmt-nixSrc;
in
treefmt-nix.mkWrapper nixpkgs {
# Used to find the project root
projectRootFile = ".git/config";
# Enable the terraform formatter
programs.terraform.enable = true;
# Override the default package
programs.terraform.package = nixpkgs.terraform_1;
# Override the default settings generated by the above option
settings.formatter.terraform.excludes = [ "hello.tf" ];
}It's a good practice to place the configuration file in the project root directory.
Next, execute this command:
$ nix-build myfile.nix
This command returns a derivation that contains a treefmt binary at
./result/bin/treefmt in your current directory. The file is actually a symlink
to the artifact in /nix/store.
treefmt.toml in this case isn't generated: the binary is wrapped with the
config.
Running treefmt-nix with flakes isn't hard. The library is exposed as the lib
attribute:
# flake.nix
{
inputs.treefmt-nix.url = "github:numtide/treefmt-nix";
outputs = { self, nixpkgs, systems, treefmt-nix }:
let
# Small tool to iterate over each systems
eachSystem = f: nixpkgs.lib.genAttrs (import systems) (system: f nixpkgs.legacyPackages.${system});
# Eval the treefmt modules from ./treefmt.nix
treefmtEval = eachSystem (pkgs: treefmt-nix.lib.evalModule pkgs ./treefmt.nix);
in
{
# for `nix fmt`
formatter = eachSystem (pkgs: treefmtEval.${pkgs.system}.config.build.wrapper);
# for `nix flake check`
checks = eachSystem (pkgs: {
formatting = treefmtEval.${pkgs.system}.config.build.check self;
});
};
}And also add the treefmt.nix file (or put the content inline if you prefer):
# treefmt.nix
{ pkgs, ... }:
{
# Used to find the project root
projectRootFile = "flake.nix";
# Enable the terraform formatter
programs.terraform.enable = true;
# Override the default package
programs.terraform.package = pkgs.terraform_1;
# Override the default settings generated by the above option
settings.formatter.terraform.excludes = [ "hello.tf" ];
}This file is also the place to define all the treefmt parameters like includes, excludes and formatter options.
After specifying the flake, run
nix fmt:
$ nix fmt
Nix-fmt is a tool to format all nix files in the project, but with the specified flake, it starts treefmt-nix and formats your project.
You can also run nix flake check (eg: in CI) to validate that the project's
code is properly formatted.
This flake exposes a flake-parts module as well. To use it:
-
Add
inputs.treefmt-nix.flakeModuleto theimportslist of yourflake-partscall. -
Add
treefmt = { .. }(containing the configuration above) to yourperSystem.
As an example, see https://github.com/nix-community/buildbot-nix/blob/2695e33353d7bffb2073dc6a1789502dd9e7b9fd/nix/treefmt/flake-module.nix
While dealing with treefmt outside of nix, the formatter configuration is
specified in a toml format. On the contrary, with nix, you write in with a
nix syntax like this:
# Used to find the project root
projectRootFile = ".git/config";
# Enable the terraform formatter
programs.terraform.enable = true;
# Override the default package
programs.terraform.package = nixpkgs.terraform_1;
# Override the default settings generated by the above option
settings.formatter.terraform.excludes = [ "hello.tf" ];Options:
Project root fileis the git file of the project which you plan to format.- The option
programs.terraform.enableenables the needed formatter. You can specify as many formatter as you want. For instance:
programs.terraform.enable = true;
programs.gofmt.enable = true;
- The option
programs.terraform.packageallows you to use a particular build/version of the specified formatter. - By setting
settings.formatter.terraform.excludesyou can mark the files which should be excluded from formatting. You can also specify other formatter options or includes this way.
For detailed description of the options, refer to the treefmt
documentation.
This repo contains a top-level default.nix that returns the library helper
functions.
mkWrapperis the main function which wraps treefmt with the needed configuration.mkConfigFileevalModuleall-modules
treefmt-nix currently supports 106 formatters:
- actionlint
- alejandra
- asmfmt
- beautysh
- biome
- black
- buf
- buildifier
- cabal-fmt
- clang-format
- cljfmt
- cmake-format
- csharpier
- cue
- d2
- dart-format
- deadnix
- deno
- dhall
- dnscontrol
- dos2unix
- dprint
- efmt
- elm-format
- erlfmt
- fantomas
- fish_indent
- fnlfmt
- formatjson5
- fourmolu
- fprettify
- gdformat
- genemichaels
- gleam
- gofmt
- gofumpt
- goimports
- golines
- google-java-format
- hclfmt
- hlint
- isort
- jsonfmt
- jsonnet-lint
- jsonnetfmt
- just
- kdlfmt
- keep-sorted
- ktfmt
- ktlint
- latexindent
- leptosfmt
- mdformat
- mdsh
- meson
- mix-format
- muon
- mypy
- nickel
- nimpretty
- nixfmt-classic
- nixfmt-rfc-style
- nixfmt
- nixpkgs-fmt
- nufmt
- ocamlformat
- odinfmt
- opa
- ormolu
- oxipng
- packer
- perltidy
- php-cs-fixer
- pinact
- prettier
- protolint
- purs-tidy
- rstfmt
- rubocop
- ruff-check
- ruff-format
- rufo
- rustfmt
- scalafmt
- shellcheck
- shfmt
- sql-formatter
- sqlfluff-lint
- sqlfluff
- sqruff
- statix
- stylish-haskell
- stylua
- swift-format
- taplo
- templ
- terraform
- texfmt
- toml-sort
- typos
- typstfmt
- typstyle
- yamlfmt
- zig
- zizmor
- zprint
For non-Nix users, you can also find the generated examples in the ./examples folder.
It is also possible to use custom formatters with treefmt-nix. For example,
the following custom formatter formats JSON files using yq-go:
settings.formatter = {
"yq-json" = {
command = "${pkgs.bash}/bin/bash";
options = [
"-euc"
''
for file in "$@"; do
${lib.getExe yq-go} -i --output-format=json $file
done
''
"--" # bash swallows the second argument when using -c
];
includes = [ "*.json" ];
};
};PRs to add new formatters are welcome!
- The formatter should conform to the formatter specifications.
- This is not the place to debate formatting preferences. Please pick defaults that are standard in your community -- for instance, python is usually indented with 4 spaces, so don't add a python formatter with 2 spaces as the default.
In order to add a new formatter do the following things:
-
Create a new entry in the
./programs/folder. -
Consider adding yourself as the
meta.maintainer(see below). -
Run
./examples.shto update the./examplesfolder. -
To test the program:
-
Extend the project's
./treefmt.nixfile (temporarily) to enable the new formatter and configure it in whatever manner is appropriate. -
Add a bunch of pertinent sources in this repo -- for instance, if the new formatter is meant to format
*.foofiles, add a number of*.foofiles, some well-formatted (and therefore expected to be exempt from modification bytreefmt) and some badly-formatted. -
Run
nix fmt. Confirm that well-formatted files are unchanged and that badly-formatted files are flagged as such. Re-runnix fmtand confirm that no additional changes were made. -
Add the formatter to this file here by running:
mdsh -i README.md -o README.md
or with Nix
nix run github:zimbatm/mdsh -- -i README.md -o README.md
-
Once this is good, revert those changes.
-
-
Submit the PR!
You can register your desire to help with a specific formatter by adding your
GitHub handle to the module's meta.maintainers list.
That mostly means, for the given formatter:
- You get precedence if any decisions need to be made.
- Getting pinged if any issue is being found.
treefmt-nix works with all known Nix version.
If you rely on flakes and nix fmt, we recommend running Nix 2.25 or Lix 2.92
or later. See NixOS/nix#11438
Looking for help or customization?
Get in touch with Numtide to get a quote. We make it easy for companies to work with Open Source projects: https://numtide.com/contact
All the code and documentation is licensed with the MIT license.