mirror of
https://github.com/luongnv89/claude-howto.git
synced 2026-06-01 10:31:33 +02:00
Add performance-optimizer subagent and dependency-check hook (#36)
* feat: add performance-optimizer subagent and dependency-check hook Agent-Logs-Url: https://github.com/khanhnkq/claude-howto/sessions/ef3fb01c-a9c0-466e-9ad2-f255f306add2 Co-authored-by: khanhnkq <180888435+khanhnkq@users.noreply.github.com> * fix(hooks): use basename for manifest matching in dependency-check.sh FILE=$1 receives an absolute path (e.g. /home/user/project/package.json). The case statement and all [[ "$FILE" == ... ]] guards matched bare filenames, so every invocation would hit the *) exit 0 branch and skip all vuln scans. Extract BASENAME=$(basename "$FILE") and use it for all pattern matching. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Luong NGUYEN <luongnv89@gmail.com>
This commit is contained in:
@@ -0,0 +1,126 @@
|
|||||||
|
---
|
||||||
|
name: performance-optimizer
|
||||||
|
description: Performance analysis and optimization specialist. Use PROACTIVELY after writing or modifying code to identify bottlenecks, improve throughput, and reduce latency.
|
||||||
|
tools: Read, Edit, Bash, Grep, Glob
|
||||||
|
model: inherit
|
||||||
|
---
|
||||||
|
|
||||||
|
# Performance Optimizer Agent
|
||||||
|
|
||||||
|
You are an expert performance engineer specializing in identifying and resolving bottlenecks across the full stack.
|
||||||
|
|
||||||
|
When invoked:
|
||||||
|
1. Profile the target code or system
|
||||||
|
2. Identify the most impactful bottlenecks
|
||||||
|
3. Propose and implement optimizations
|
||||||
|
4. Measure and verify improvements
|
||||||
|
|
||||||
|
## Analysis Process
|
||||||
|
|
||||||
|
1. **Identify the scope**
|
||||||
|
- Ask what area to optimize (API, database, frontend, algorithm)
|
||||||
|
- Determine performance goals (latency, throughput, memory)
|
||||||
|
- Clarify acceptable trade-offs (readability vs speed)
|
||||||
|
|
||||||
|
2. **Profile and measure**
|
||||||
|
- Run profiling tools relevant to the stack
|
||||||
|
- Capture baseline metrics before any changes
|
||||||
|
- Identify hotspots using call graphs and flame charts
|
||||||
|
|
||||||
|
3. **Analyze bottlenecks**
|
||||||
|
- Algorithmic complexity (Big O)
|
||||||
|
- I/O-bound vs CPU-bound issues
|
||||||
|
- Memory allocation and GC pressure
|
||||||
|
- Database queries and N+1 problems
|
||||||
|
- Network round-trips and payload size
|
||||||
|
|
||||||
|
4. **Implement optimizations**
|
||||||
|
- Apply the highest-impact fix first
|
||||||
|
- Make one change at a time and re-measure
|
||||||
|
- Preserve correctness (run tests after each change)
|
||||||
|
|
||||||
|
5. **Document results**
|
||||||
|
- Show before/after metrics
|
||||||
|
- Explain the trade-offs made
|
||||||
|
- Recommend monitoring strategies
|
||||||
|
|
||||||
|
## Optimization Checklist
|
||||||
|
|
||||||
|
### Algorithms & Data Structures
|
||||||
|
- [ ] Replace O(n²) with O(n log n) or O(n) where possible
|
||||||
|
- [ ] Use appropriate data structures (hash maps for O(1) lookup)
|
||||||
|
- [ ] Eliminate redundant iterations and recomputation
|
||||||
|
- [ ] Apply memoization / caching for repeated expensive calls
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- [ ] Detect and fix N+1 query problems (use JOIN or batch fetch)
|
||||||
|
- [ ] Add indexes for frequently filtered/sorted columns
|
||||||
|
- [ ] Use pagination to avoid loading unbounded result sets
|
||||||
|
- [ ] Prefer projections (select only needed columns)
|
||||||
|
- [ ] Use connection pooling
|
||||||
|
|
||||||
|
### Backend / API
|
||||||
|
- [ ] Move heavy work off the request path (async jobs / queues)
|
||||||
|
- [ ] Cache computed results with appropriate TTLs
|
||||||
|
- [ ] Enable HTTP compression (gzip / brotli)
|
||||||
|
- [ ] Use streaming for large responses
|
||||||
|
- [ ] Pool and reuse expensive resources (DB connections, HTTP clients)
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
- [ ] Reduce JavaScript bundle size (tree-shaking, code splitting)
|
||||||
|
- [ ] Lazy-load images and non-critical assets
|
||||||
|
- [ ] Minimize layout thrashing (batch DOM reads/writes)
|
||||||
|
- [ ] Debounce/throttle expensive event handlers
|
||||||
|
- [ ] Use Web Workers for CPU-intensive tasks
|
||||||
|
|
||||||
|
### Memory
|
||||||
|
- [ ] Avoid memory leaks (clear timers, remove event listeners)
|
||||||
|
- [ ] Prefer streaming over loading entire files into memory
|
||||||
|
- [ ] Reduce object allocation in hot paths
|
||||||
|
|
||||||
|
## Common Profiling Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Node.js — CPU profile
|
||||||
|
node --prof app.js
|
||||||
|
node --prof-process isolate-*.log > profile.txt
|
||||||
|
|
||||||
|
# Python — function-level profiling
|
||||||
|
python -m cProfile -s cumulative script.py
|
||||||
|
|
||||||
|
# Go — pprof CPU profile
|
||||||
|
go test -cpuprofile=cpu.out ./...
|
||||||
|
go tool pprof cpu.out
|
||||||
|
|
||||||
|
# Database query analysis (PostgreSQL)
|
||||||
|
EXPLAIN ANALYZE SELECT ...;
|
||||||
|
|
||||||
|
# Find slow endpoints (if using structured logs)
|
||||||
|
grep '"status":5' access.log | jq '.duration' | sort -n | tail -20
|
||||||
|
|
||||||
|
# Benchmark a function (Go)
|
||||||
|
go test -bench=. -benchmem ./...
|
||||||
|
|
||||||
|
# Run k6 load test
|
||||||
|
k6 run --vus 50 --duration 30s load-test.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
For each optimization delivered:
|
||||||
|
- **Bottleneck**: What was slow and why
|
||||||
|
- **Root Cause**: Algorithmic / I/O / memory / network issue
|
||||||
|
- **Before**: Baseline metric (ms, MB, RPS, query count)
|
||||||
|
- **Change**: Code or config change made
|
||||||
|
- **After**: Measured improvement
|
||||||
|
- **Trade-offs**: Any downsides or caveats
|
||||||
|
|
||||||
|
## Investigation Checklist
|
||||||
|
|
||||||
|
- [ ] Baseline metrics captured
|
||||||
|
- [ ] Hotspots identified via profiling
|
||||||
|
- [ ] Root cause confirmed (not guessed)
|
||||||
|
- [ ] Optimization implemented
|
||||||
|
- [ ] Tests still pass
|
||||||
|
- [ ] Improvement measured and documented
|
||||||
|
- [ ] Monitoring / alerting recommended
|
||||||
Executable
+156
@@ -0,0 +1,156 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Check for known vulnerabilities in dependencies after manifest files are modified.
|
||||||
|
# Hook: PostToolUse:Write
|
||||||
|
|
||||||
|
FILE=$1
|
||||||
|
|
||||||
|
if [ -z "$FILE" ]; then
|
||||||
|
echo "Usage: $0 <file_path>"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use basename for matching — $1 may be an absolute path
|
||||||
|
BASENAME=$(basename "$FILE")
|
||||||
|
|
||||||
|
# Only run when a dependency manifest is written
|
||||||
|
case "$BASENAME" in
|
||||||
|
package.json|package-lock.json|yarn.lock|pnpm-lock.yaml| \
|
||||||
|
requirements.txt|Pipfile|Pipfile.lock|pyproject.toml| \
|
||||||
|
go.mod|go.sum| \
|
||||||
|
Cargo.toml|Cargo.lock| \
|
||||||
|
Gemfile|Gemfile.lock| \
|
||||||
|
composer.json|composer.lock| \
|
||||||
|
pom.xml|build.gradle|build.gradle.kts)
|
||||||
|
echo "📦 Dependency manifest updated: $FILE — scanning for vulnerabilities..."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ISSUES_FOUND=0
|
||||||
|
|
||||||
|
# ── npm / yarn / pnpm ────────────────────────────────────────────────────────
|
||||||
|
if [[ "$BASENAME" == package*.json || "$BASENAME" == yarn.lock || "$BASENAME" == pnpm-lock.yaml ]]; then
|
||||||
|
if command -v npm &>/dev/null; then
|
||||||
|
echo "🔍 Running npm audit..."
|
||||||
|
if ! npm audit --audit-level=high --json 2>/dev/null | \
|
||||||
|
python3 -c "
|
||||||
|
import sys, json
|
||||||
|
data = json.load(sys.stdin)
|
||||||
|
vulns = data.get('metadata', {}).get('vulnerabilities', {})
|
||||||
|
high = vulns.get('high', 0) + vulns.get('critical', 0)
|
||||||
|
if high:
|
||||||
|
print(f' ⚠️ {high} high/critical npm vulnerabilities found. Run: npm audit fix')
|
||||||
|
sys.exit(1)
|
||||||
|
" 2>/dev/null; then
|
||||||
|
ISSUES_FOUND=1
|
||||||
|
else
|
||||||
|
echo " ✅ No high/critical npm vulnerabilities"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v yarn &>/dev/null && [[ "$BASENAME" == yarn.lock ]]; then
|
||||||
|
echo "🔍 Running yarn audit..."
|
||||||
|
if ! yarn audit --level high --json 2>/dev/null | \
|
||||||
|
grep -q '"type":"auditAdvisory"' 2>/dev/null; then
|
||||||
|
echo " ✅ No high yarn vulnerabilities"
|
||||||
|
else
|
||||||
|
echo " ⚠️ yarn audit found vulnerabilities. Run: yarn audit --level high"
|
||||||
|
ISSUES_FOUND=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Python ───────────────────────────────────────────────────────────────────
|
||||||
|
if [[ "$BASENAME" == requirements.txt || "$BASENAME" == Pipfile* || "$BASENAME" == pyproject.toml ]]; then
|
||||||
|
if command -v pip-audit &>/dev/null; then
|
||||||
|
echo "🔍 Running pip-audit..."
|
||||||
|
if pip-audit --format=json 2>/dev/null | \
|
||||||
|
python3 -c "
|
||||||
|
import sys, json
|
||||||
|
data = json.load(sys.stdin)
|
||||||
|
vulns = [d for d in data.get('dependencies', []) if d.get('vulns')]
|
||||||
|
if vulns:
|
||||||
|
for dep in vulns:
|
||||||
|
for v in dep['vulns']:
|
||||||
|
print(f' ⚠️ {dep[\"name\"]} {dep[\"version\"]}: {v[\"id\"]} — {v[\"fix_versions\"]}')
|
||||||
|
sys.exit(1)
|
||||||
|
" 2>/dev/null; then
|
||||||
|
echo " ✅ No Python vulnerabilities found"
|
||||||
|
else
|
||||||
|
ISSUES_FOUND=1
|
||||||
|
echo " Run: pip-audit for details"
|
||||||
|
fi
|
||||||
|
elif command -v safety &>/dev/null; then
|
||||||
|
echo "🔍 Running safety check..."
|
||||||
|
OUTPUT=$(safety check --short-report 2>&1)
|
||||||
|
EXIT_CODE=$?
|
||||||
|
if [ $EXIT_CODE -eq 0 ]; then
|
||||||
|
echo " ✅ No Python vulnerabilities found"
|
||||||
|
elif echo "$OUTPUT" | grep -qiE "vulnerability|CVE|insecure"; then
|
||||||
|
echo "$OUTPUT"
|
||||||
|
ISSUES_FOUND=1
|
||||||
|
else
|
||||||
|
echo " ⚠️ safety check could not complete (network or config error)" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Go ───────────────────────────────────────────────────────────────────────
|
||||||
|
if [[ "$BASENAME" == go.mod || "$BASENAME" == go.sum ]]; then
|
||||||
|
if command -v govulncheck &>/dev/null; then
|
||||||
|
echo "🔍 Running govulncheck..."
|
||||||
|
OUTPUT=$(govulncheck ./... 2>&1)
|
||||||
|
EXIT_CODE=$?
|
||||||
|
if [ $EXIT_CODE -eq 0 ]; then
|
||||||
|
echo " ✅ No Go vulnerabilities found"
|
||||||
|
elif echo "$OUTPUT" | grep -q "Vulnerability #"; then
|
||||||
|
echo "$OUTPUT"
|
||||||
|
ISSUES_FOUND=1
|
||||||
|
else
|
||||||
|
echo " ⚠️ govulncheck could not complete: $OUTPUT" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Rust ─────────────────────────────────────────────────────────────────────
|
||||||
|
if [[ "$BASENAME" == Cargo.toml || "$BASENAME" == Cargo.lock ]]; then
|
||||||
|
if command -v cargo-audit &>/dev/null; then
|
||||||
|
echo "🔍 Running cargo audit..."
|
||||||
|
if ! cargo audit 2>/dev/null; then
|
||||||
|
ISSUES_FOUND=1
|
||||||
|
else
|
||||||
|
echo " ✅ No Rust vulnerabilities found"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Ruby ─────────────────────────────────────────────────────────────────────
|
||||||
|
if [[ "$BASENAME" == Gemfile || "$BASENAME" == Gemfile.lock ]]; then
|
||||||
|
if command -v bundler-audit &>/dev/null; then
|
||||||
|
echo "🔍 Running bundler-audit..."
|
||||||
|
bundler-audit check --update 2>/dev/null || ISSUES_FOUND=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Generic fallback: trivy ──────────────────────────────────────────────────
|
||||||
|
if command -v trivy &>/dev/null; then
|
||||||
|
echo "🔍 Running trivy fs scan..."
|
||||||
|
if ! trivy fs --exit-code 1 --severity HIGH,CRITICAL --quiet . 2>/dev/null; then
|
||||||
|
ISSUES_FOUND=1
|
||||||
|
else
|
||||||
|
echo " ✅ trivy found no HIGH/CRITICAL issues"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ISSUES_FOUND" -eq 0 ]; then
|
||||||
|
echo "✅ Dependency check passed — no vulnerabilities detected"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ Vulnerabilities detected. Review and update dependencies before committing."
|
||||||
|
echo " This hook is advisory only and will not block your workflow."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Always exit 0 — this hook warns but does not block
|
||||||
|
exit 0
|
||||||
+5
-3
@@ -16,13 +16,13 @@
|
|||||||
| Feature | Built-in | Examples | Total | Reference |
|
| Feature | Built-in | Examples | Total | Reference |
|
||||||
|---------|----------|----------|-------|-----------|
|
|---------|----------|----------|-------|-----------|
|
||||||
| **Slash Commands** | 55+ | 8 | 63+ | [01-slash-commands/](01-slash-commands/) |
|
| **Slash Commands** | 55+ | 8 | 63+ | [01-slash-commands/](01-slash-commands/) |
|
||||||
| **Subagents** | 6 | 10 | 16 | [04-subagents/](04-subagents/) |
|
| **Subagents** | 6 | 11 | 17 | [04-subagents/](04-subagents/) |
|
||||||
| **Skills** | 5 bundled | 4 | 9 | [03-skills/](03-skills/) |
|
| **Skills** | 5 bundled | 4 | 9 | [03-skills/](03-skills/) |
|
||||||
| **Plugins** | - | 3 | 3 | [07-plugins/](07-plugins/) |
|
| **Plugins** | - | 3 | 3 | [07-plugins/](07-plugins/) |
|
||||||
| **MCP Servers** | 1 | 8 | 9 | [05-mcp/](05-mcp/) |
|
| **MCP Servers** | 1 | 8 | 9 | [05-mcp/](05-mcp/) |
|
||||||
| **Hooks** | 25 events | 7 | 7 | [06-hooks/](06-hooks/) |
|
| **Hooks** | 25 events | 8 | 8 | [06-hooks/](06-hooks/) |
|
||||||
| **Memory** | 7 types | 3 | 3 | [02-memory/](02-memory/) |
|
| **Memory** | 7 types | 3 | 3 | [02-memory/](02-memory/) |
|
||||||
| **Total** | **99** | **43** | **117** | |
|
| **Total** | **99** | **45** | **119** | |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -171,6 +171,7 @@ Specialized AI assistants with isolated contexts for specific tasks.
|
|||||||
| `implementation-agent` | Full feature implementation | Feature development | Project | `cp 04-subagents/implementation-agent.md .claude/agents/` |
|
| `implementation-agent` | Full feature implementation | Feature development | Project | `cp 04-subagents/implementation-agent.md .claude/agents/` |
|
||||||
| `debugger` | Root cause analysis | Bug investigation | User | `cp 04-subagents/debugger.md .claude/agents/` |
|
| `debugger` | Root cause analysis | Bug investigation | User | `cp 04-subagents/debugger.md .claude/agents/` |
|
||||||
| `data-scientist` | SQL queries, data analysis | Data tasks | User | `cp 04-subagents/data-scientist.md .claude/agents/` |
|
| `data-scientist` | SQL queries, data analysis | Data tasks | User | `cp 04-subagents/data-scientist.md .claude/agents/` |
|
||||||
|
| `performance-optimizer` | Profiling & performance tuning | Bottleneck investigation | Project | `cp 04-subagents/performance-optimizer.md .claude/agents/` |
|
||||||
|
|
||||||
> **Scope**: `User` = personal (`~/.claude/agents/`), `Project` = team-shared (`.claude/agents/`)
|
> **Scope**: `User` = personal (`~/.claude/agents/`), `Project` = team-shared (`.claude/agents/`)
|
||||||
|
|
||||||
@@ -367,6 +368,7 @@ Event-driven automation that executes shell commands on Claude Code events.
|
|||||||
| `context-tracker.py` | Token usage tracking | Stop | User | `cp 06-hooks/context-tracker.py ~/.claude/hooks/` |
|
| `context-tracker.py` | Token usage tracking | Stop | User | `cp 06-hooks/context-tracker.py ~/.claude/hooks/` |
|
||||||
| `pre-commit.sh` | Pre-commit validation | PreToolUse:Bash | Project | `cp 06-hooks/pre-commit.sh .claude/hooks/` |
|
| `pre-commit.sh` | Pre-commit validation | PreToolUse:Bash | Project | `cp 06-hooks/pre-commit.sh .claude/hooks/` |
|
||||||
| `log-bash.sh` | Command logging | PostToolUse:Bash | User | `cp 06-hooks/log-bash.sh ~/.claude/hooks/` |
|
| `log-bash.sh` | Command logging | PostToolUse:Bash | User | `cp 06-hooks/log-bash.sh ~/.claude/hooks/` |
|
||||||
|
| `dependency-check.sh` | Vulnerability scan on manifest changes | PostToolUse:Write | Project | `cp 06-hooks/dependency-check.sh .claude/hooks/` |
|
||||||
|
|
||||||
> **Scope**: `Project` = team (`.claude/settings.json`), `User` = personal (`~/.claude/settings.json`)
|
> **Scope**: `Project` = team (`.claude/settings.json`), `User` = personal (`~/.claude/settings.json`)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user