{"id":51040150,"url":"https://github.com/silvansky/xcode-clr","last_synced_at":"2026-06-22T10:01:46.243Z","repository":{"id":357566991,"uuid":"1237503413","full_name":"silvansky/xcode-clr","owner":"silvansky","description":"Delete stale Xcode DerivedData and worktree build/ directories.","archived":false,"fork":false,"pushed_at":"2026-06-10T06:41:33.000Z","size":22,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-10T08:17:57.848Z","etag":null,"topics":["derived-data","macos","xcode"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/silvansky.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-13T08:40:22.000Z","updated_at":"2026-06-10T06:41:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/silvansky/xcode-clr","commit_stats":null,"previous_names":["silvansky/xcode-clr"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/silvansky/xcode-clr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvansky%2Fxcode-clr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvansky%2Fxcode-clr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvansky%2Fxcode-clr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvansky%2Fxcode-clr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/silvansky","download_url":"https://codeload.github.com/silvansky/xcode-clr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvansky%2Fxcode-clr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34643624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["derived-data","macos","xcode"],"created_at":"2026-06-22T10:01:42.830Z","updated_at":"2026-06-22T10:01:46.238Z","avatar_url":"https://github.com/silvansky.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xcode-clr\n\nDelete stale Xcode DerivedData, worktree `build/` directories, and long-unused iOS Simulators.\n\nSingle-file Python 3 CLI. No dependencies. macOS only.\n\n## What it scans\n\n- `~/Library/Developer/Xcode/DerivedData/*` — each project folder. Skips shared caches (`ModuleCache.noindex`, `SDKStatCaches.noindex`, `CompilationCache.noindex`).\n- `build/` inside every git worktree of every project Xcode has built (auto-derived from DerivedData `WorkspacePath`). Add extras with `--worktree-root`, disable auto with `--no-auto`.\n- iOS Simulator devices (`xcrun simctl list devices`) not booted in a long time. Disable with `--no-simulators`.\n\n## Staleness rules\n\nAn item is marked `to_be_removed` if **any** apply:\n\n- DerivedData's `WorkspacePath` (from `info.plist`) no longer exists → `source missing`.\n- `max(LastAccessedDate, folder mtime)` is older than 7 days → `stale \u003e7d` (override with `--days`).\n- Worktree `build/` folder mtime older than 7 days → `stale \u003e7d`.\n- Simulator last booted (`lastBootedAt`) older than 14 days → `stale \u003e14d` (override with `--simulator-days`).\n- Simulator whose runtime is no longer installed → `runtime unavailable`.\n\nSimulators that are **currently booted** or were **never booted** (Xcode's default templates) are never removed.\n\n## Usage\n\n```\nxcode-clr [--dry-run] [--json] [--yes] [--days N] [--worktree-root PATH]\n```\n\n| Flag | Effect |\n|---|---|\n| *(none)* | Print table, prompt once, delete on `y`. |\n| `--dry-run` | Print table, never delete. |\n| `--json` | Emit JSON to stdout (all scanned items, `to_be_removed` flag). No prompts, no delete. |\n| `--yes` / `-y` | Skip confirmation; delete everything marked. |\n| `--days N` | Staleness threshold for DerivedData \u0026 worktree builds (default `7`). |\n| `--simulator-days N` | Staleness threshold for simulators (default `14`). |\n| `--worktree-root PATH` | Extra git worktree root to scan. Repeatable. |\n| `--no-auto` | Disable auto-discovery of worktree roots from DerivedData. |\n| `--no-simulators` | Skip scanning iOS Simulator devices. |\n| `--all` | List every item found (stale and fresh). Deletion still targets only stale ones. |\n\n## Install\n\nClone anywhere, make the script executable, then symlink it into any directory on your `PATH`:\n\n```sh\ngit clone https://github.com/silvansky/xcode-clr.git\nchmod +x xcode-clr/xcode-clr\n# pick whichever PATH dir you use:\nln -s \"$PWD/xcode-clr/xcode-clr\" /opt/homebrew/bin/xcode-clr   # Apple Silicon Homebrew\nln -s \"$PWD/xcode-clr/xcode-clr\" /usr/local/bin/xcode-clr      # Intel Homebrew\nln -s \"$PWD/xcode-clr/xcode-clr\" \"$HOME/.local/bin/xcode-clr\"  # user-local\n```\n\nVerify with `which xcode-clr \u0026\u0026 xcode-clr --dry-run`.\n\nThe shebang is `/usr/bin/python3` (system Python 3.9+, stdlib only — no `pip install` needed).\n\n## Claude skill\n\nThe repo ships a [Claude Code](https://docs.claude.com/en/docs/claude-code) skill at `.claude/skills/xcode-clr/SKILL.md`. When loaded, Claude will reach for `xcode-clr` automatically on prompts like \"free up disk space\", \"clean DerivedData\", \"Xcode is eating my drive\". It defaults to `xcode-clr --json` for safe, structured inventory and only invokes destructive commands after you confirm.\n\nInstall once, globally:\n\n```sh\nln -s \"$PWD/xcode-clr/.claude/skills/xcode-clr\" \"$HOME/.claude/skills/xcode-clr\"\n```\n\n(or run `claude` from inside this repo — project-local `.claude/skills` is picked up automatically).\n\nUninstall: `rm \"$HOME/.claude/skills/xcode-clr\"`.\n\n## Configuration\n\nOptional config at `~/.config/xcode-clr/config.json` (or `$XDG_CONFIG_HOME/xcode-clr/config.json`):\n\n```json\n{\n  \"worktree_roots\": [\"~/code/my-ios-app\", \"~/work/other-repo\"],\n  \"threshold_days\": 14,\n  \"auto_discover\": true,\n  \"scan_simulators\": true,\n  \"simulator_threshold_days\": 14\n}\n```\n\nPaths support `~` expansion.\n\nEnvironment override: `XCODE_CLR_WORKTREE_ROOTS=/path/a:/path/b` (colon-separated).\n\nPrecedence: CLI flags \u003e env \u003e config file \u003e built-in defaults. `worktree_roots` from all sources are merged \u0026 deduped.\n\n## JSON output\n\n```json\n{\n  \"scanned_at\": \"2026-05-13T08:13:09Z\",\n  \"threshold_days\": 7,\n  \"items\": [\n    {\n      \"path\": \"/Users/.../DerivedData/Foo-abc\",\n      \"kind\": \"derived_data\",\n      \"source_path\": \"/Users/.../Foo.xcworkspace\",\n      \"size_bytes\": 1234567,\n      \"last_accessed\": \"2026-04-13T06:55:31Z\",\n      \"mtime\": \"2026-04-13T06:55:31Z\",\n      \"age_days\": 30.05,\n      \"reason\": \"stale \u003e7d\",\n      \"to_be_removed\": true\n    }\n  ]\n}\n```\n\n`kind` is `\"derived_data\"`, `\"worktree_build\"`, or `\"simulator\"`. `reason` is `null` for kept items. Simulator items add `name`, `udid`, `state`, and `available`; their `last_accessed` is the device's last boot time.\n\n## Examples\n\n```sh\nxcode-clr --dry-run                 # preview\nxcode-clr --json | jq '.items[] | select(.to_be_removed)'\nxcode-clr --yes                     # non-interactive cleanup\nxcode-clr --days 30                 # only purge things older than 30d\nxcode-clr --all --dry-run           # full inventory, stale and fresh\nxcode-clr --worktree-root ~/work/repo-a --worktree-root ~/work/repo-b\nxcode-clr --no-auto                 # only scan explicit/config roots\nxcode-clr --no-simulators           # skip iOS Simulator devices\nxcode-clr --simulator-days 30       # only purge sims unbooted \u003e30d\nxcode-clr --json | jq '.items[] | select(.kind==\"simulator\" and .to_be_removed)'\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilvansky%2Fxcode-clr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsilvansky%2Fxcode-clr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilvansky%2Fxcode-clr/lists"}