From ios-craft
Keep dependencies and APIs current. Use when checking for outdated SPM packages, deprecated APIs, or planning iOS version migration. Scans for deprecation warnings and recommends updates.
npx claudepluginhub ildunari/kosta-plugins --plugin ios-craftThis skill uses the workspace's default tool permissions.
Guide the user through auditing their project for outdated dependencies, deprecated APIs, and opportunities to adopt new iOS features. The goal is keeping the app modern, secure, and maintainable.
Provides Ktor server patterns for routing DSL, plugins (auth, CORS, serialization), Koin DI, WebSockets, services, and testApplication testing.
Conducts multi-source web research with firecrawl and exa MCPs: searches, scrapes pages, synthesizes cited reports. For deep dives, competitive analysis, tech evaluations, or due diligence.
Provides demand forecasting, safety stock optimization, replenishment planning, and promotional lift estimation for multi-location retailers managing 300-800 SKUs.
Guide the user through auditing their project for outdated dependencies, deprecated APIs, and opportunities to adopt new iOS features. The goal is keeping the app modern, secure, and maintainable.
Check all Swift Package Manager dependencies for updates:
# List current resolved versions
cat YourProject.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved \
| python3 -c "
import json, sys
data = json.load(sys.stdin)
pins = data.get('pins', data.get('object', {}).get('pins', []))
for pin in sorted(pins, key=lambda p: p.get('identity', p.get('package', ''))):
name = pin.get('identity', pin.get('package', 'unknown'))
version = pin.get('state', {}).get('version', pin.get('state', {}).get('revision', 'unknown')[:8])
print(f' {name}: {version}')
"
For each dependency, check:
Updating SPM packages in Xcode:
Manual version bump:
Edit your Package.swift or Xcode project's package dependency version rules.
Find deprecated API usage in your codebase:
# Build with all warnings visible
xcodebuild build \
-scheme "YourApp" \
-destination "platform=iOS Simulator,name=iPhone 16 Pro" \
2>&1 | grep -i "deprecated"
# More targeted: find specific deprecation patterns in source
grep -rn "@available.*deprecated\|\.deprecated\|API_DEPRECATED\|is deprecated" \
--include="*.swift" .
Common deprecation patterns to check:
// Search for these in your codebase
UIApplication.shared.keyWindow // Deprecated iOS 13 — use scene-based window
UIApplication.shared.statusBarStyle // Deprecated iOS 9 — use UIViewController
UIColor.groupTableViewBackground // Deprecated iOS 13 — use .systemGroupedBackground
UITableViewCell.textLabel // Deprecated iOS 14 — use content configurations
UIAlertView / UIActionSheet // Deprecated iOS 9 — use UIAlertController
URLSession.shared.dataTask(with:completionHandler:) // Not deprecated, but async/await is preferred
See references/common-deprecation-migrations.md for 30 common migrations with before/after code.
Check your project's deployment target and SDK version:
# Current deployment target
xcodebuild -showBuildSettings -scheme "YourApp" 2>/dev/null | grep IPHONEOS_DEPLOYMENT_TARGET
# SDK version
xcodebuild -showBuildSettings -scheme "YourApp" 2>/dev/null | grep SDK_VERSION
Deployment target recommendations (as of 2026):
| Target | Drops Support For | Gains Access To |
|---|---|---|
| iOS 16 | iPhone 7, iPod Touch | Charts, NavigationStack, PhotosPicker |
| iOS 17 | iPhone 8, iPhone X | Observable, SwiftData, TipKit, StoreKit 2 |
| iOS 18 | iPhone XR, iPhone XS | ControlWidget, custom Lock Screen controls |
Rule of thumb: Support the last 2-3 major iOS versions. Check Apple's usage stats (Settings → Privacy → Analytics on your published app, or App Store Connect analytics).
For each external API your app calls, verify:
Automated check script:
// Add to your test target
func testAPIEndpointsReachable() async throws {
let endpoints = [
"https://api.yourservice.com/v2/health",
"https://api.yourservice.com/v2/config"
]
for endpoint in endpoints {
let url = URL(string: endpoint)!
let (_, response) = try await URLSession.shared.data(from: url)
let httpResponse = response as! HTTPURLResponse
XCTAssertEqual(httpResponse.statusCode, 200, "Endpoint unreachable: \(endpoint)")
}
}
See references/ios-version-feature-matrix.md for a complete table of features by iOS version.
Questions to ask for each new iOS version:
When raising the deployment target:
Step 1: Audit availability checks
# Find all #available and @available checks
grep -rn "#available\|@available" --include="*.swift" . | grep -v "Pods\|.build"
Step 2: Remove unnecessary availability checks
If your new deployment target is iOS 17, any if #available(iOS 17, *) check can be simplified — the else branch is dead code.
// BEFORE (when supporting iOS 16+)
if #available(iOS 17, *) {
ContentView()
.onChange(of: value) { oldValue, newValue in
// iOS 17+ two-parameter closure
}
} else {
ContentView()
.onChange(of: value) { newValue in
// iOS 16 single-parameter closure
}
}
// AFTER (when minimum is iOS 17)
ContentView()
.onChange(of: value) { oldValue, newValue in
// Just use the iOS 17+ API directly
}
Step 3: Adopt modern replacements Replace deprecated patterns with their modern equivalents. See the deprecation migrations reference.
Step 4: Test on the new minimum
Save as check_freshness.sh and run periodically:
#!/bin/bash
# iOS Project Freshness Checker
# Run from your project root
echo "=== iOS Project Freshness Report ==="
echo ""
# 1. Check Xcode version
echo "## Xcode Version"
xcodebuild -version
echo ""
# 2. Check deployment target
echo "## Deployment Target"
SCHEME="${1:-YourApp}"
TARGET=$(xcodebuild -showBuildSettings -scheme "$SCHEME" 2>/dev/null | grep IPHONEOS_DEPLOYMENT_TARGET | awk '{print $3}')
echo " Minimum iOS: $TARGET"
echo ""
# 3. Count deprecation warnings
echo "## Deprecation Warnings"
WARNINGS=$(xcodebuild build -scheme "$SCHEME" \
-destination "platform=iOS Simulator,name=iPhone 16 Pro" \
2>&1 | grep -c "deprecated")
echo " Found: $WARNINGS deprecation warnings"
echo ""
# 4. Check SPM dependencies
echo "## SPM Dependencies"
RESOLVED=$(find . -name "Package.resolved" -not -path "*/DerivedData/*" | head -1)
if [ -n "$RESOLVED" ]; then
python3 -c "
import json
with open('$RESOLVED') as f:
data = json.load(f)
pins = data.get('pins', data.get('object', {}).get('pins', []))
print(f' Total packages: {len(pins)}')
for pin in sorted(pins, key=lambda p: p.get('identity', p.get('package', ''))):
name = pin.get('identity', pin.get('package', 'unknown'))
version = pin.get('state', {}).get('version', pin.get('state', {}).get('revision', 'unknown')[:8])
print(f' {name}: {version}')
"
else
echo " No Package.resolved found"
fi
echo ""
# 5. Check for availability annotations
echo "## Availability Checks"
CHECKS=$(grep -rc "#available\|@available" --include="*.swift" . 2>/dev/null | \
awk -F: '{sum+=$2} END {print sum}')
echo " #available / @available usages: ${CHECKS:-0}"
echo ""
# 6. Check for privacy manifest
echo "## Privacy Manifest"
if find . -name "PrivacyInfo.xcprivacy" -not -path "*/DerivedData/*" | head -1 | grep -q .; then
echo " PrivacyInfo.xcprivacy: Found"
else
echo " PrivacyInfo.xcprivacy: MISSING (required since 2024)"
fi
echo ""
echo "=== End Report ==="