| name | static-analysis |
| description | Run static analysis tools on changed files and generate a report |
Static Analysis Skill
Run available static analysis tools on changed files and produce a structured report.
When to Use
| Context | Trigger |
|---|
| Standalone | User asks to run static analysis, linters, or check code quality |
| PR Review | Invoked by pr-review before manual code review |
| Pre-commit | User wants to check code before committing |
Workflow
┌─────────────────────────────────────────────────────────────────┐
│ Phase 1: Get Changed Files │
│ Determine scope (PR, staged, or all changes) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Phase 2: Detect Available Tools │
│ Check which tools are installed on the system │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Phase 3: Run Tools on Changed Files │
│ Execute each tool, capture output │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Phase 4: Generate Report │
│ Parse output, categorize by severity, format report │
└─────────────────────────────────────────────────────────────────┘
Phase 1: Get Changed Files
Determine Scope
Ask user or detect automatically:
| Scope | Command | Use When |
|---|
| PR changes | git diff --name-only <base>...HEAD | Reviewing a PR |
| Staged | git diff --name-only --cached | Pre-commit check |
| Unstaged | git diff --name-only | Check current work |
| All uncommitted | git diff --name-only HEAD | Local changes review |
| Specific files | User-provided list | Targeted analysis |
base_branch=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
[ -z "$base_branch" ] && base_branch="main"
case "$scope" in
pr) changed_files=$(git diff --name-only "$base_branch"...HEAD) ;;
staged) changed_files=$(git diff --name-only --cached) ;;
all) changed_files=$(git diff --name-only HEAD) ;;
esac
Filter by Language
cpp_files=$(echo "$changed_files" | grep -E '\.(cpp|cc|cxx|c|hpp|h)$' | tr '\n' ' ')
py_files=$(echo "$changed_files" | grep -E '\.py$' | tr '\n' ' ')
sh_files=$(echo "$changed_files" | grep -E '\.(sh|bash)$' | tr '\n' ' ')
cmake_files=$(echo "$changed_files" | grep -E '(CMakeLists\.txt|\.cmake)$' | tr '\n' ' ')
Phase 2: Detect Available Tools
which clang-tidy >/dev/null 2>&1 && echo "clang-tidy: available"
which cppcheck >/dev/null 2>&1 && echo "cppcheck: available"
which ruff >/dev/null 2>&1 && echo "ruff: available"
which pylint >/dev/null 2>&1 && echo "pylint: available"
which mypy >/dev/null 2>&1 && echo "mypy: available"
which shellcheck >/dev/null 2>&1 && echo "shellcheck: available"
which cmake-lint >/dev/null 2>&1 && echo "cmake-lint: available"
Check for compile_commands.json (C++)
if [ -f "build/compile_commands.json" ]; then
echo "compile_commands.json: build/"
elif [ -f "compile_commands.json" ]; then
echo "compile_commands.json: ./"
else
echo "compile_commands.json: NOT FOUND (clang-tidy may not work)"
fi
Use IDE Diagnostics (if available)
If running in VS Code with MCP:
Use mcp__ide__getDiagnostics to get real-time diagnostics
Phase 3: Run Tools on Changed Files
C++ Tools
clang-tidy:
if [ -n "$cpp_files" ] && which clang-tidy >/dev/null 2>&1; then
compile_db=""
[ -f "build/compile_commands.json" ] && compile_db="-p build/"
[ -f "compile_commands.json" ] && compile_db="-p ."
for file in $cpp_files; do
[ -f "$file" ] && clang-tidy "$file" $compile_db 2>&1
done
fi
cppcheck:
if [ -n "$cpp_files" ] && which cppcheck >/dev/null 2>&1; then
cppcheck --enable=warning,style,performance $cpp_files 2>&1
fi
Python Tools
ruff (recommended - fast):
if [ -n "$py_files" ] && which ruff >/dev/null 2>&1; then
ruff check $py_files 2>&1
fi
pylint:
if [ -n "$py_files" ] && which pylint >/dev/null 2>&1; then
pylint --output-format=text $py_files 2>&1
fi
mypy:
if [ -n "$py_files" ] && which mypy >/dev/null 2>&1; then
mypy $py_files 2>&1
fi
Shell Tools
shellcheck:
if [ -n "$sh_files" ] && which shellcheck >/dev/null 2>&1; then
shellcheck $sh_files 2>&1
fi
CMake Tools
cmake-lint:
if [ -n "$cmake_files" ] && which cmake-lint >/dev/null 2>&1; then
cmake-lint $cmake_files 2>&1
fi
Phase 4: Generate Report
Severity Mapping
| Tool | Check/Code | Severity |
|---|
| clang-tidy | bugprone-*, clang-analyzer-* | Critical (100) |
| clang-tidy | performance-* | Should Fix (50) |
| clang-tidy | modernize-*, readability-* | Nitpick (20) |
| cppcheck | error | Critical (100) |
| cppcheck | warning | Must Fix (80) |
| cppcheck | style, performance | Should Fix (50) |
| ruff | E (error), F (pyflakes) | Must Fix (80) |
| ruff | W (warning) | Should Fix (50) |
| ruff | C, N (convention, naming) | Nitpick (20) |
| pylint | E, F (error, fatal) | Critical (100) |
| pylint | W (warning) | Should Fix (50) |
| pylint | C, R (convention, refactor) | Nitpick (20) |
| mypy | error | Must Fix (80) |
| shellcheck | error | Must Fix (80) |
| shellcheck | warning | Should Fix (50) |
| shellcheck | info, style | Nitpick (20) |
Report Format
# Static Analysis Report
**Scope:** [PR #123 / staged changes / all uncommitted]
**Files analyzed:** X files
**Tools run:** clang-tidy, ruff, shellcheck
## Summary
| Severity | Count |
|----------|-------|
| 🔴 Critical | X |
| 🟠 Must Fix | X |
| 🟡 Should Fix | X |
| 🔵 Nitpick | X |
**Total issues:** X
---
## 🔴 Critical Issues (X)
### 1. bugprone-use-after-move
**File:** `src/parser.cpp:42`
**Tool:** clang-tidy
**Severity:** Critical (100)
**Message:**
'data' used after it was moved
**Context:**
```cpp
auto result = std::move(data);
process(data); // Bug: data was moved
🟠 Must Fix (X)
2. performance-unnecessary-copy-initialization
File: src/handler.cpp:78
Tool: clang-tidy
Severity: Should Fix (50)
Message:
The copy 'config' is only used as const reference; consider making it a const reference
🟡 Should Fix (X)
...
🔵 Nitpicks (X)
...
Tools Not Available
The following tools were not found and could not be run:
cppcheck - Install with: apt install cppcheck
mypy - Install with: pip install mypy
No Issues Found
✅ No issues detected by static analysis tools.
## Integration with pr-review
When invoked from `pr-review`:
1. `pr-review` calls `static-analysis` with PR scope
2. `static-analysis` runs tools and generates report
3. Report is included in PR review under "Static Analysis Results"
4. Issues are merged with manual review findings by severity
```markdown
## How pr-review uses this skill:
1. Invoke static-analysis skill with scope=pr
2. Get the generated report
3. Include report in Phase 4 (Code Review) findings
4. Critical/Must Fix issues from tools → Must Fix in review
5. Should Fix from tools → Should Fix in review
6. Nitpicks from tools → Nitpick in review
Standalone Usage
When run standalone, output the full report to the user.
Example invocations:
- "run static analysis" → analyze all uncommitted changes
- "run static analysis on staged files" → pre-commit check
- "run clang-tidy on the PR" → C++ analysis only
- "check code quality" → full analysis with report
Tool Installation Reference
| Tool | Language | Install Command |
|---|
| clang-tidy | C++ | apt install clang-tidy or comes with LLVM |
| cppcheck | C++ | apt install cppcheck |
| ruff | Python | pip install ruff |
| pylint | Python | pip install pylint |
| mypy | Python | pip install mypy |
| shellcheck | Shell | apt install shellcheck |
| cmake-lint | CMake | pip install cmakelint |