Skip to content

Instantly share code, notes, and snippets.

@leogdion
Last active July 23, 2025 13:21
Show Gist options
  • Select an option

  • Save leogdion/0bcafebe6b8e1ae0e2ce6044ea68c59e to your computer and use it in GitHub Desktop.

Select an option

Save leogdion/0bcafebe6b8e1ae0e2ce6044ea68c59e to your computer and use it in GitHub Desktop.
Delete Old 26.0 Beta Simulator Runtime
#!/bin/bash
# Script to clean up old 26.0 beta simulator runtimes
# Keeps only the latest build version for each platform
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Check if jq is installed
if ! command -v jq &> /dev/null; then
print_error "jq is required but not installed. Please install jq first:"
echo " brew install jq"
exit 1
fi
# Check if simctl is available
if ! command -v xcrun simctl &> /dev/null; then
print_error "xcrun simctl is not available. Make sure Xcode is installed."
exit 1
fi
print_status "Fetching current simulator runtimes..."
# Get runtime list as JSON
RUNTIMES_JSON=$(xcrun simctl runtime list -j)
# Parse command line arguments
DRY_RUN=false
DEBUG=false
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run|-n)
DRY_RUN=true
print_warning "DRY RUN MODE - No runtimes will be deleted"
shift
;;
--debug|-d)
DEBUG=true
print_status "DEBUG MODE - Will show detailed processing"
shift
;;
*)
print_error "Unknown option: $1"
echo "Usage: $0 [--dry-run|-n] [--debug|-d]"
exit 1
;;
esac
done
# Debug mode - show available runtimes
if [[ "$DEBUG" == true ]]; then
print_status "Available 26.0 runtimes:"
echo "$RUNTIMES_JSON" | jq -r 'to_entries[] | select(.value.version == "26.0" and (.value.state == "Ready" or .value.state == "Unusable")) | "\(.value.platformIdentifier) \(.value.version) \(.value.build) \(.value.state)"'
echo
fi
# Get all 26.0 runtimes as tab-separated data
RUNTIME_DATA=$(echo "$RUNTIMES_JSON" | jq -r 'to_entries[] | select(.value.version == "26.0") | "\(.key)\t\(.value.platformIdentifier // "")\t\(.value.version // "")\t\(.value.build // "")\t\(.value.state // "")\t\(.value.runtimeIdentifier // "")"')
# Check if we have any data
if [[ -z "$RUNTIME_DATA" ]]; then
print_error "No 26.0 runtimes found in the system"
exit 1
fi
print_status "Analyzing 26.0 runtimes for cleanup..."
echo
# Initialize arrays
RUNTIMES_TO_DELETE=()
RUNTIMES_TO_KEEP=()
# Process each platform
for platform in iOS tvOS watchOS xrOS; do
print_status "Checking $platform 26.0 runtimes..."
# Get platform identifier
case $platform in
"iOS") platform_id="com.apple.platform.iphonesimulator" ;;
"tvOS") platform_id="com.apple.platform.appletvsimulator" ;;
"watchOS") platform_id="com.apple.platform.watchsimulator" ;;
"xrOS") platform_id="com.apple.platform.xrsimulator" ;;
esac
# Get all runtimes for this platform
platform_runtimes=$(echo "$RUNTIME_DATA" | grep "$platform_id")
if [[ -z "$platform_runtimes" ]]; then
print_warning "No $platform 26.0 runtimes found"
continue
fi
runtime_count=$(echo "$platform_runtimes" | wc -l | tr -d ' ')
echo " Found $runtime_count $platform runtimes"
# Find the latest ready runtime
latest_build=""
latest_uuid=""
latest_state=""
latest_runtime_id=""
while IFS=$'\t' read -r uuid platform_id_check version build state runtime_id; do
if [[ "$DEBUG" == true ]]; then
echo " Processing: UUID=${uuid:0:8}..., Build=$build, State=$state"
fi
if [[ "$state" == "Ready" ]]; then
if [[ -z "$latest_build" ]] || [[ "$build" > "$latest_build" ]]; then
if [[ "$DEBUG" == true ]]; then
echo " New latest: $build (was: $latest_build)"
fi
latest_build="$build"
latest_uuid="$uuid"
latest_state="$state"
latest_runtime_id="$runtime_id"
fi
fi
done <<< "$platform_runtimes"
if [[ -z "$latest_build" ]]; then
print_warning "No ready $platform runtimes found (all may be unusable/duplicates)"
continue
fi
print_success "Latest $platform runtime: build $latest_build ($latest_state)"
RUNTIMES_TO_KEEP+=("$latest_uuid|$latest_build|$platform 26.0|$latest_runtime_id")
# Find old runtimes to delete
old_count=0
while IFS=$'\t' read -r uuid platform_id_check version build state runtime_id; do
if [[ "$uuid" != "$latest_uuid" ]]; then
status_msg="build $build"
if [[ "$state" == "Unusable" ]]; then
status_msg="$status_msg (unusable/duplicate)"
fi
echo " - To delete: $platform 26.0 ($status_msg)"
RUNTIMES_TO_DELETE+=("$uuid|$build|$platform 26.0|$runtime_id")
((old_count++))
fi
done <<< "$platform_runtimes"
if [[ $old_count -eq 0 ]]; then
print_status "No old $platform runtimes to clean up"
fi
echo
done
# Summary
echo "==============================================="
print_status "SUMMARY"
echo "==============================================="
if [[ ${#RUNTIMES_TO_KEEP[@]} -gt 0 ]]; then
print_success "Runtimes to KEEP (${#RUNTIMES_TO_KEEP[@]}):"
for runtime in "${RUNTIMES_TO_KEEP[@]}"; do
IFS='|' read -r uuid build name runtime_id <<< "$runtime"
echo " ✓ $name (build $build)"
done
echo
fi
if [[ ${#RUNTIMES_TO_DELETE[@]} -gt 0 ]]; then
print_warning "Runtimes to DELETE (${#RUNTIMES_TO_DELETE[@]}):"
for runtime in "${RUNTIMES_TO_DELETE[@]}"; do
IFS='|' read -r uuid build name runtime_id <<< "$runtime"
echo " ✗ $name (build $build)"
done
echo
else
print_success "No old runtimes found to delete!"
exit 0
fi
if [[ "$DRY_RUN" == true ]]; then
print_warning "DRY RUN COMPLETE - No changes made"
print_status "Run without --dry-run to actually delete the runtimes"
exit 0
fi
# Confirm deletion
echo "==============================================="
print_warning "This will permanently delete ${#RUNTIMES_TO_DELETE[@]} old runtime(s)"
read -p "Are you sure you want to continue? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_status "Cancelled by user"
exit 0
fi
# Delete old runtimes
print_status "Deleting old runtimes..."
DELETED_COUNT=0
FAILED_COUNT=0
for runtime in "${RUNTIMES_TO_DELETE[@]}"; do
IFS='|' read -r uuid build name runtime_id <<< "$runtime"
print_status "Deleting: $name (build $build, UUID: ${uuid:0:8}...)"
# Use the UUID to delete the runtime
if xcrun simctl runtime delete "$uuid" 2>/dev/null; then
print_success "Deleted: $name (build $build)"
((DELETED_COUNT++))
else
print_error "Failed to delete: $name (build $build)"
((FAILED_COUNT++))
fi
done
echo
echo "==============================================="
print_status "CLEANUP COMPLETE"
echo "==============================================="
print_success "Successfully deleted: $DELETED_COUNT runtimes"
if [[ $FAILED_COUNT -gt 0 ]]; then
print_error "Failed to delete: $FAILED_COUNT runtimes"
fi
print_status "You may want to restart Xcode and Simulator to see the changes"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment