{"id":18996310,"url":"https://github.com/cpp-linter/cpp-linter-hooks","last_synced_at":"2026-04-06T23:04:27.903Z","repository":{"id":44340925,"uuid":"502861149","full_name":"cpp-linter/cpp-linter-hooks","owner":"cpp-linter","description":"C/C++ code linter hooks for pre-commit","archived":false,"fork":false,"pushed_at":"2025-03-27T10:09:30.000Z","size":109,"stargazers_count":21,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-16T08:58:41.984Z","etag":null,"topics":["clang","clang-format","clang-tidy","pre-commit","pre-commit-hook","pre-commit-hooks"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cpp-linter.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-13T08:00:00.000Z","updated_at":"2025-04-09T00:33:11.000Z","dependencies_parsed_at":"2024-02-27T02:45:11.425Z","dependency_job_id":"26941ade-8741-4c58-8f7b-01597ed4863f","html_url":"https://github.com/cpp-linter/cpp-linter-hooks","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpp-linter%2Fcpp-linter-hooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpp-linter%2Fcpp-linter-hooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpp-linter%2Fcpp-linter-hooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpp-linter%2Fcpp-linter-hooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cpp-linter","download_url":"https://codeload.github.com/cpp-linter/cpp-linter-hooks/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250252225,"owners_count":21399956,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clang","clang-format","clang-tidy","pre-commit","pre-commit-hook","pre-commit-hooks"],"created_at":"2024-11-08T17:34:39.154Z","updated_at":"2026-04-06T23:04:27.896Z","avatar_url":"https://github.com/cpp-linter.png","language":"Python","readme":"# cpp-linter-hooks\n\n[![PyPI](https://img.shields.io/pypi/v/cpp-linter-hooks?color=blue)](https://pypi.org/project/cpp-linter-hooks/)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cpp-linter-hooks)](https://pypi.org/project/cpp-linter-hooks/)\n[![codecov](https://codecov.io/gh/cpp-linter/cpp-linter-hooks/branch/main/graph/badge.svg?token=L74Z3HZ4Y5)](https://codecov.io/gh/cpp-linter/cpp-linter-hooks)\n[![Test](https://github.com/cpp-linter/cpp-linter-hooks/actions/workflows/test.yml/badge.svg)](https://github.com/cpp-linter/cpp-linter-hooks/actions/workflows/test.yml)\n[![CodeQL](https://github.com/cpp-linter/cpp-linter-hooks/actions/workflows/codeql.yml/badge.svg)](https://github.com/cpp-linter/cpp-linter-hooks/actions/workflows/codeql.yml)\n\nA pre-commit hook that automatically formats and lints your C/C++ code using `clang-format` and `clang-tidy`.\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n  - [Custom Configuration Files](#custom-configuration-files)\n  - [Custom Clang Tool Version](#custom-clang-tool-version)\n  - [Compilation Database (CMake/Meson Projects)](#compilation-database-cmakemeson-projects)\n- [Output](#output)\n  - [clang-format Output](#clang-format-output)\n  - [clang-tidy Output](#clang-tidy-output)\n- [Troubleshooting](#troubleshooting)\n  - [Performance Optimization](#performance-optimization)\n  - [Verbose Output](#verbose-output)\n- [FAQ](#faq)\n  - [What's the difference between `cpp-linter-hooks` and `mirrors-clang-format`?](#whats-the-difference-between-cpp-linter-hooks-and-mirrors-clang-format)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Quick Start\n\nAdd this configuration to your `.pre-commit-config.yaml` file:\n\n```yaml\nrepos:\n  - repo: https://github.com/cpp-linter/cpp-linter-hooks\n    rev: v1.4.0  # Use the tag or commit you want\n    hooks:\n      - id: clang-format\n        args: [--style=Google] # Other coding style: LLVM, GNU, Chromium, Microsoft, Mozilla, WebKit.\n      - id: clang-tidy\n        args: [--checks='boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*,clang-analyzer-*,cppcoreguidelines-*']\n```\n\n### Custom Configuration Files\n\nTo use custom configurations like `.clang-format` and `.clang-tidy`:\n\n```yaml\nrepos:\n  - repo: https://github.com/cpp-linter/cpp-linter-hooks\n    rev: v1.4.0\n    hooks:\n      - id: clang-format\n        args: [--style=file]  # Loads style from .clang-format file\n      - id: clang-tidy\n        args: [--checks=.clang-tidy] # Loads checks from .clang-tidy file\n```\n\n\u003e [!TIP]\n\u003e The `rev` tag (e.g. `v1.4.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.\n\n### Custom Clang Tool Version\n\nTo use specific versions of clang-format and clang-tidy (using Python wheel packages):\n\n```yaml\nrepos:\n  - repo: https://github.com/cpp-linter/cpp-linter-hooks\n    rev: v1.4.0\n    hooks:\n      - id: clang-format\n        args: [--style=file, --version=21] # Specifies version\n      - id: clang-tidy\n        args: [--checks=.clang-tidy, --version=21] # Specifies version\n```\n\n\u003e [!TIP]\n\u003e 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.\n\n### Compilation Database (CMake/Meson Projects)\n\nFor CMake or Meson projects, clang-tidy works best with a `compile_commands.json`\nfile that records the exact compiler flags used for each file. Without it, clang-tidy\nmay report false positives from missing include paths or wrong compiler flags.\n\nThe hook auto-detects `compile_commands.json` in common build directories (`build/`,\n`out/`, `cmake-build-debug/`, `_build/`) and passes `-p \u003cdir\u003e` to clang-tidy\nautomatically — no configuration needed for most projects:\n\n```yaml\nrepos:\n  - repo: https://github.com/cpp-linter/cpp-linter-hooks\n    rev: v1.4.0\n    hooks:\n      - id: clang-tidy\n        args: [--checks=.clang-tidy]\n        # Auto-detects ./build/compile_commands.json if present\n```\n\nTo specify the build directory explicitly:\n\n```yaml\n      - id: clang-tidy\n        args: [--compile-commands=build, --checks=.clang-tidy]\n```\n\nTo disable auto-detection (e.g. in a monorepo where auto-detect might pick the wrong database):\n\n```yaml\n      - id: clang-tidy\n        args: [--no-compile-commands, --checks=.clang-tidy]\n```\n\nTo see which `compile_commands.json` the hook is using, add `-v`:\n\n```yaml\n      - id: clang-tidy\n        args: [--compile-commands=build, -v, --checks=.clang-tidy]\n```\n\n\u003e [!NOTE]\n\u003e Generate `compile_commands.json` with CMake using `cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -Bbuild .`\n\u003e or add `set(CMAKE_EXPORT_COMPILE_COMMANDS ON)` to your `CMakeLists.txt`.\n\u003e `--compile-commands` takes the **directory** containing `compile_commands.json`, not the file path itself.\n\n## Output\n\n### clang-format Output\n\n```bash\nclang-format.............................................................Failed\n- hook id: clang-format\n- files were modified by this hook\n```\n\nHere’s a sample diff showing the formatting applied:\n\n```diff\n--- a/testing/main.c\n+++ b/testing/main.c\n@@ -1,3 +1,6 @@\n #include \u003cstdio.h\u003e\n-int main() {for (;;) break; printf(\"Hello world!\\n\");return 0;}\n-\n+int main() {\n+  for (;;) break;\n+  printf(\"Hello world!\\n\");\n+  return 0;\n+}\n```\n\u003e [!NOTE]\n\u003e Use `--dry-run` in `args` of `clang-format` to print instead of changing the format, e.g.:\n\n```bash\nclang-format.............................................................Failed\n- hook id: clang-format\n- exit code: 255\n\nmain.c:2:11: warning: code should be clang-formatted [-Wclang-format-violations]\nint main() {for (;;) break; printf(\"Hello world!\\n\");return 0;}\n          ^\nmain.c:2:13: warning: code should be clang-formatted [-Wclang-format-violations]\nint main() {for (;;) break; printf(\"Hello world!\\n\");return 0;}\n            ^\nmain.c:2:21: warning: code should be clang-formatted [-Wclang-format-violations]\nint main() {for (;;) break; printf(\"Hello world!\\n\");return 0;}\n                    ^\nmain.c:2:28: warning: code should be clang-formatted [-Wclang-format-violations]\nint main() {for (;;) break; printf(\"Hello world!\\n\");return 0;}\n                           ^\nmain.c:2:54: warning: code should be clang-formatted [-Wclang-format-violations]\nint main() {for (;;) break; printf(\"Hello world!\\n\");return 0;}\n                                                     ^\nmain.c:2:63: warning: code should be clang-formatted [-Wclang-format-violations]\nint main() {for (;;) break; printf(\"Hello world!\\n\");return 0;}\n                                                              ^\n```\n\n### clang-tidy Output\n\n```bash\nclang-tidy...............................................................Failed\n- hook id: clang-tidy\n- exit code: 1\n\n522 warnings generated.\nSuppressed 521 warnings (521 in non-user code).\nUse -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.\n/home/runner/work/cpp-linter-hooks/cpp-linter-hooks/testing/main.c:4:13: warning: statement should be inside braces [readability-braces-around-statements]\n    for (;;)\n            ^\n             {\n\n```\n\n\u003e [!NOTE]\n\u003e Add `--fix` to `args` to automatically apply clang-tidy fixes in place (equivalent to\n\u003e passing `-fix` to clang-tidy directly). This is **opt-in** and **not the default** because\n\u003e auto-fixing can modify source files in unexpected ways. A valid `compile_commands.json` is\n\u003e strongly recommended when using `--fix`.\n\u003e\n\u003e For cases where compiler errors exist alongside style issues, pass `-fix-errors` directly\n\u003e in `args` instead (clang-tidy native flag).\n\n```yaml\nrepos:\n  - repo: https://github.com/cpp-linter/cpp-linter-hooks\n    rev: v1.4.0  # requires the version that introduced --fix\n    hooks:\n      - id: clang-tidy\n        args: [--checks=.clang-tidy, --fix]\n```\n\n\u003e [!WARNING]\n\u003e When `--fix` (or `-fix-errors`) is active, parallel execution via `--jobs`/`-j` is\n\u003e automatically disabled to prevent concurrent writes to the same header file.\n\n## Troubleshooting\n\n### Performance Optimization\n\n\u003e [!TIP]\n\u003e 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:\n\n```yaml\n- repo: https://github.com/cpp-linter/cpp-linter-hooks\n  rev: v1.4.0\n  hooks:\n    - id: clang-format\n      args: [--style=file, --version=21]\n      files: ^(src|include)/.*\\.(cpp|cc|cxx|h|hpp)$ # Limits to specific dirs and file types\n    - id: clang-tidy\n      args: [--checks=.clang-tidy, --version=21]\n      files: ^(src|include)/.*\\.(cpp|cc|cxx|h|hpp)$\n```\n\nFor `clang-tidy`, you can also process multiple files in parallel by adding `--jobs`\nor `-j`:\n\n```yaml\n- repo: https://github.com/cpp-linter/cpp-linter-hooks\n  rev: v1.4.0\n  hooks:\n    - id: clang-tidy\n      args: [--checks=.clang-tidy, --version=21, --jobs=4]\n```\n\n\u003e [!WARNING]\n\u003e When using `--jobs`/`-j`, avoid sharing options that write to a single output file\n\u003e (for example `--export-fixes=fixes.yaml`) across parallel `clang-tidy` invocations.\n\u003e If you need `--export-fixes`, ensure each job writes to a unique file path to avoid\n\u003e corrupted or overwritten outputs.\nAlternatively, if you want to run the hooks manually on only the changed files, you can use the following command:\n\n```bash\npre-commit run --files $(git diff --name-only)\n```\n\nThis approach ensures that only modified files are checked, further speeding up the linting process during development.\n\n### Verbose Output\n\n\u003e [!NOTE]\n\u003e Use `-v` or `--verbose` in `args` to enable verbose output.\n\u003e For `clang-format`, it shows the list of processed files.\n\u003e For `clang-tidy`, it prints which `compile_commands.json` is being used (when auto-detected or explicitly set).\n\n```yaml\nrepos:\n  - repo: https://github.com/cpp-linter/cpp-linter-hooks\n    rev: v1.4.0\n    hooks:\n      - id: clang-format\n        args: [--style=file, --version=21, --verbose]   # Shows processed files\n      - id: clang-tidy\n        args: [--checks=.clang-tidy, --verbose]   # Shows which compile_commands.json is used\n```\n\n## FAQ\n\n### 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)?\n\n| Feature                          | `cpp-linter-hooks`                        | `mirrors-clang-format`                 |\n|----------------------------------|-------------------------------------------|----------------------------------------|\n| Supports `clang-format` and `clang-tidy` | ✅ (`clang-format` \u0026 `clang-tidy`)| ✅ (`clang-format` only)              |\n| Custom configuration files       | ✅ `.clang-format`, `.clang-tidy`         | ✅ `.clang-format`                    |\n| Specify tool version             | ✅ via `--version` arg (e.g. `--version=21`) | ✅ via `rev` tag (e.g. `rev: v21.1.8`) |\n| `rev` tag meaning                | Project version — see release notes for bundled tool version | Equals the clang-format version directly |\n| Supports passing format style string | ✅ via `--style`                      | ❌                                    |\n| Verbose output                   | ✅ via `--verbose`                        | ❌                                    |\n| Dry-run mode                     | ✅ via `--dry-run`                        | ❌                                    |\n| Auto-fix mode                    | ✅ via `--fix` (clang-tidy only)          | ❌                                    |\n| Compilation database support     | ✅ auto-detect or `--compile-commands`    | ❌                                    |\n\n\n\u003c!-- \u003e [!TIP]\n\u003e In most cases, there is no significant performance difference between `cpp-linter-hooks` and `mirrors-clang-format`. See the [benchmark results](testing/benchmark.md) for details. --\u003e\n\n## Contributing\n\nWe welcome contributions! Whether it's fixing issues, suggesting improvements, or submitting pull requests, your support is greatly appreciated.\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcpp-linter%2Fcpp-linter-hooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcpp-linter%2Fcpp-linter-hooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcpp-linter%2Fcpp-linter-hooks/lists"}