Skip to content

Performance Optimizer

A two-phase workflow — Analyze then Optimize — that finds performance problems and code-quality issues, then applies behavior-preserving fixes directly to the codebase.

Phase 1 — Analyze.

  1. Map the project: language, framework, build tool, and package manager.
  2. Scan for these categories:
    • Duplication — repeated logic or blocks across files.
    • Bundle size — heavy or unused dependencies, missing tree-shaking or code-splitting, large barrel imports.
    • Images & assets — uncompressed images, wrong format, oversized dimensions, missing lazy-loading.
    • Runtime performance — N+1 queries, unnecessary re-renders, blocking sync I/O, unindexed queries, O(n²) loops on large data.
    • Dead code — unused exports, unreachable branches, commented-out blocks.
    • Build config — missing minification or compression, dev-only code shipped to production.
  3. Produce a concise report with file:line, what’s wrong, estimated impact, and a proposed fix.
  4. Ask which categories to act on if the list is long.

Phase 2 — Optimize. Apply fixes one category at a time, keeping changes reviewable. After each category, run the existing tests/build to confirm nothing broke, and report file-by-file what changed and why.

Analyzing a React app:

  • Bundle size: a heavy date library imported for a single format call — replace it with a native Intl.DateTimeFormat call, cutting ~40 KB.
  • Runtime: a dashboard re-renders on every keystroke because of inline object props — memoize the child or lift the object.
  • Images: hero images are 4000×3000 PNGs — resize to display dimensions and convert to WebP.
  • Dead code: a module exports three functions with no references — remove after confirming with a repo-wide search.
  1. Analyze before you touch — findings are always shown first unless the user says “just fix it”.
  2. Behavior-preserving fixes — never “optimize” into different output.
  3. One category at a time — keeps diffs small and reviewable.
  4. No unnecessary dependencies — use native or existing solutions when they work.
  • Reducing bundle size or improving load speed
  • Cleaning up duplicated or dead code
  • Optimizing images and assets for the web
  • Fixing slow queries, re-renders, or blocking I/O
  • Run the test suite after each category of changes.
  • If there is no test suite, proceed conservatively with smaller diffs.
  • On very large repos, sample representative files first rather than blindly scanning everything.
  • Verify a symbol has no other references before deleting dead code.

Save the following as SKILL.md to use it as an OpenCode skill:

---
name: performance-optimizer
description: Analyze codebase for performance issues and code quality problems, then apply optimizations directly to code. Use when user asks to analyze performance, audit code quality, find bottlenecks, reduce bundle size, optimize images/assets, remove duplicated code, or "make the code faster/cleaner/lighter" — even if not named explicitly. Trigger on "check the performance of this project", "optimize my codebase", "find and fix inefficiencies", "reduce bundle size", "clean up duplicated code".
---
# Codebase Performance Optimizer
Two phases: **Analyze** then **Optimize**. Always show findings before touching code, unless user says "just fix it".
## Phase 1 — Analyze
1. Map project: language(s), framework, build tool, package manager. Use `view` on root dir, then relevant configs (package.json, webpack/vite config, tsconfig, etc).
2. Scan for these issue categories (use `bash_tool` with grep/find, or language-specific tools when available):
- **Duplication**: repeated logic/blocks across files (near-identical functions, copy-pasted components).
- **Bundle size**: heavy/unused deps, missing tree-shaking, no code-splitting, large barrel imports.
- **Images/assets**: uncompressed images, wrong format (e.g. PNG where WebP/AVIF fits), oversized dimensions, missing lazy-loading.
- **Runtime perf**: N+1 queries, unnecessary re-renders (React: missing memo/useMemo/useCallback, inline object/function props), blocking sync I/O, unindexed DB queries, O(n²) loops on large data.
- **Dead code**: unused exports, unreachable branches, commented-out blocks.
- **Build config**: missing minification, no compression (gzip/brotli), dev-only code shipped to prod.
3. Produce findings report (in chat, concise): per issue — file:line, what's wrong, estimated impact (high/medium/low), proposed fix.
4. Ask user which categories to act on if list long (use `ask_user_input_v0`), unless already said "fix everything".
## Phase 2 — Optimize
Apply fixes incrementally, one category at a time, so changes stay reviewable:
- **Dedup**: extract shared logic into function/module/component; update call sites.
- **Bundle**: replace heavy deps with lighter alternatives (only if drop-in compatible), add/adjust code-splitting or dynamic imports, fix barrel-import issues.
- **Images**: recompress/convert via `bash_tool` (e.g. `cwebp`, `sharp`, `imagemin` if available — check what's installed first), resize to actual display dimensions, add lazy-loading attributes.
- **Runtime**: apply memoization, batch queries, replace O(n²) with efficient structures/algorithms.
- **Dead code**: remove after confirming no external references (grep whole repo first).
After each category: run existing tests/build if project has them (`npm test`, `npm run build`, etc.) to confirm nothing broke. Report what changed and why, file by file, in short summary — not just "done".
## Rules
- Never guess at "optimized" behavior that changes program output — perf fixes must be behavior-preserving.
- Don't install new deps for a fix if native/existing solution works.
- No test suite → flag it and proceed more conservatively (smaller diffs, manual reasoning about correctness).
- Very large repos → sample representative files/modules first, not blind full scan; ask user for subfolder if scope unclear.