Skip to content

Installation

Get cmakefmt running, wire it into your project, and never worry 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 .
Terminal window
pip install cmakefmt

This installs the native cmakefmt binary into your environment’s bin/ directory. No Python runtime overhead — the binary is the same Rust-compiled formatter available via Homebrew and Cargo.

Pre-built wheels are available for Linux (x86_64, aarch64), macOS (x86_64, aarch64), and Windows (x64). On unsupported platforms, pip falls back to building from the source distribution, which requires a Rust toolchain.

Terminal window
conda install -c conda-forge cmakefmt

Built from source by conda-forge. Future version bumps are handled automatically by the conda-forge autotick bot.

Recommended for Windows users — installs a native binary, no Rust toolchain or Python environment needed:

Terminal window
winget install cmakefmt.cmakefmt

The package is published in the microsoft/winget-pkgs community repository. New manifests are submitted automatically when each GitHub Release is published, so the available version closely tracks the latest tagged release once the upstream PR is merged.

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.
pip install cmakefmtOfficially maintainedNative binary via pre-built wheel.
conda install -c conda-forge cmakefmtCommunity maintainedBuilt from source; autotick bot tracks releases.
winget install cmakefmt.cmakefmtOfficially maintainedRecommended on Windows. Manifest lives in microsoft/winget-pkgs; new versions are submitted automatically on each release.
GitHub Releases binariesOfficially maintainedNative binaries for Linux, macOS, and Windows.
Docs site / CLI referenceOfficially maintainedStays in lock-step with each tagged release.
ScoopPlannedNot published yet.
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 completions bash > cmakefmt.bash
cmakefmt completions zsh > _cmakefmt
cmakefmt completions fish > cmakefmt.fish

Source the file from your .bashrc or .bash_profile:

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

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

Terminal window
cmakefmt completions bash | sudo tee /etc/bash_completion.d/cmakefmt > /dev/null

Place the file somewhere on your fpath and reload completions:

Terminal window
cmakefmt completions 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 completions 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 config dump > .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 config dump --format 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 config dump
  • 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 config path src/CMakeLists.txt
cmakefmt config show src/CMakeLists.txt
cmakefmt config explain
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 config path path/to/CMakeLists.txt
cmakefmt config explain

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 config dump --format toml > .cmakefmt.toml

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

Docs track main. For historical docs, check out a release tag in the repository and build docs/ locally.