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¶
- uses: jidicula/clang-format-action@v4.18.0
with:
clang-format-version: '21'
check-path: 'src'
- 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¶
- uses: ZedThree/clang-tidy-review@v0.23.1
with:
clang_tidy_version: '21'
build_dir: build
config_file: .clang-tidy
- 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¶
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v21.1.0
hooks:
- id: clang-format
- 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¶
- Getting started lists every integration and how to install the tools.
- Who uses cpp-linter shows projects that made the switch.
- The cpp-linter-action docs describe every input, output and permission.