clang-format and clang-tidy for C and C++

C/C++ pull requests
that arrive
already checked.

cpp-linter runs clang-format and clang-tidy on the files each pull request changes and reports what it finds in the job log and as annotations on the pull request. Turn on reviews and the fixes arrive as suggestions you commit in one click. Set the same LLVM version in the workflow and the pre-commit hooks, and laptops and CI use the same major release.

  • Used by 1,000+ repositories
  • Linux, macOS and Windows runners
  • Free and open source

Start here

Pick where the checks run

Four ways in. Each can use the same .clang-format and .clang-tidy files from your repository.

Compare with other tools

On every pull request

cpp-linter-action

Annotates findings on the pull request. Pass GITHUB_TOKEN with pull-requests: write to add a summary comment or review suggestions. Linux, macOS and Windows runners.

uses: cpp-linter/cpp-linter-action@v2 Read the docs

Before every commit

cpp-linter-hooks

pre-commit hooks that pip-install the clang-format and clang-tidy version you pin, on every developer's machine. clang-tidy wheels cover LLVM 13 to 22.

args: [--style=file, --version=21] View on GitHub

Locally or in other CI

cpp-linter

The Python command behind the action. Run it locally, or on the whole repository in other CI, with clang tools you install first. It exits 0 even when checks fail.

pip install cpp-linter Read the docs

Just the clang tools

clang-tools

clang-format, clang-tidy and friends for LLVM 12 to 23 via pip or asdf, plus Docker images (up to 22) and a macOS Homebrew tap (19 to 23).

pip install clang-tools clang-tools install clang-format clang-tidy --version 21 Read the docs

The idea behind it

Pin the same LLVM version in each tool

Different clang-format releases can format the same file differently. Set the same LLVM version in the action, the pre-commit hooks and on your machine, and every step runs the same major release. The clang-tidy hook covers LLVM 13 to 22; the action and clang-tools cover 12 to 23.

  1. --version 21

    On your laptop

    clang-tools

    Install clang-format and clang-tidy by LLVM version with pip, Homebrew or asdf, or run them from a Docker image.

  2. --version=21

    Before each commit

    cpp-linter-hooks

    pre-commit runs them on the files you staged.

  3. version: '21'

    On the pull request

    cpp-linter-action

    Checks the files the pull request changes and annotates the findings.

  4. --version=21

    In other CI

    cpp-linter

    The same checks as one Python command. Install LLVM 21 first: without it, --version=21 falls back to whatever clang-format is on PATH.

What reviewers see

Results show up on the pull request

Annotations are on by default. Review suggestions, a summary comment and auto-fix each take one input plus write access for the job.

Suggestions you can commit

Set format-review or tidy-review and fixes for lines in the diff arrive as review suggestions. Needs pull-requests: write, so pull requests from forks get annotations only.

Notes in the diff

clang-tidy findings in the checked file are annotated on their line (GitHub shows up to 10 warnings per step), and clang-format adds one note per file. Annotations need no write access, so they also work on pull requests from forks.

One summary comment

Set thread-comments: update and one comment lists the results, edited on each push while there are findings. It is posted by github-actions[bot] or your own App, and needs pull-requests: write, so it fails on pull requests from forks.

Fixes pushed for you

New in v2.23

Set auto-fix: true and give the job contents: write, and the clang-format fixes are committed to the branch of a same-repository pull request, by default under the name of whoever triggered the run.

Bringing clang-tidy to an old codebase? Set lines-changed-only: true and only the lines each pull request changes are checked, so a strict .clang-tidy works from the first pull request.

Read the guide

Get started

Start with one workflow file

  1. 1Save it as .github/workflows/cpp-linter.yml
  2. 2Open a pull request that changes C or C++ files, from a branch in this repository and not as a draft.
  3. 3Commit the suggestions you agree with.

Runs on Linux, macOS and Windows runners with LLVM 12 to 23, and reads your .clang-format and .clang-tidy files. On pull requests from forks the token is read-only, so findings show up as annotations only.

Read the getting started guide
.github/workflows/cpp-linter.yml
name: cpp-linter
on: pull_request

jobs:
  cpp-linter:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v7
      - uses: cpp-linter/cpp-linter-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          style: file
          tidy-checks: ''
          format-review: true

Maintained by two volunteers

cpp-linter is free and open source. Sponsorship goes to the project through Open Collective, where all income and expenses are public.