Skip to content

Installation

Get cmakefmt running, wire it into your project, and never think about CMake formatting again.

Recommended for macOS users — no Rust toolchain needed:

Terminal window
brew install cmakefmt/cmakefmt/cmakefmt

Reference install path for developers already using Rust, works on any platform:

Terminal window
cargo install cmakefmt-rust

Verify the binary is on your path:

Terminal window
cmakefmt --version
cmakefmt --help

You can also install from a local checkout — for development, benchmarking, or reviewing changes:

Terminal window
cargo install --path .

Native binaries for Linux, macOS, and Windows are published to GitHub Releases. Download the .zip / .tar.gz for your platform, extract, and place the binary on your PATH.

Terminal window
git clone https://github.com/cmakefmt/cmakefmt
cd cmakefmt
cargo build --release
./target/release/cmakefmt --help

This is the right path if you are actively developing cmakefmt, reviewing changes, or benchmarking local modifications.

The release plan separates channels into explicit support levels so users know what to trust:

ChannelSupport levelNotes
Homebrew (cmakefmt/cmakefmt)Officially maintainedRecommended for macOS users. Ships completions and man page.
cargo install cmakefmt-rustOfficially maintainedReference install path for developers already using Rust.
GitHub Releases binariesOfficially maintainedNative binaries for Linux, macOS, and Windows.
Docs site / CLI referenceOfficially maintainedStays in lock-step with each tagged release.
winget / ScoopOfficially maintainedPlanned first-party Windows package-manager channels.
Additional package managers (AUR, Nix, containers, etc.)Automated or best-effortUseful channels, but not the first rollout priority.

Release archives include shell completion scripts for the supported shells:

  • cmakefmt.bash for Bash
  • _cmakefmt for Zsh
  • cmakefmt.fish for Fish

The Zsh file intentionally uses the conventional completion-function name _cmakefmt rather than a .zsh suffix.

You can also generate the completion files yourself from any installed binary:

Terminal window
cmakefmt --generate-completion bash > cmakefmt.bash
cmakefmt --generate-completion zsh > _cmakefmt
cmakefmt --generate-completion fish > cmakefmt.fish

Source the file from your .bashrc or .bash_profile:

Terminal window
cmakefmt --generate-completion bash > ~/.local/share/bash-completion/completions/cmakefmt

Or for a system-wide install (requires write access):

Terminal window
cmakefmt --generate-completion bash | sudo tee /etc/bash_completion.d/cmakefmt > /dev/null

Place the file somewhere on your fpath and reload completions:

Terminal window
cmakefmt --generate-completion zsh > ~/.zfunc/_cmakefmt

Then add the following to your .zshrc if ~/.zfunc is not already on fpath:

Terminal window
fpath=(~/.zfunc $fpath)
autoload -Uz compinit && compinit

Fish looks for completions in a fixed directory — just drop the file there:

Terminal window
cmakefmt --generate-completion fish > ~/.config/fish/completions/cmakefmt.fish

Fish picks up the new file automatically without a shell restart.

Dump a starter config into your repo root:

Terminal window
cmakefmt --dump-config > .cmakefmt.yaml

Why YAML by default? For larger configs, YAML requires less punctuation and is more readable with nested custom-command specs. TOML is still available via --dump-config toml if you prefer it.

Do a dry run — check your whole project without rewriting a single file:

Terminal window
cmakefmt --check .

When you are happy with what you see, apply the formatting:

Terminal window
cmakefmt --in-place .

The commands you will reach for every day:

Terminal window
cmakefmt --check .
cmakefmt --in-place .
cmakefmt --verify CMakeLists.txt
cmakefmt --cache --check .
cmakefmt --require-pragma --check .
cmakefmt --staged --check
cmakefmt --changed --since origin/main --check

What each one does:

  • --check .: CI-safe validation for a repository or directory
  • --in-place .: rewrite all discovered CMake files, with semantic verification by default
  • --verify CMakeLists.txt: do a safe stdout-format run when you want the extra parse-tree check
  • --cache --check .: speed up repeated whole-repo checks when your config is stable
  • --require-pragma --check .: roll formatting out gradually, only touching opted-in files
  • --staged --check: pre-commit guard — only touches staged files
  • --changed --since origin/main --check: PR-scoped check for branch-only changes

The simplest CI baseline:

Terminal window
cmakefmt --check .

For quieter CI logs:

Terminal window
cmakefmt --check --quiet .

For machine-readable output that scripts or dashboards can consume:

Terminal window
cmakefmt --check --report-format json .

Many editor integrations pipe a buffer through stdin rather than passing a real file path. Use --stdin-path to give config discovery and diagnostics the on-disk context they need:

Terminal window
cat src/CMakeLists.txt | cmakefmt - --stdin-path src/CMakeLists.txt

This is also the right pattern for ad-hoc scripts and custom editor commands.

If your project uses many custom CMake functions or macros:

  • start from --dump-config
  • keep the file as .cmakefmt.yaml
  • define command syntax under commands:
  • use per_command_overrides: only for layout and style tweaks

If you are debugging config discovery:

Terminal window
cmakefmt --show-config-path src/CMakeLists.txt
cmakefmt --show-config src/CMakeLists.txt
cmakefmt --explain-config
Terminal window
brew update
brew upgrade cmakefmt
Terminal window
brew uninstall cmakefmt
brew untap cmakefmt/cmakefmt
Terminal window
git pull --ff-only
cargo install --path . --force
Terminal window
cargo uninstall cmakefmt-rust

Once release tags exist, prefer explicit version pins:

Terminal window
cargo install cmakefmt-rust --version <tagged-version>

The release docs and release notes will also publish SHA-256 sums for release artifacts so non-Cargo installs can verify downloads.

Make sure Cargo’s install bin directory is on your PATH.

Terminal window
cmakefmt --show-config-path path/to/CMakeLists.txt
cmakefmt --explain-config

A hook or script only sees stdin and ignores my project config

Section titled “A hook or script only sees stdin and ignores my project config”

Pass --stdin-path with the buffer’s real project-relative path.

Terminal window
cmakefmt --dump-config toml > .cmakefmt.toml

YAML is the recommended default because it is more readable for larger configurations with nested custom command specs.