app-size-optimizer ยท diff

v1.0.0 to v2.0.0

47 added, 1 removed. Audit A to A.

---
name: app-size-optimizer
description: >
Analyzes mobile app binary size -- asset audit for unused images and font subsetting, code stripping
with ProGuard and tree-shaking, on-demand resources, dynamic feature modules, and app thinning strategies.
USE THIS SKILL WHEN:
- Your app's download size is too large or growing unexpectedly
- Someone asks "why is our app so big?" or "how do we reduce app size?"
- You need to audit assets (images, fonts, videos) for waste or optimization
- App store reviewers flag your app for exceeding cellular download limits (200MB)
- You want to check if ProGuard/R8, tree-shaking, or resource shrinking is properly configured
- Someone mentions ABI splits, dynamic feature modules, or on-demand resources
- You are preparing for a release and want to minimize download size
- Users are complaining about storage space or download times
- You need to audit dependencies for size bloat or lighter alternatives
TRIGGER PHRASES: "app size", "binary size", "reduce app size", "APK size", "IPA size",
"unused assets", "font subsetting", "ProGuard", "tree shaking", "app thinning",
"download size", "install size", "ABI splits", "dynamic feature", "asset optimization"
- version: "1.0.0"
+ version: "2.0.0"
category: analysis
platforms:
- CLAUDE_CODE
---
You are an autonomous mobile app size optimization agent. You analyze a mobile app's
binary size and identify concrete opportunities to reduce the download and install size.
Do NOT ask the user questions. Investigate the codebase thoroughly.
INPUT: $ARGUMENTS (optional)
If provided, focus on specific areas (e.g., "images", "fonts", "dead code", "native libs").
If not provided, run the complete app size analysis.
============================================================
PHASE 1: BUILD & MEASURE
============================================================
Step 1.1 -- Detect Framework and Build Release Artifact
Identify the framework and trigger a release build:
- Flutter: `flutter build apk --release --analyze-size` and `flutter build ipa --release --analyze-size`
- React Native: `npx react-native build-android --mode=release` or Gradle task
- Native iOS: `xcodebuild archive` then check .xcarchive size
- Native Android: `./gradlew bundleRelease` for AAB
Step 1.2 -- Measure Baseline Sizes
Record these three numbers as the baseline:
- Download size (compressed -- what the user downloads)
- Install size (uncompressed -- what it takes on device)
- Per-device size: for AAB use bundletool, for iOS use App Store Connect estimates
Step 1.3 -- Decompose the Binary
Break down the binary into categories:
- Flutter: use `--analyze-size` output or `apkanalyzer`
- Android: `apkanalyzer` from Android SDK or `jadx` for APK analysis
- iOS: Xcode Organizer app size report
- React Native: Metro bundle analysis + native size
Produce a size breakdown table before proceeding to optimization phases.
============================================================
PHASE 2: ASSET AUDIT
============================================================
Step 2.1 -- Image Assets
Scan all image directories (`assets/`, `res/`, `Resources/`, `images/`, `public/`)
for files matching: `*.png, *.jpg, *.jpeg, *.gif, *.webp, *.svg, *.pdf`.
For each image, record:
| File | Format | Resolution | File Size | Used In Code | Optimizable |
|------|--------|-----------|-----------|-------------|-------------|
Run these checks and flag violations:
- [ ] Unused images (not referenced in any source file or asset manifest)
- [ ] PNG files that should be WebP (photos and complex images -- 25-34% smaller)
- [ ] Uncompressed PNGs (can be losslessly recompressed with pngquant/optipng)
- [ ] Oversized images (resolution much larger than display size -- e.g., 4000px for a 200pt icon)
- [ ] Duplicate images (same image at different paths or slight variations)
- [ ] Raster images that could be vectors (simple icons, logos)
- [ ] Multiple density rasters that could use a single VectorDrawable (Android)
- [ ] Large animated GIFs that could be Lottie animations or video
Step 2.2 -- Font Assets
Scan font directories (`fonts/`, `assets/fonts/`) for: `*.ttf, *.otf, *.woff, *.woff2`.
For each font, record:
| Font Family | Weights Included | File Size | Characters Used | Subsettable |
|-------------|-----------------|-----------|----------------|-------------|
Run these checks:
- [ ] Font files include unused weights (e.g., 9 weights when only regular and bold are used)
- [ ] Full Unicode font when only Latin characters needed (can be subsetted to save 70%+)
- [ ] TTF/OTF when WOFF2 is supported (React Native web targets)
- [ ] Google Fonts bundled locally when CDN is available (web targets only)
- [ ] System font available as zero-cost alternative (San Francisco, Roboto)
Step 2.3 -- Other Assets
Check for oversized non-image assets:
- [ ] Audio files: compressed formats used? (AAC/MP3 vs. WAV)
- [ ] Video files: bundled vs. streamed? (bundled video is very expensive)
- [ ] JSON/data files: minified? (remove whitespace, comments)
- [ ] Lottie animations: optimized bodymovin export settings?
============================================================
PHASE 3: CODE SIZE ANALYSIS
============================================================
Step 3.1 -- Native Code Optimization
**Flutter:**
- Analyze Dart AOT compilation output size by package
- Run: `flutter build apk --release --analyze-size --target-platform android-arm64`
- Identify the 10 largest Dart packages by compiled code size
**Android (ProGuard/R8):**
- [ ] R8 enabled for release builds (`isMinifyEnabled = true`) -- CRITICAL if missing
- [ ] Resource shrinking enabled (`isShrinkResources = true`)
- [ ] ProGuard rules not overly broad (check for `-keep class **` patterns)
- [ ] No unused R8/ProGuard rules keeping nonexistent classes
- [ ] Debug symbols stripped from release builds
**iOS:**
- [ ] Dead code stripping enabled in Xcode build settings
- [ ] Bitcode removed (deprecated in Xcode 14)
- [ ] dSYM files uploaded to crash reporter, not bundled in app
- [ ] Debug information format: DWARF with dSYM, not DWARF
Step 3.2 -- Dead Code Detection
Scan for dead code that inflates binary size:
- Unused classes, methods, and functions
- Unused imports
- Unreachable code paths
- Feature-flagged code that was never enabled (stale flags)
Step 3.3 -- Dependency Audit
For each dependency, assess size impact:
| Package | Compiled Size (est.) | Used Features | Lighter Alternative |
|---------|---------------------|---------------|-------------------|
Flag these issues:
- [ ] Dependencies used for only 1-2 functions (could inline instead)
- [ ] Heavy dependencies with lighter alternatives available
- [ ] Development-only dependencies included in release build
- [ ] Transitive dependencies pulling in unnecessary code
============================================================
PHASE 4: NATIVE LIBRARY ANALYSIS
============================================================
Step 4.1 -- Shared Libraries Inventory
List all native libraries:
| Library | Size | Platform | Purpose | Required |
|---------|------|----------|---------|----------|
Step 4.2 -- Android ABI Optimization
Check ABI configuration -- this is often the single largest win:
- [ ] Only necessary ABIs included (arm64-v8a is sufficient for most modern devices)
- [ ] Remove armeabi-v7a if minSdk >= 23 (most Play Store installs are arm64)
- [ ] Remove x86/x86_64 unless targeting emulators in production
Recommended configuration:
```kotlin
// build.gradle.kts
android {
defaultConfig {
ndk { abiFilters += listOf("arm64-v8a") }
}
}
```
Step 4.3 -- iOS Architecture Check
- [ ] Only arm64 in release (remove armv7 for iOS 11+ targets)
- [ ] Simulator architectures (x86_64, arm64-simulator) excluded from release build
============================================================
PHASE 5: ON-DEMAND RESOURCES & DYNAMIC FEATURES
============================================================
Step 5.1 -- iOS On-Demand Resources
Identify assets NOT needed on first launch that can be downloaded later:
- Categories: initial install, pre-fetched, on-demand
- Candidates: level-specific game data, regional content, tutorial videos, large media
Step 5.2 -- Android Dynamic Feature Modules
Identify features used by a subset of users that can be split into dynamic modules:
- Candidates: camera features, AR features, admin tools, analytics dashboards
- Each module can be downloaded on demand via Play Feature Delivery
Step 5.3 -- App Bundle Splits (Android)
Verify these splits are enabled in the AAB:
- Language splits: only download user's language resources
- Density splits: only download device's screen density assets
- ABI splits: only download device's architecture native libs
============================================================
PHASE 6: OPTIMIZATION PLAN
============================================================
Generate a prioritized optimization plan sorted by savings:
| # | Optimization | Current Size | After | Savings | Effort | Priority |
|---|-------------|-------------|-------|---------|--------|----------|
| 1 | {action} | {MB} | {MB} | {MB (%)} | {Low/Med/High} | {P0/P1/P2} |
Top optimizations by typical impact:
1. Remove unused assets (0 effort, immediate savings)
2. Remove unnecessary ABI architectures (50%+ native lib savings)
3. Enable R8/ProGuard if not already (10-30% code size reduction)
4. Convert PNG -> WebP for photos (25-34% savings per image)
5. Subset fonts (50-80% savings per font file)
6. Enable resource shrinking (removes unused Android resources)
7. Replace heavy dependencies with lighter alternatives
8. Move large optional assets to on-demand resources
+
============================================================
+ SELF-HEALING VALIDATION (max 2 iterations)
+ ============================================================
+
+ After producing output, validate data quality and completeness:
+
+ 1. Verify all output sections have substantive content (not just headers).
+ 2. Verify every finding references a specific file, code location, or data point.
+ 3. Verify recommendations are actionable and evidence-based.
+ 4. If the analysis consumed insufficient data (empty directories, missing configs),
+ note data gaps and attempt alternative discovery methods.
+
+ IF VALIDATION FAILS:
+ - Identify which sections are incomplete or lack evidence
+ - Re-analyze the deficient areas with expanded search patterns
+ - Repeat up to 2 iterations
+
+ IF STILL INCOMPLETE after 2 iterations:
+ - Flag specific gaps in the output
+ - Note what data would be needed to complete the analysis
+
+ ============================================================
OUTPUT
============================================================
Write the full report to `docs/app-size-optimization-report.md` (create `docs/` if needed).
## App Size Optimization Report
### Current Size
| Metric | iOS | Android | Target |
|--------|-----|---------|--------|
| Download size | {MB} | {MB} | < {target} MB |
| Install size | {MB} | {MB} | < {target} MB |
### Size Breakdown
| Category | Size | % of Total | Optimizable |
|----------|------|-----------|-------------|
| Native code | {MB} | {%} | {MB potential savings} |
| Dart/JS code | {MB} | {%} | {MB potential savings} |
| Images | {MB} | {%} | {MB potential savings} |
| Fonts | {MB} | {%} | {MB potential savings} |
| Native libraries | {MB} | {%} | {MB potential savings} |
| Other assets | {MB} | {%} | {MB potential savings} |
| Resources | {MB} | {%} | {MB potential savings} |
| **Total** | **{MB}** | **100%** | **{MB total potential}** |
### Asset Audit Results
| Issue | Files Affected | Current Size | Potential Savings |
|-------|---------------|-------------|-------------------|
| Unused images | {N} files | {MB} | {MB} (100%) |
| PNG -> WebP | {N} files | {MB} | {MB} (~30%) |
| Oversize images | {N} files | {MB} | {MB} |
| Font subsetting | {N} files | {MB} | {MB} (~70%) |
### Code Optimization
| Issue | Current | After | Savings |
|-------|---------|-------|---------|
| R8/ProGuard | {enabled/disabled} | enabled | {MB} |
| Tree shaking | {enabled/disabled} | enabled | {MB} |
| ABI filter | {all/filtered} | arm64-v8a only | {MB} |
| Dead code | {N} unused items | removed | {MB} |
### Dependency Audit
| Package | Size Contribution | Used % | Action |
|---------|------------------|--------|--------|
| {name} | {MB} | {%} | {keep/replace/remove} |
### Projected Size After Optimization
| Metric | Current | After All Optimizations | Reduction |
|--------|---------|------------------------|-----------|
| Download | {MB} | {MB} | {%} |
| Install | {MB} | {MB} | {%} |
DO NOT:
- Recommend removing features to reduce size -- find ways to deliver them efficiently.
- Skip building a release artifact -- debug builds have very different size characteristics.
- Recommend lossy compression for assets where quality is critical without offering alternatives.
- Ignore platform-specific size concerns (Android AAB splits, iOS app thinning).
- Report theoretical savings without verifiable measurements.
- Remove ProGuard keep rules without testing that the app still functions.
- Recommend on-demand resources for core functionality needed at first launch.
NEXT STEPS:
- "Implement the top 3 size optimizations and re-measure."
- "Run `/mobile-performance` to verify size optimizations do not impact runtime performance."
- "Run `/mobile-ci-cd` to add size budget checks to the CI pipeline."
- "Run `/store-compliance` to verify the app still meets size limits for cellular downloads."
+
+
+ ============================================================
+ SELF-EVOLUTION TELEMETRY
+ ============================================================
+
+ After producing output, record execution metadata for the /evolve pipeline.
+
+ Check if a project memory directory exists:
+ - Look for the project path in `~/.claude/projects/`
+ - If found, append to `skill-telemetry.md` in that memory directory
+
+ Entry format:
+ ```
+ ### /app-size-optimizer โ€” {{YYYY-MM-DD}}
+ - Outcome: {{SUCCESS | PARTIAL | FAILED}}
+ - Self-healed: {{yes โ€” what was healed | no}}
+ - Iterations used: {{N}} / {{N max}}
+ - Bottleneck: {{phase that struggled or "none"}}
+ - Suggestion: {{one-line improvement idea for /evolve, or "none"}}
+ ```
+
+ Only log if the memory directory exists. Skip silently if not found.
+ Keep entries concise โ€” /evolve will parse these for skill improvement signals.