cpp-linter-hooks
pre-commit hooks that pip-install the clang-format and clang-tidy version you pin, on every developer's machine.
Website · Get started · Discussions
Quick start
Add this configuration to your .pre-commit-config.yaml file:
repos:
- repo: https://github.com/cpp-linter/cpp-linter-hooks
rev: v1.6.1
hooks:
- id: clang-format
args: [--style=file, --version=21]
- id: clang-tidy
args: [--version=21]
Run pre-commit install once in each clone. --style=file loads the style from your
.clang-format file, and clang-tidy reads your .clang-tidy file by itself. The clang-tidy hook
needs a compile_commands.json, which it looks for in build/ and a few other directories (see
Compilation database);
leave it out if you only run clang-tidy in CI, for example with
cpp-linter-action.
Usage
Custom clang tool version
--version=21installs the newest 21.x wheel, and--version=21.1.8pins an exact release. clang-tidy wheels are released separately from clang-format wheels and skip some releases, so give clang-tidy the major version.- clang-format wheels cover LLVM 6 to 23 and clang-tidy wheels LLVM 13 to 22. For a version without a wheel, the hook fails and lists some of the versions that exist.
- The hook looks the version up on pypi.org every time it runs. Without network access it fails
when
--versionis set, and otherwise uses the clang-format or clang-tidy already installed.
clang-format
To use a predefined coding style instead of your .clang-format file:
- id: clang-format
args: [--style=Google] # Other coding style: LLVM, GNU, Chromium, Microsoft, Mozilla, WebKit.
When clang-format changes a file, the hook fails and pre-commit stops the commit:
clang-format.............................................................Failed
- hook id: clang-format
- files were modified by this hook
Here’s a sample diff showing the formatting applied with --style=Google:
--- a/testing/main.c
+++ b/testing/main.c
@@ -1,3 +1,6 @@
#include <stdio.h>
-int main() {for (;;) break; printf("Hello world!\n");return 0;}
-
+int main() {
+ for (;;) break;
+ printf("Hello world!\n");
+ return 0;
+}
clang-format.............................................................Failed
- hook id: clang-format
- exit code: 1
main.c:2:13: error: code should be clang-formatted [-Wclang-format-violations]
int main() {for (;;) break; printf("Hello world!\n");return 0;}
^
main.c:2:21: error: code should be clang-formatted [-Wclang-format-violations]
int main() {for (;;) break; printf("Hello world!\n");return 0;}
^
main.c:2:28: error: code should be clang-formatted [-Wclang-format-violations]
int main() {for (;;) break; printf("Hello world!\n");return 0;}
^
main.c:2:54: error: code should be clang-formatted [-Wclang-format-violations]
int main() {for (;;) break; printf("Hello world!\n");return 0;}
^
main.c:2:63: error: code should be clang-formatted [-Wclang-format-violations]
int main() {for (;;) break; printf("Hello world!\n");return 0;}
^
clang-tidy
To set the checks in args instead of your .clang-tidy file, quote the whole option: inside
[...], YAML splits an unquoted value at each comma.
- id: clang-tidy
args: ["--checks=boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*,clang-analyzer-*,cppcoreguidelines-*"]
When clang-tidy reports a warning or an error, the hook fails:
clang-tidy...............................................................Failed
- hook id: clang-tidy
- exit code: 1
522 warnings generated.
Suppressed 521 warnings (521 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
/home/runner/work/cpp-linter-hooks/cpp-linter-hooks/testing/main.c:4:13: warning: statement should be inside braces [readability-braces-around-statements]
for (;;)
^
{
repos:
- repo: https://github.com/cpp-linter/cpp-linter-hooks
rev: v1.6.1 # includes --fix support
hooks:
- id: clang-tidy
args: [--fix]
Compilation database
For CMake or Meson projects, clang-tidy works best with a compile_commands.json
file that records the exact compiler flags used for each file. Without it, clang-tidy
may report false positives from missing include paths or wrong compiler flags.
The hook auto-detects compile_commands.json in common build directories (build/,
out/, cmake-build-debug/, _build/) and passes -p <dir> to clang-tidy
automatically — no configuration needed for most projects:
repos:
- repo: https://github.com/cpp-linter/cpp-linter-hooks
rev: v1.6.1
hooks:
- id: clang-tidy
# Auto-detects ./build/compile_commands.json if present
To specify the build directory explicitly:
- id: clang-tidy
args: [--compile-commands=build]
To disable auto-detection (e.g. in a monorepo where auto-detect might pick the wrong database):
- id: clang-tidy
args: [--no-compile-commands]
Examples
Two self-contained templates plus quick snippets for other common setups.
- CMake minimal config
- Large project
files:regex — scoping hooks for speed - Quick snippets — Meson, clang-format-only, monorepo, CI,
compile_commands.json
Troubleshooting
Performance optimization
- repo: https://github.com/cpp-linter/cpp-linter-hooks
rev: v1.6.1
hooks:
- id: clang-format
args: [--style=file, --version=21]
files: ^(src|include)/.*\.(cpp|cc|cxx|h|hpp)$ # Limits to specific dirs and file types
- id: clang-tidy
args: [--version=21]
files: ^(src|include)/.*\.(cpp|cc|cxx|h|hpp)$
For clang-tidy, you can also process multiple files in parallel by adding --jobs
or -j:
- repo: https://github.com/cpp-linter/cpp-linter-hooks
rev: v1.6.1
hooks:
- id: clang-tidy
args: [--version=21, --jobs=4]
Alternatively, if you want to run the hooks manually on only the changed files, you can use the following command:
pre-commit run --files $(git diff --name-only)
This approach ensures that only modified files are checked, further speeding up the linting process during development.
Verbose output
repos:
- repo: https://github.com/cpp-linter/cpp-linter-hooks
rev: v1.6.1
hooks:
- id: clang-format
args: [--style=file, --version=21, --verbose] # Shows processed files
- id: clang-tidy
args: [--verbose] # Shows which compile_commands.json is used
Compared with mirrors-clang-format
mirrors-clang-format is pre-commit's mirror of the clang-format wheel.
| Feature | cpp-linter-hooks |
mirrors-clang-format |
|---|---|---|
Supports clang-format and clang-tidy |
Both | clang-format only |
| Custom configuration files | .clang-format, .clang-tidy |
.clang-format |
| Specify tool version | via --version arg (e.g. --version=21) |
via rev tag (e.g. rev: v21.1.8) |
rev tag meaning |
Project version, not the tool version | Equals the clang-format version directly |
| Default file types | C, C++ | C, C++, C#, CUDA, Java, JavaScript, JSON, Objective-C, proto, textproto, Metal |
| Supports passing format style string | via --style |
via --style |
| Verbose output | via --verbose |
via --verbose |
| Dry-run mode | via --dry-run |
via --dry-run --Werror |
| Auto-fix mode | via --fix (clang-tidy only) |
No |
| Compilation database support | auto-detect or --compile-commands |
No |
Used by
These organizations run cpp-linter-hooks on their default branch:
MIT ACL ·
Bazel Contrib ·
CodSpeed ·
doldecomp ·
HKUST Aerial Robotics ·
Kubewarden ·
Computational Geography ·
IMSY ·
CONVINCE-Project
The showcase lists more projects that use cpp-linter tools.
Contributing
See the contributing guide and open an issue for bugs and feature requests.
License
This project is licensed under the MIT License.
Metadata
Release files for cpp-linter-hooks 1.6.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cpp_linter_hooks-1.6.1-py3-none-any.whl | Python 3 | none | any | Details |
Release files / cpp_linter_hooks-1.6.1-py3-none-any.whl
| Download URL | cpp_linter_hooks-1.6.1-py3-none-any.whl |
|---|---|
| Size | 15.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2920e7385eca7b25e88135f0d88c3bd91a3188b6b4d5ce6884cf2b2e6930dcf5
|
|
BLAKE2b-256 checksum How to use checksums |
b859e8e8417f3d94d4757e8eb6bf8af3d4cc70475a4915512b4c1a4ec77e6e05
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|