From harness-anchor
Performs static analysis on C/C++ code using clang-tidy, cppcheck, and IWYU. Designed for incremental review of changed lines, needs compile_commands.json.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-anchor:cpp-static-analysisThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Static analysis catches an enormous class of bugs at zero runtime cost: null derefs, leaks, dangling refs, integer overflow, missing initializers, unused includes, banned APIs.
Static analysis catches an enormous class of bugs at zero runtime cost: null derefs, leaks, dangling refs, integer overflow, missing initializers, unused includes, banned APIs.
Three core tools cover most needs:
| Tool | What it catches | Cost |
|---|---|---|
| clang-tidy | Style + correctness + modernize + bugprone | Heavy (uses full AST) |
| cppcheck | Quick correctness, leaks, off-by-one | Light (own parser) |
| IWYU | Missing/superfluous #include | Heavy (compile-driven) |
compile_commands.json exists at project root or symlinkedclang-tidy --version, cppcheck --version, include-what-you-use --version).clang-tidy config exists at project root (use template if not)If any prerequisite is missing, say so explicitly instead of pretending to analyze:
"Cannot run clang-tidy because compile_commands.json is missing. Generate it via
cmake -S . -B .build -DCMAKE_EXPORT_COMPILE_COMMANDS=ONthen symlink to root."
After an Edit/Write to a .c/.cpp/.h file:
clang-tidy -p .build --quiet path/to/changed_file.cpp
-p .build points at compile_commands.json's directory--quiet suppresses progress noisescripts/lint.sh)For changed lines only (large existing codebases), use clang-tidy-diff.py:
git diff -U0 main | clang-tidy-diff.py -p1 -path .build
run-clang-tidy -p .build -quiet -j$(nproc) > clang-tidy-report.txt 2>&1
Use sparingly — slow on large codebases.
'<header>' file not found (Homebrew clang-tidy)compile_commands.json produced with Apple clang (/usr/bin/c++) implies the macOS SDK;
Homebrew clang-tidy does not know it. Without a sysroot it fails to parse the TU
(error: 'atomic' file not found or similar) — and diagnostics from a failed parse are
garbage: the half-parsed TU yields false positives (bogus const/naming/static
suggestions). Do not act on them; capture the real signal first (self-correction-loop).
Fix — point clang-tidy at the active SDK:
clang-tidy -p .build \
--extra-arg=-isysroot --extra-arg="$(xcrun --show-sdk-path)" \
path/to/changed_file.cpp
Or use the project wrapper scripts/lint.sh (dropped by /cpp-init), which locates the
compilation database (root / .build/ / build/ / builddir/, same search order as the
PostToolUse hook) and injects the sysroot automatically on macOS. The hook applies the
same fix and suppresses its diagnostics entirely when the TU still fails to parse.
| Category | What it covers | Recommendation |
|---|---|---|
bugprone-* | Likely bugs | Always on |
cert-* | CERT secure coding | Often on |
clang-analyzer-* | Path-sensitive analysis | Always on |
cppcoreguidelines-* | C++ Core Guidelines | Selective |
modernize-* | Convert to modern idioms | Off in legacy code, on in greenfield |
performance-* | Perf antipatterns | Selective |
readability-* | Style | Selective |
The template .clang-tidy enables a safe baseline; tune per project.
cppcheck --enable=warning,style,performance,portability --suppress=missingIncludeSystem -j$(nproc) src/ 2>&1
cppcheck catches things clang-tidy misses (and vice versa). Run before claiming a feature done.
include-what-you-use -Xiwyu --no_fwd_decls path/to/file.cpp 2>&1
Reports: which includes are unused, which symbols come from indirect includes (should be added). Use iwyu_tool.py for project-wide.
Note: IWYU has false positives; review suggestions, don't auto-apply.
The clang-analyzer-* checks in the baseline .clang-tidy are the Clang Static Analyzer
(path-sensitive, inter-procedural symbolic execution), run per translation unit. clang-tidy
already gives you CSA coverage — don't treat a separate analyzer run as "new" findings.
scan-build is the same engine driven across a whole build: it wraps your compiler
(no compile_commands.json needed) and emits browsable HTML reports tracing each bug's path.
scan-build --view make # wraps the build; --view opens the HTML report
Reach for scan-build only for whole-program / cross-TU findings or HTML triage — otherwise
the per-file clang-tidy path (including the PostToolUse hook) already covers you.
GCC 10+ ships its own static analyzer — a different engine from clang-tidy, so it's a genuine second opinion: double-free, use-after-free, leaks, null derefs, taint, fd misuse.
gcc -fanalyzer -c path/to/file.c # warnings on stderr; uses the compiler you already have
Caveat (important): the GCC manual states -fanalyzer is "only suitable for use on C
code" — C++ is not officially supported. For C++, stay on clang-tidy + cppcheck. Use
-fanalyzer as a free extra pass on C builds.
The PostToolUse hook surfaces clang-tidy warnings as additionalContext. You see them on the next turn. You decide whether to fix each one — there are legitimate reasons to suppress (e.g., // NOLINT(specific-check) with a comment).
Anti-patterns:
// NOLINTBEGIN/NOLINTEND on hundreds of lines).clang-tidy to "make it stop"If a warning is wrong (false positive), file a one-line // NOLINT(check-name) — reason with explanation. Be specific.
If a warning is in code you didn't change (legacy area) and not a regression risk, defer it: note in progress.md, don't fix in this session. Scope discipline.
When you encounter a clang-tidy check name you don't recognize (e.g. bugprone-suspicious-enum-usage, cert-err58-cpp), or an unfamiliar cppcheck ID / IWYU pragma — invoke the docs-lookup skill. It handles Context7 → WebSearch fallback (with explicit failure-mode detection) so you don't silently substitute a guess.
Typical entry query: clang-tidy <check-name> or cppcheck <id>.
.clang-tidy baseline config: templates/cpp/.clang-tidy.tpl (copied by /cpp-init)scripts/lint.sh sysroot-aware clang-tidy wrapper: templates/cpp/lint.sh.tpl (copied by /cpp-init)tool-comparison.md for clang-tidy vs cppcheck vs IWYU side-by-side decisions.compile_commands.json; CMake + Ninja (-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja)
produces one on Windows — MSBuild generators do NOT. No sysroot injection is needed
(that is a macOS-only concern); the PostToolUse hook already skips xcrun off-Darwin.cl.exe commands), clang-tidy auto-detects driver
mode in most setups; if the TU fails to parse, the diagnostics-are-garbage rule
applies unchanged — verify via the build or scripts/lint.sh, don't act on them.-fanalyzer guidance is unchanged (MinGW GCC works; still C-only).npx claudepluginhub redtropig/harness-anchor --plugin harness-anchorRuns cppcheck, clang-tidy, or GCC -fanalyzer static analysis on embedded C/C++ code, with optional MISRA-C 2012 compliance checking.
Formats C/C++ code with clang-format, focusing on changed lines only to avoid diff pollution. Provides commands for formatting, verification, and .clang-format configuration.
Configures clang-format code formatting: creates .clang-format from templates, analyzes code styles to generate configs, troubleshoots issues, integrates with git and editors.