Last active
September 8, 2026 02:04
-
-
Save dytra/d101dbef9d711fab982a2c62b76aca4f to your computer and use it in GitHub Desktop.
a CLI utility that analyzes system disk usage taken up by Xcode and iOS Simulators, listing every individual simulator sorted by disk size (with UUID, name, and status), and provides commands/flags to clean build caches (DerivedData) or erase simulator data to reclaim disk space.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # ============================================================================== | |
| # iOS Simulator & Xcode Disk Usage Inspector | |
| # Usage: ./scripts/ios_disk_usage.sh [--erase <UUID_or_Name>] [--erase-all] [--clean-deriveddata] [--delete-unavailable] | |
| # ============================================================================== | |
| set -euo pipefail | |
| BOLD='\033[1m' | |
| GREEN='\033[0;32m' | |
| CYAN='\033[0;36m' | |
| YELLOW='\033[1;33m' | |
| RED='\033[0;31m' | |
| NC='\033[0m' # No Color | |
| echo -e "${BOLD}${CYAN}======================================================${NC}" | |
| echo -e "${BOLD}${CYAN} iOS Simulator & Xcode Disk Usage Report ${NC}" | |
| echo -e "${BOLD}${CYAN}======================================================${NC}\n" | |
| # 1. System Available Disk Space | |
| AVAIL_DISK=$(df -h / | awk 'NR==2 {print $4}') | |
| TOTAL_DISK=$(df -h / | awk 'NR==2 {print $2}') | |
| echo -e "${BOLD}System Disk (/):${NC} ${GREEN}${AVAIL_DISK}${NC} available out of ${TOTAL_DISK}\n" | |
| # 2. Overall Directory Breakdown | |
| CORE_SIM_PATH="$HOME/Library/Developer/CoreSimulator" | |
| DERIVED_DATA_PATH="$HOME/Library/Developer/Xcode/DerivedData" | |
| if [ -d "$CORE_SIM_PATH" ]; then | |
| CORE_SIM_SIZE=$(du -sh "$CORE_SIM_PATH" 2>/dev/null | awk '{print $1}') | |
| else | |
| CORE_SIM_SIZE="0B" | |
| fi | |
| if [ -d "$DERIVED_DATA_PATH" ]; then | |
| DERIVED_DATA_SIZE=$(du -sh "$DERIVED_DATA_PATH" 2>/dev/null | awk '{print $1}') | |
| else | |
| DERIVED_DATA_SIZE="0B" | |
| fi | |
| echo -e "${BOLD}Developer Cache Summary:${NC}" | |
| echo -e " • CoreSimulator Total: ${YELLOW}${CORE_SIM_SIZE}${NC}" | |
| echo -e " • Xcode DerivedData: ${YELLOW}${DERIVED_DATA_SIZE}${NC}\n" | |
| # 3. Per-Simulator Breakdown | |
| DEVICES_DIR="$HOME/Library/Developer/CoreSimulator/Devices" | |
| if [ ! -d "$DEVICES_DIR" ]; then | |
| echo -e "${RED}No CoreSimulator Devices directory found at $DEVICES_DIR${NC}" | |
| exit 0 | |
| fi | |
| echo -e "${BOLD}Per-Simulator Disk Usage:${NC}" | |
| printf "%-10s | %-28s | %-10s | %-36s\n" "SIZE" "DEVICE NAME" "STATUS" "UUID" | |
| echo "---------------------------------------------------------------------------------------" | |
| temp_file=$(mktemp) | |
| for d in "$DEVICES_DIR"/*; do | |
| if [ -f "$d/device.plist" ]; then | |
| uuid=$(basename "$d") | |
| name=$(plutil -extract name xml1 -o - "$d/device.plist" 2>/dev/null | sed -n 's/.*<string>\(.*\)<\/string>.*/\1/p') | |
| runtime=$(plutil -extract runtime xml1 -o - "$d/device.plist" 2>/dev/null | sed -n 's/.*<string>\(.*\)<\/string>.*/\1/p' | sed 's/com.apple.CoreSimulator.SimRuntime.//' | tr '-' '.') | |
| # Check if booted | |
| status="Shutdown" | |
| if xcrun simctl list devices | grep -q "$uuid.*Booted"; then | |
| status="Booted" | |
| fi | |
| # Raw bytes for sorting | |
| raw_bytes=$(du -sk "$d" 2>/dev/null | awk '{print $1}') | |
| human_size=$(du -sh "$d" 2>/dev/null | awk '{print $1}') | |
| echo "$raw_bytes|$human_size|$name ($runtime)|$status|$uuid" >> "$temp_file" | |
| fi | |
| done | |
| if [ -s "$temp_file" ]; then | |
| sort -t'|' -k1 -nr "$temp_file" | while IFS='|' read -r raw human name status uuid; do | |
| if [ "$status" = "Booted" ]; then | |
| formatted_status="${GREEN}${status}${NC}" | |
| else | |
| formatted_status="${NC}${status}${NC}" | |
| fi | |
| printf "%-10s | %-28s | %-10b | %-36s\n" "$human" "${name:0:28}" "$formatted_status" "$uuid" | |
| done | |
| else | |
| echo "No active simulators found." | |
| fi | |
| rm -f "$temp_file" | |
| echo -e "\n${BOLD}${CYAN}======================================================${NC}" | |
| echo -e "${BOLD}Cleanup Options Available:${NC}" | |
| echo -e " 1. Erase a specific simulator (e.g., iPhone 16e):" | |
| echo -e " ${GREEN}./scripts/ios_disk_usage.sh --erase \"iPhone 16e\"${NC}" | |
| echo -e " ${GREEN}xcrun simctl erase <UUID>${NC}" | |
| echo -e " 2. Erase all simulator app caches (reclaims ~8-10 GB):" | |
| echo -e " ${GREEN}xcrun simctl erase all${NC}" | |
| echo -e " 3. Clear Xcode build cache (reclaims DerivedData):" | |
| echo -e " ${GREEN}rm -rf ~/Library/Developer/Xcode/DerivedData/*${NC}" | |
| echo -e " 4. Delete obsolete/unavailable simulators:" | |
| echo -e " ${GREEN}xcrun simctl delete unavailable${NC}" | |
| echo -e "${BOLD}${CYAN}======================================================${NC}" | |
| # Handle Optional Flags | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| --erase) | |
| target="${2:-}" | |
| if [ -z "$target" ]; then | |
| echo -e "${RED}Error: --erase requires a device name or UUID (e.g., 'iPhone 16e')${NC}" | |
| exit 1 | |
| fi | |
| echo -e "\n${YELLOW}Shutting down & erasing data for '$target'...${NC}" | |
| xcrun simctl shutdown "$target" 2>/dev/null || true | |
| xcrun simctl erase "$target" | |
| echo -e "${GREEN}Successfully erased data for '$target'.${NC}" | |
| shift 2 | |
| ;; | |
| --erase-all) | |
| echo -e "\n${YELLOW}Running: xcrun simctl erase all...${NC}" | |
| xcrun simctl erase all | |
| echo -e "${GREEN}Successfully erased all simulator data.${NC}" | |
| shift | |
| ;; | |
| --clean-deriveddata) | |
| echo -e "\n${YELLOW}Clearing Xcode DerivedData...${NC}" | |
| rm -rf "$HOME/Library/Developer/Xcode/DerivedData"/* | |
| echo -e "${GREEN}Successfully cleared DerivedData.${NC}" | |
| shift | |
| ;; | |
| --delete-unavailable) | |
| echo -e "\n${YELLOW}Deleting unavailable simulators...${NC}" | |
| xcrun simctl delete unavailable | |
| echo -e "${GREEN}Successfully deleted unavailable simulators.${NC}" | |
| shift | |
| ;; | |
| *) | |
| shift | |
| ;; | |
| esac | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment