Skip to content

Why cpp-linter?

There are several ways to run clang-format and clang-tidy on a pull request. Most of them do one tool, in one place, with whatever clang version the runner happens to have. cpp-linter pins one LLVM version and runs both tools in every place code gets checked, from a contributor's pre-commit hook to the review comments on the pull request.

What the action does

cpp-linter-action runs clang-format and clang-tidy in one step and reports through four channels, each behind its own input: pull request reviews with suggested fixes (format-review, tidy-review), annotations in the diff view (file-annotations), one thread comment that is rewritten on every push (thread-comments: update), and the job step summary (step-summary).

Only the files changed in the pull request are checked unless you set files-changed-only: false, and lines-changed-only: true drops clang-tidy findings outside the changed lines. That is how a strict .clang-tidy becomes usable on a code base that has never run it.

The version input picks the clang tools: an LLVM major version that clang-tools can install, a path to tools you installed yourself, or an empty string for whatever the runner already has. The input reference has the details. The action installs the tools itself on ubuntu, macOS and Windows runners, so there is no Docker image to build before the first result.

The same two tools run outside CI from the same project: as pre-commit hooks through cpp-linter-hooks with the same --version pin, from any script through the cpp-linter CLI, and on a laptop through clang-tools.

How it compares

Checked on 2026-09-12 against each project's current README and action.yml. Follow the header links to verify a cell. ✓ yes · ✗ no · — not applicable.

cpp-linter-action jidicula/
clang-format-action
DoozyX/
clang-format-lint-action
ZedThree/
clang-tidy-review
platisd/
clang-tidy-pr-comments
JacobDomagala/
StaticAnalysis
pre-commit/
mirrors-clang-format
Runs clang-format ✓ check only ✓ check or fix ✓ fix
Runs clang-tidy ✗ (reads your -export-fixes YAML) ✓ plus cppcheck
PR review with suggested fixes
File annotations ✓ (10 max)
Thread comment, updated per push LGTM only
Job step summary on failure
Only changed files / lines ✓ both ✓ diff changed lines only ✓ lines staged files
Choose the LLVM version major, path or runner default 3–22 5–20 14, 17–21 via rev
Installs the tools itself Docker run Docker Docker (2–3 min build) Docker ✓ wheel
Runners ubuntu, macOS, Windows ubuntu only Linux (Docker) Linux (Docker) unclear Linux (Docker)
Compilation database input database build_dir
pre-commit hook from the same project ✓ cpp-linter-hooks is one

The table is there to help people pick a tool. If you maintain one of these projects and a cell is out of date, open an issue or edit this page and we will correct it.

reviewdog is not in the table because it is a reporting framework rather than a linter: it has no built-in clang-format or clang-tidy support and needs a wrapper plus an error-format definition. It is a good choice when you already run many linters through it.

When another tool is the better fit

If all you want is a red check when formatting is off, jidicula/clang-format-action is one input and one script. cpp-linter can be configured the same way with tidy-checks: '-*' and file-annotations: false, but it is not smaller. If you already run clang-tidy in your own build job and only want its YAML turned into review comments, platisd/clang-tidy-pr-comments does exactly that step, and nothing else.

cpp-linter does not run cppcheck; JacobDomagala/StaticAnalysis runs it next to clang-tidy. For fixes committed straight back to the pull request, DoozyX's README shows an inplace plus commit-action recipe. cpp-linter-action has an auto-fix option in review, and until it ships the format-review suggestions are one click from the same result. If you lint many languages through one framework, reviewdog or MegaLinter fit better, with the cpp-linter CLI as the C/C++ step if you want it.

Migrating

From jidicula/clang-format-action

Before
- uses: jidicula/clang-format-action@v4.18.0
  with:
    clang-format-version: '21'
    check-path: 'src'
After
- uses: cpp-linter/cpp-linter-action@v2
  id: linter
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    version: '21'
    style: file            # .clang-format
    tidy-checks: '-*'      # keep it format-only for now
    ignore: 'third_party'  # paths to skip, separated by |
- if: steps.linter.outputs.checks-failed > 0
  run: exit 1

check-path scanned a whole directory on every run; cpp-linter checks the files changed in the pull request by default, and files-changed-only: false restores the whole-tree behaviour. Drop tidy-checks: '-*' when you are ready to add clang-tidy; with tidy-checks: '' the action reads .clang-tidy. Set format-review: true to turn findings into review suggestions.

From ZedThree/clang-tidy-review

Before
- uses: ZedThree/clang-tidy-review@v0.23.1
  with:
    clang_tidy_version: '21'
    build_dir: build
    config_file: .clang-tidy
After
- uses: cpp-linter/cpp-linter-action@v2
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    version: '21'
    database: build        # directory holding compile_commands.json
    tidy-checks: ''        # .clang-tidy
    style: file            # .clang-format, or '' to skip clang-format
    tidy-review: true
    lines-changed-only: true

The review comments land in the same job, without the separate post step and without waiting for a Docker image to build.

From pre-commit/mirrors-clang-format

Before
- repo: https://github.com/pre-commit/mirrors-clang-format
  rev: v21.1.0
  hooks:
    - id: clang-format
After
- repo: https://github.com/cpp-linter/cpp-linter-hooks
  rev: v1.6.0
  hooks:
    - id: clang-format
      args: [--style=file, --version=21]
    - id: clang-tidy
      args: [--checks=.clang-tidy, --version=21]

--version pins the tool independently of the hooks release, so updating rev never changes which clang-format formats your code. The clang-tidy hook is optional; it auto-detects compile_commands.json in common build directories.

Next steps