diff --git a/README.md b/README.md
index 8a990b0..45c909f 100644
--- a/README.md
+++ b/README.md
@@ -1,76 +1,20 @@
# cpp-linter-hooks
-[](https://pypi.org/project/cpp-linter-hooks/)
-[](https://pypi.org/project/cpp-linter-hooks/)
-[](https://codecov.io/gh/cpp-linter/cpp-linter-hooks)
-[](https://github.com/cpp-linter/cpp-linter-hooks/actions/workflows/test.yml)
-[](https://github.com/cpp-linter/cpp-linter-hooks/actions/workflows/codeql.yml)
-[](https://cpp-linter.github.io/)
-
-A pre-commit hook repository for C/C++ projects that installs and runs
-`clang-format` and `clang-tidy` through the
-[pre-commit](https://pre-commit.com/) framework.
-
-## Why cpp-linter-hooks?
-
-Use `cpp-linter-hooks` when you want the same C/C++ formatting and linting tools
-to run consistently on developer machines and in CI without requiring every
-developer to install LLVM tools manually.
-
-- Runs both `clang-format` and `clang-tidy` from one pre-commit repository.
-- Installs clang tools from Python wheels for a cross-platform setup.
-- Lets projects pin the clang tool version explicitly with `--version`.
-- Supports project-native `.clang-format` and `.clang-tidy` configuration files.
-- Auto-detects `compile_commands.json` for CMake and Meson-style build trees.
-- Supports `clang-format` dry-run checks, verbose diagnostics, and opt-in
- `clang-tidy` fixes.
-
-Compared with [`mirrors-clang-format`](https://github.com/pre-commit/mirrors-clang-format),
-this project also provides `clang-tidy`, compile database discovery, explicit
-tool-version selection, and richer diagnostics. See the [FAQ](#faq) for the full
-comparison.
+[](https://pypi.org/project/cpp-linter-hooks/)
+[](https://github.com/cpp-linter/cpp-linter-hooks/actions/workflows/test.yml)
+[](https://codecov.io/gh/cpp-linter/cpp-linter-hooks)
+[](https://cpp-linter.github.io/)
-> [!TIP]
-> Using GitHub Actions for CI? Check out
-> **[cpp-linter-action](https://github.com/cpp-linter/cpp-linter-action)** —
-> our companion GitHub Action that runs the same tools in CI with rich PR reviews,
-> thread comments, step summaries, and file annotations.
-
-## Quick Start
-
-Add this configuration to your `.pre-commit-config.yaml` file:
-
-```yaml
-repos:
- - repo: https://github.com/cpp-linter/cpp-linter-hooks
- rev: v1.6.0 # Use the tag or commit you want
- hooks:
- - id: clang-format
- args: [--style=Google] # Other coding style: LLVM, GNU, Chromium, Microsoft, Mozilla, WebKit.
- - id: clang-tidy
- args: ["--checks=boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*,clang-analyzer-*,cppcoreguidelines-*"]
-```
-
-### Custom Configuration Files
+[pre-commit](https://pre-commit.com/) hooks that pip-install the clang-format and clang-tidy
+version you pin, on every developer's machine.
-To use custom configurations like `.clang-format` and `.clang-tidy`:
+[Website](https://cpp-linter.github.io/) ·
+[Get started](https://cpp-linter.github.io/getting-started/#before-every-commit) ·
+[Discussions](https://github.com/orgs/cpp-linter/discussions)
-```yaml
-repos:
- - repo: https://github.com/cpp-linter/cpp-linter-hooks
- rev: v1.6.0
- hooks:
- - id: clang-format
- args: [--style=file] # Loads style from .clang-format file
- - id: clang-tidy # clang-tidy reads your .clang-tidy file by itself
-```
+## Quick start
-> [!TIP]
-> The `rev` tag (e.g. `v1.6.0`) is the **project** version, not the clang tool version. Each release bundles a default version of `clang-format` and `clang-tidy` — check the [release notes](https://github.com/cpp-linter/cpp-linter-hooks/releases) to see which tool version a given `rev` ships with. To pin an exact tool version independently of the project release, use `--version` as shown below.
-
-### Custom Clang Tool Version
-
-To use specific versions of clang-format and clang-tidy (using Python wheel packages):
+Add this configuration to your `.pre-commit-config.yaml` file:
```yaml
repos:
@@ -78,62 +22,47 @@ repos:
rev: v1.6.0
hooks:
- id: clang-format
- args: [--style=file, --version=21] # Specifies version
+ args: [--style=file, --version=21]
- id: clang-tidy
- args: [--version=21] # Specifies version
+ args: [--version=21]
```
-> [!TIP]
-> For production use, always pin the tool version explicitly with `--version` (e.g. `--version=21`) so upgrades to `cpp-linter-hooks` never silently change your linter version.
+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](https://github.com/cpp-linter/cpp-linter-hooks#compilation-database));
+leave it out if you only run clang-tidy in CI, for example with
+[cpp-linter-action](https://cpp-linter.github.io/cpp-linter-action/).
-### Compilation Database (CMake/Meson Projects)
-
-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.
+## Usage
-The hook auto-detects `compile_commands.json` in common build directories (`build/`,
-`out/`, `cmake-build-debug/`, `_build/`) and passes `-p
` to clang-tidy
-automatically — no configuration needed for most projects:
+### Custom clang tool version
-```yaml
-repos:
- - repo: https://github.com/cpp-linter/cpp-linter-hooks
- rev: v1.6.0
- hooks:
- - id: clang-tidy
- # Auto-detects ./build/compile_commands.json if present
-```
+> [!TIP]
+> The `rev` tag (e.g. `v1.6.0`) is the **project** version, not the clang tool version. Without
+> `--version`, each hook installs the newest clang-format or clang-tidy wheel on PyPI at the time it
+> runs, so the tool version can change without any change to your configuration, and the two hooks
+> can run different LLVM versions. For production use, always pin the tool version explicitly
+> with `--version`.
-To specify the build directory explicitly:
+- `--version=21` installs the newest 21.x wheel, and `--version=21.1.8` pins 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 `--version` is set, and otherwise uses the clang-format or clang-tidy already installed.
-```yaml
- - id: clang-tidy
- args: [--compile-commands=build]
-```
+### clang-format
-To disable auto-detection (e.g. in a monorepo where auto-detect might pick the wrong database):
+To use a predefined coding style instead of your `.clang-format` file:
```yaml
- - id: clang-tidy
- args: [--no-compile-commands]
+ - id: clang-format
+ args: [--style=Google] # Other coding style: LLVM, GNU, Chromium, Microsoft, Mozilla, WebKit.
```
-To see which `compile_commands.json` the hook is using, add `-v`:
-
-```yaml
- - id: clang-tidy
- args: [--compile-commands=build, -v]
-```
-
-> [!NOTE]
-> Generate `compile_commands.json` with CMake using `cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -Bbuild .`
-> or add `set(CMAKE_EXPORT_COMPILE_COMMANDS ON)` to your `CMakeLists.txt`.
-> `--compile-commands` takes the **directory** containing `compile_commands.json`, not the file path itself.
-
-## Output
-
-### clang-format Output
+When clang-format changes a file, the hook fails and pre-commit stops the commit:
```bash
clang-format.............................................................Failed
@@ -141,7 +70,7 @@ clang-format.............................................................Failed
- files were modified by this hook
```
-Here’s a sample diff showing the formatting applied:
+Here’s a sample diff showing the formatting applied with `--style=Google`:
```diff
--- a/testing/main.c
@@ -156,35 +85,45 @@ Here’s a sample diff showing the formatting applied:
+ return 0;
+}
```
+
> [!NOTE]
-> Use `--dry-run` in `args` of `clang-format` to print instead of changing the format, e.g.:
+> Use `--dry-run` in `args` of `clang-format` to print instead of changing the format.
+> In v1.6.0 the hook passes and prints nothing even when files need formatting; the fix is on
+> `main` and not released yet. With the fix, the output looks like this:
```bash
clang-format.............................................................Failed
- hook id: clang-format
-- exit code: 255
+- exit code: 1
-main.c:2:11: warning: code should be clang-formatted [-Wclang-format-violations]
-int main() {for (;;) break; printf("Hello world!\n");return 0;}
- ^
-main.c:2:13: warning: code should be clang-formatted [-Wclang-format-violations]
+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: warning: code should be clang-formatted [-Wclang-format-violations]
+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: warning: code should be clang-formatted [-Wclang-format-violations]
+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: warning: code should be clang-formatted [-Wclang-format-violations]
+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: warning: code should be clang-formatted [-Wclang-format-violations]
+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 Output
+### 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.
+
+```yaml
+ - 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:
```bash
clang-tidy...............................................................Failed
@@ -219,13 +158,55 @@ repos:
args: [--fix]
```
-> [!WARNING]
-> When `--fix` (or `-fix-errors`) is active, parallel execution via `--jobs`/`-j` is
-> automatically disabled to prevent concurrent writes to the same header file.
+### 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 ` to clang-tidy
+automatically — no configuration needed for most projects:
+
+```yaml
+repos:
+ - repo: https://github.com/cpp-linter/cpp-linter-hooks
+ rev: v1.6.0
+ hooks:
+ - id: clang-tidy
+ # Auto-detects ./build/compile_commands.json if present
+```
+
+To specify the build directory explicitly:
+
+```yaml
+ - id: clang-tidy
+ args: [--compile-commands=build]
+```
+
+To disable auto-detection (e.g. in a monorepo where auto-detect might pick the wrong database):
+
+```yaml
+ - id: clang-tidy
+ args: [--no-compile-commands]
+```
+
+> [!NOTE]
+> Generate `compile_commands.json` with CMake using `cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -Bbuild .`
+> or add `set(CMAKE_EXPORT_COMPILE_COMMANDS ON)` to your `CMakeLists.txt`.
+> `--compile-commands` takes the **directory** containing `compile_commands.json`, not the file path itself.
+
+### Examples
+
+Two self-contained templates plus quick snippets for other common setups.
+
+- [CMake minimal config](https://github.com/cpp-linter/cpp-linter-hooks/tree/main/examples/cmake)
+- [Large project `files:` regex](https://github.com/cpp-linter/cpp-linter-hooks/tree/main/examples/large-project) — scoping hooks for speed
+- [Quick snippets](https://github.com/cpp-linter/cpp-linter-hooks/blob/main/examples/README.md) — Meson, clang-format-only, monorepo, CI, `compile_commands.json`
## Troubleshooting
-### Performance Optimization
+### Performance optimization
> [!TIP]
> For large codebases, if your `pre-commit` runs longer than expected, it is highly recommended to add `files` in `.pre-commit-config.yaml` to limit the scope of the hook. This helps improve performance by reducing the number of files being checked and avoids unnecessary processing. Here's an example configuration:
@@ -254,10 +235,10 @@ or `-j`:
```
> [!WARNING]
-> When using `--jobs`/`-j`, avoid sharing options that write to a single output file
-> (for example `--export-fixes=fixes.yaml`) across parallel `clang-tidy` invocations.
-> If you need `--export-fixes`, ensure each job writes to a unique file path to avoid
-> corrupted or overwritten outputs.
+> When `args` include `--fix`, `-fix`, `-fix-errors` or `--export-fixes`, the hook ignores
+> `--jobs`. pre-commit itself still runs the hook on groups of files in parallel, so each group
+> overwrites a shared `--export-fixes` file and fixes to the same header can collide. Add
+> `require_serial: true` to the hook to run it once for all files.
Alternatively, if you want to run the hooks manually on only the changed files, you can use the following command:
@@ -267,12 +248,13 @@ 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
+### Verbose output
> [!NOTE]
> Use `-v` or `--verbose` in `args` to enable verbose output.
> For `clang-format`, it shows the list of processed files.
> For `clang-tidy`, it prints which `compile_commands.json` is being used (when auto-detected or explicitly set).
+> pre-commit shows this output only when the hook fails; add `verbose: true` to the hook to see it on every run.
```yaml
repos:
@@ -285,65 +267,44 @@ repos:
args: [--verbose] # Shows which compile_commands.json is used
```
-## Examples
+## Compared with mirrors-clang-format
-Two self-contained templates plus quick snippets for other common setups.
-
-- [CMake minimal config](examples/cmake/) — covers ~80% of C++ projects
-- [Large project `files:` regex](examples/large-project/) — scoping hooks for speed
-- [Quick snippets](examples/README.md) — Meson, clang-format-only, monorepo, CI, `compile_commands.json`
-
-## Used By
-
-
-
- MIT ACL
-
- Bazel Contrib
-
- CodSpeed
-
- doldecomp
-
- HKUST Aerial Robotics
-
-
- Kubewarden
-
- Computational Geography
-
- IMSY
-
- CONVINCE-Project
- and many more.
-
- See the cpp-linter showcase for projects using cpp-linter tools.
-
-
-## FAQ
-
-### What's the difference between [`cpp-linter-hooks`](https://github.com/cpp-linter/cpp-linter-hooks) and [`mirrors-clang-format`](https://github.com/pre-commit/mirrors-clang-format)?
+[mirrors-clang-format](https://github.com/pre-commit/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` | ✅ (`clang-format` & `clang-tidy`)| ✅ (`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 — see release notes for bundled tool version | Equals the clang-format version directly |
-| Supports passing format style string | ✅ via `--style` | ❌ |
-| Verbose output | ✅ via `--verbose` | ❌ |
-| Dry-run mode | ✅ via `--dry-run` | ❌ |
-| Auto-fix mode | ✅ via `--fix` (clang-tidy only) | ❌ |
-| Compilation database support | ✅ auto-detect or `--compile-commands` | ❌ |
-
-
-
+| 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` (v1.6.0 always passes) | 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](https://github.com/mit-acl) ·
+[
Bazel Contrib](https://github.com/bazel-contrib) ·
+[
CodSpeed](https://github.com/CodSpeedHQ) ·
+[
doldecomp](https://github.com/doldecomp) ·
+[
HKUST Aerial Robotics](https://github.com/HKUST-Aerial-Robotics) ·
+[
Kubewarden](https://github.com/kubewarden) ·
+[
Computational Geography](https://github.com/computationalgeography) ·
+[
IMSY](https://github.com/IMSY-DKFZ) ·
+[
CONVINCE-Project](https://github.com/convince-project)
+
+The [showcase](https://cpp-linter.github.io/showcase/) lists more projects that use cpp-linter tools.
## Contributing
-We welcome contributions! Whether it's fixing issues, suggesting improvements, or submitting pull requests, your support is greatly appreciated.
+See the [contributing guide](https://github.com/cpp-linter/cpp-linter-hooks/blob/main/CONTRIBUTING.md) and [open an issue](https://github.com/cpp-linter/cpp-linter-hooks/issues) for bugs and feature requests.
## License
-This project is licensed under the [MIT License](LICENSE).
+This project is licensed under the [MIT License](https://github.com/cpp-linter/cpp-linter-hooks/blob/main/LICENSE).
diff --git a/examples/README.md b/examples/README.md
index d5bfbd5..ea0e53e 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,6 +1,6 @@
# Examples
-- [CMake project](cmake/) — the default for ~80% of C++ projects
+- [CMake project](cmake/)
- [Large project `files:` regex](large-project/) — scoping hooks for speed
## Quick snippets
@@ -19,13 +19,13 @@
meson setup build # auto-detect works with build/
```
-Or point explicitly: `args: [--compile-commands=builddir, --checks=.clang-tidy]`.
+Or point explicitly: `args: [--compile-commands=builddir]`.
### clang-tidy + compile_commands.json
```yaml
- id: clang-tidy
- args: [--compile-commands=build, --checks=.clang-tidy, --version=21, --jobs=4]
+ args: [--compile-commands=build, --version=21, --jobs=4]
files: ^src/.*\.cpp$
```
@@ -55,8 +55,8 @@ jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
+ - uses: actions/checkout@v7
+ - uses: actions/setup-python@v7
with: { python-version: '3.11' }
- uses: pre-commit/action@v3.0.1
```
diff --git a/examples/cmake/README.md b/examples/cmake/README.md
index 4d07ff7..3a1fda3 100644
--- a/examples/cmake/README.md
+++ b/examples/cmake/README.md
@@ -7,14 +7,14 @@ If you already have a CMake project, you need **two files**:
```yaml
repos:
- repo: https://github.com/cpp-linter/cpp-linter-hooks
- rev: v1.5.0
+ rev: v1.6.0
hooks:
- id: clang-format
args: [--style=file, --version=21]
files: ^(src|include)/.*\.(cpp|cc|cxx|h|hpp)$
- id: clang-tidy
- args: [--checks=.clang-tidy, --version=21]
+ args: [--version=21]
files: ^(src|include)/.*\.(cpp|cc|cxx)$
```
diff --git a/examples/large-project/README.md b/examples/large-project/README.md
index 7d10da6..0311439 100644
--- a/examples/large-project/README.md
+++ b/examples/large-project/README.md
@@ -35,4 +35,4 @@ files: \.(c|h|s|S)$
- **Don't lint headers directly with `clang-tidy`** — they're processed when a `.cpp` includes them. Restrict to `files: ^src/.*\.cpp$`.
- **Use `--jobs=N` for `clang-tidy`** — start with `N=2`, go up to CPU core count.
-- **`--dry-run` for `clang-format` in CI** — fail with a readable diff instead of auto-committing formatting.
+- **`--dry-run` for `clang-format` in CI** — report the lines that need formatting instead of changing the files.