Performance
Parent skill for performance analysis and optimisation. Routes to sub-skills based on the user's need and the detected tech stack, delegates runnable artifacts to scripts/ templates, and references the improvement catalogue for synthesis — never inlines it.
Companion Files
Sub-skills (measurement)
- profiling.md — CPU/memory profiling, flame graphs, hotspot identification
- load-testing.md — Load/stress/spike/soak tools, SLA determination, capacity validation patterns
- database.md — Query optimisation, N+1 detection, index design, connection pool monitoring
- frontend-performance.md — Core Web Vitals, INP, animation smoothness, Lighthouse CI, Playwright CWV
- capacity-planning.md — Theoretical headroom math, contention scenarios, consumer of load-test output
References (lookups, not routes)
references/perf-test-contract-template.md— SLO + acceptance-criteria contract; source of truth for generating scriptsreferences/test-reality-model.md— Environment isolation, warmup, mocks, CI tiers; mandatory pre-flightreferences/workload-taxonomy.md— Workload-shape table (HTTP, browser, queues, streaming, batch, cache)references/improvement-catalog.md— Improvement patterns with applicability, impact, owner skills
Scripts (runnable templates)
scripts/k6-template.js— Parameterised k6 load testscripts/locust-template.py— Parameterised Locust load testscripts/playwright-perf-template.ts— Programmatic CWV via Playwrightscripts/lighthouse-ci-template.js— Lighthouse CI configscripts/capacity-model.py— Consumes load-test JSON, emits capacity-model.mdscripts/detect-stack.sh— Thin wrapper for non-context-aware callers; delegates toproject-documentation/context-detection
Stack Detection (Step 1)
Before routing, determine the stack and context. Reuse the existing detector — do not build a second one.
Read ~/.claude/skills/project-documentation/context-detection.md
Apply its Detection Flow (Steps 1-6) against the current project:
- Step 1: PROJECT.md present?
- Step 2: package manifest present?
- Step 3: component membership
- Step 4: consumer detection
- Step 5: dependency depth
- Step 6: classify → context_type (standalone | component | library | service | monorepo-package)
Extract the detected tech stack from the package manifest and PROJECT.md:
- python-flask | python-django | python-fastapi
- nodejs | nextjs | nestjs
- java-spring
- php-woocommerce | php-wordpress
- go | rust | other
Report the detection to the user and offer override:
Detected stack: python-flask (pyproject.toml + Flask in dependencies).
Detected context_type: service (has public API, has consumers).
Override? [y/N]
After confirmation, surface the relevant domain skill for the synthesis phase:
| Detected stack | Primary domain skill |
|---|---|
| python-flask / python-fastapi | python-flask-developer |
| python-django | python-flask-developer + python-data-engineer |
| nodejs (Express / Fastify) | (no dedicated skill — use profiling.md + database.md) |
| nextjs / SSR React | modern-frontend |
| java-spring | java-backend |
| php-woocommerce | woocommerce-developer |
| php-wordpress | wordpress-developer |
| go | (no dedicated skill — use profiling.md + database.md) |
For non-context-aware callers (CI scripts, external tools), invoke scripts/detect-stack.sh which simply collects signals and points the caller back to context-detection.md. The script parses nothing — it is a wrapper, not a detector.
Routing Table
| User Need | Route To | Notes |
|---|---|---|
| Profile / bottleneck / slow code | profiling.md |
unchanged |
| Load test / stress / SLA validation | load-testing.md |
also handles capacity execution |
| Slow queries / DB / N+1 / indexes | database.md |
unchanged |
| Capacity / scaling / max users / headroom | capacity-planning.md |
theory + math; consumes load-test output |
| Page speed / CWV / Lighthouse / jank / perceived perf | frontend-performance.md |
new sub-skill |
| Performance contract / SLOs / acceptance criteria | references/perf-test-contract-template.md |
template, not a sub-skill |
| Workload doesn't look like plain HTTP (queue / stream / batch / cache) | references/workload-taxonomy.md then linked sub-skill |
lookup, not a route |
| "Make it faster" / improvement ideas | sub-skill's "Synthesis & Improvements" section → references/improvement-catalog.md |
synthesis layer, not a route |
When a user asks for "performance" broadly, gather context first:
- Run stack detection (above)
- Classify the workload via
references/workload-taxonomy.md - Choose the measurement sub-skill for the primary workload
- Write a perf-test contract from
references/perf-test-contract-template.mdif the project has none - Run the measurement
- Synthesise improvements from the matching
references/improvement-catalog.mdcategories
Synthesis-Section Pattern
Each measurement sub-skill (profiling, load-testing, database, frontend-performance, capacity-planning) ends with a short "Synthesis & Improvements" stub that:
- Names the finding type (slow_query, lcp_budget_breach, headroom_exhausted, etc.)
- Points at specific
references/improvement-catalog.mdcategories - Delegates stack-specific implementation to the detected domain skill
These stubs are ~10 lines. They do NOT repeat the catalogue inline. This keeps the catalogue as the single source of truth and avoids drift across five sub-skills.
Gap Detection
Before routing to a child skill:
- Verify target exists (check
~/.claude/skills/performance/<name>.md) - If missing: follow gap-detection protocol at
~/.claude/skills/research-for-skills/gap-detection.md - If exists: invoke with context (detected stack, context_type, workload category, contract path if any)
Performance Findings Output Format
All performance findings — from sub-skills or fallback guidance — use this structured format. Consumable by team-manager, bob, qa-reviewer, and development-lifecycle.
## Performance Finding: [component]
### Measurement
| metric | measured | budget | status |
|---|---|---|---|
| [metric] | [value] | [target or N/A] | PASS/FAIL/BASELINE |
### Root Cause (if identified)
- [specific bottleneck]
### Recommended Fix
- [actionable fix — owned by detected-stack domain skill]
### Action Required
- [ ] Fix root cause
- [ ] Re-measure after fix
- [ ] Update performance budget if baseline changed
Self-Learning
Log all significant findings to ~/.claude/skills/_meta/perf-findings.jsonl:
{"date":"YYYY-MM-DD","project_type":"<stack>","component":"<name>","finding_type":"slow_query|hotspot|high_latency|memory_leak|regression|lcp_budget_breach|cls_budget_breach|inp_budget_breach|ttfb_regression|headroom_exhausted|workload-gap","metric":"<name>","measured":"<value>","target":"<value or N/A>","root_cause":"<description>","fix_applied":true|false,"improvement":"<before->after>"}
Log when:
- A performance issue is identified and measured
- A fix is applied and re-measured
- A baseline is established for the first time
- A workload type has no matching taxonomy row (type
workload-gap)
Do NOT log:
- Speculative findings without measurements
- Duplicate entries for the same issue in the same session
Standalone-First Design
This skill works without forge, bob, or PA:
- Directly usable by any agent or in standalone conversation
- No dependency on MCP tools or orchestration infrastructure
- Sub-skills and references are self-contained
Optional PA Integration
If PA MCP tools are available (pa_log_action, pa_update_task):
- Log performance findings via
pa_log_action() - Update task status when performance checks complete
If PA is not available: skip silently. PA integration is optional.
Anti-patterns
| Don't | Why |
|---|---|
| Optimise without measuring first | You might optimise the wrong thing. Measure, then fix. |
| Report "it's fast" without numbers | Numbers are evidence. Feelings are not. |
| Skip baseline measurement | Without a baseline, you cannot prove improvement. |
| Test with unrealistic data volumes | Production data is 10-100× larger than test data. Scale matters. |
| Focus on averages instead of percentiles | p95/p99 reveal the real user experience. Averages hide outliers. |
| Block tasks to run performance tests | Performance is a dimension of TEST phase, not a separate gate. |
| Assume all changes need perf testing | Config, docs, CSS-only, test-only changes do not need it. |
| Run perf tests against production | The scripts refuse; the harness must too. See test-reality-model.md. |
| Compare results across different env tiers | Baselines are per-tier; cross-tier comparisons are invalid. |
| Accept "p95 = X" without warmup | First requests hit cold caches; warmup is mandatory per stack. |
| Generate runnable scripts before the contract exists | The contract drives the scripts; generating the other way round guarantees drift. |
| Embed runnable code in these .md files | Runnable artifacts live in scripts/ — this file points at them. |
| Build a second stack detector | Reuse project-documentation/context-detection. detect-stack.sh is a wrapper only. |
| Duplicate the improvement catalogue in sub-skill synthesis sections | Synthesis is a 10-line lookup stub; the catalogue is the single source of truth. |