XcodesOrg/xcodes
The best command-line tool to install and switch between multiple versions of Xcode.
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 8mo ago
- ✓16 active contributors
- ✓MIT licensed
Show 4 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Slowing — last commit 8mo ago
- ⚠Concentrated ownership — top contributor handles 56% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/xcodesorg/xcodes)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/xcodesorg/xcodes on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: XcodesOrg/xcodes
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/XcodesOrg/xcodes shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 8mo ago
- 16 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Slowing — last commit 8mo ago
- ⚠ Concentrated ownership — top contributor handles 56% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live XcodesOrg/xcodes
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/XcodesOrg/xcodes.
What it runs against: a local clone of XcodesOrg/xcodes — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in XcodesOrg/xcodes | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 255 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of XcodesOrg/xcodes. If you don't
# have one yet, run these first:
#
# git clone https://github.com/XcodesOrg/xcodes.git
# cd xcodes
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of XcodesOrg/xcodes and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "XcodesOrg/xcodes(\\.git)?\\b" \\
&& ok "origin remote is XcodesOrg/xcodes" \\
|| miss "origin remote is not XcodesOrg/xcodes (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "Sources/xcodes/App.swift" \\
&& ok "Sources/xcodes/App.swift" \\
|| miss "missing critical file: Sources/xcodes/App.swift"
test -f "Sources/XcodesKit/XcodeInstaller.swift" \\
&& ok "Sources/XcodesKit/XcodeInstaller.swift" \\
|| miss "missing critical file: Sources/XcodesKit/XcodeInstaller.swift"
test -f "Sources/AppleAPI/Client.swift" \\
&& ok "Sources/AppleAPI/Client.swift" \\
|| miss "missing critical file: Sources/AppleAPI/Client.swift"
test -f "Sources/XcodesKit/Models.swift" \\
&& ok "Sources/XcodesKit/Models.swift" \\
|| miss "missing critical file: Sources/XcodesKit/Models.swift"
test -f "Sources/XcodesKit/XcodeList.swift" \\
&& ok "Sources/XcodesKit/XcodeList.swift" \\
|| miss "missing critical file: Sources/XcodesKit/XcodeList.swift"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 255 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~225d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/XcodesOrg/xcodes"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
A Swift CLI tool that automates downloading, installing, and switching between multiple Xcode versions on macOS. It authenticates with Apple Developer credentials, resolves available Xcode releases from Apple's servers, downloads .xip archives via aria2, and manages parallel installations in /Applications. Core capability: reduces setup friction when developing for multiple Xcode/iOS versions. SwiftPM monorepo: Sources/AppleAPI contains Apple authentication and API communication (Client.swift, URLRequest+Apple.swift, Hashcash.swift); Sources/XcodesKit contains the core business logic (Downloader, DataSource, FastlaneSessionManager, Models); Sources/Unxip wraps unxip binary for .xip decompression. CLI entry point wraps XcodesKit. Configuration/state managed via Configuration.swift and Migration.swift.
👥Who it's for
iOS/macOS developers and CI/CD engineers who need to test against multiple Xcode versions, manage SDKs and runtimes, and automate Xcode setup on CI runners or development machines without manual App Store downloads.
🌱Maturity & risk
Production-ready and actively maintained. Project is part of the XcodesOrg organization with CI via GitHub Actions (.github/workflows/ci.yml), signing/notarization for release builds, and Homebrew distribution. Well-documented with clear installation and usage examples. Recent work visible in release-drafter and dependabot configuration suggests ongoing updates.
Low risk for a CLI tool of this scope. Single-language codebase (Swift), minimal external dependencies via SwiftPM, and strong macOS/Apple platform lock-in (which is intentional and expected). Risk: requires valid Apple Developer account and network access to Apple's APIs; authentication state lives in keychain and Fastlane session cookies, so credential management is critical.
Active areas of work
Project recently reorganized into XcodesOrg (see nextstep.md and CODEOWNERS). CI/CD pipeline active with release-drafter automating changelog generation. Makefile-driven builds and development. No recent breaking changes evident, but authentication/session handling and unxip experimental feature (--experimental-unxip flag) are active development areas.
🚀Get running
git clone https://github.com/XcodesOrg/xcodes && cd xcodes && make install (installs to /usr/local/bin, or PREFIX=/your/path make install). Requires Xcode 12.0+ to build from source; alternatively install prebuilt binary via brew install xcodesorg/made/xcodes.
Daily commands: make build compiles via swiftbuild; make install installs binary. No dev server (CLI-only tool). For local testing: swift build to produce .build/debug/xcodes, then invoke directly or via swift run xcodes install <version>. Requires network access to Apple's authentication and release API endpoints.
🗺️Map of the codebase
Sources/xcodes/App.swift— CLI entry point using ArgumentParser; every contributor must understand the command structure and how commands flow to downstream modulesSources/XcodesKit/XcodeInstaller.swift— Core installer orchestration logic; handles download, verification, and installation workflows that are central to the tool's purposeSources/AppleAPI/Client.swift— Apple authentication and API communication layer; critical for fetching Xcode versions and handling 2FA, all contributors need auth patternsSources/XcodesKit/Models.swift— Core data models (Xcode, Version, Release); foundational types used throughout the codebaseSources/XcodesKit/XcodeList.swift— Xcode version discovery and listing; bridges API calls to installation logicPackage.swift— Swift package manifest defining dependencies and targets; essential for understanding build configuration and external dependencies
🛠️How to make changes
Add support for a new Xcode data source
- Create new DataSource conformance in Sources/XcodesKit/DataSource.swift implementing the protocol with a fetchAvailableReleases() method (
Sources/XcodesKit/DataSource.swift) - Add case to DataSource enum and update switch statements if needed; add version parsing extension if new format (
Sources/XcodesKit/DataSource.swift) - Register new source as CLI option in App.swift's install/list command arguments (
Sources/xcodes/App.swift) - Add test fixtures in Tests/AppleAPITests/Fixtures and unit tests in Tests/AppleAPITests/AppleAPITests.swift (
Tests/AppleAPITests/AppleAPITests.swift)
Add a new CLI command
- Create new ParsableCommand subclass in Sources/xcodes/App.swift with appropriate @Argument/@Option properties (
Sources/xcodes/App.swift) - Implement run() method; call into XcodesKit (e.g., XcodeInstaller.install(), XcodeList.availableXcodes()) (
Sources/xcodes/App.swift) - Add command to subcommands array in main XcodesApp definition (
Sources/xcodes/App.swift) - Handle custom error formatting if needed via ParsableArguments+LegibleError.swift (
Sources/xcodes/ParsableArguments+LegibleError.swift)
Improve version matching or comparison logic
- Understand Version struct and its comparison operators in Sources/XcodesKit/Version.swift (
Sources/XcodesKit/Version.swift) - Add Xcode-specific parsing logic (build numbers, pre-release tags) in Sources/XcodesKit/Version+Xcode.swift (
Sources/XcodesKit/Version+Xcode.swift) - Use Models+FirstWithVersion.swift helpers in XcodeList.swift when filtering/matching versions (
Sources/XcodesKit/Models+FirstWithVersion.swift) - Write version matching tests in Tests/AppleAPITests/AppleAPITests.swift with semantic versioning edge cases (
Tests/AppleAPITests/AppleAPITests.swift)
Enhance authentication or Apple API integration
- Review Apple API flow in Sources/AppleAPI/Client.swift; understand the session lifecycle and Hashcash PoW (
Sources/AppleAPI/Client.swift) - Modify or extend authentication methods in AppleSessionService.swift if changing session management (
Sources/XcodesKit/AppleSessionService.swift) - Update URLRequest+Apple.swift if adding new request headers or authentication schemes (
Sources/AppleAPI/URLRequest+Apple.swift) - Add test fixtures and test cases for new auth scenarios in Tests/AppleAPITests/Fixtures and AppleAPITests.swift (
Tests/AppleAPITests/AppleAPITests.swift)
🔧Why these technologies
- Swift + PromiseKit — Async coordination across downloads, API
🪤Traps & gotchas
Apple API requires valid Apple Developer credentials and will prompt interactively unless XCODES_USERNAME and XCODES_PASSWORD env vars are set. Keychain storage is per-user; sudo operations require password re-entry. xcode-select must point to a valid Xcode or CLT (see README build section)—if xcrun fails with 'terminated(72)', your Xcode path is unset. aria2 and unxip must be available in PATH. Downloaded .xip files are large (10GB+); disk space validation is crucial. macOS-only: no Linux/Windows support.
🏗️Architecture
💡Concepts to learn
- Apple Developer Authentication & Session Persistence — xcodes must authenticate to Apple's servers to fetch Xcode releases and download .xip files. Understanding how credentials are stored (Keychain), session cookies are parsed (Fastlane format), and re-used across invocations is critical to contributing to authentication logic.
- Proof-of-Work (Hashcash) in HTTP Headers — Sources/AppleAPI/Hashcash.swift implements a Hashcash proof-of-work mechanism that Apple requires in API requests. This is a non-standard anti-bot measure and understanding its role in URLRequest+Apple.swift is key to debugging API failures.
- XIP Archive Format & Native Decompression — Xcode is distributed as .xip (eXtensible Internet Protocol) archives, a proprietary Apple compression format. xcodes wraps the native unxip binary (Sources/Unxip/Unxip.swift) for decompression; understanding this format and when to use native vs. experimental unxip is key to installation reliability.
- Promise-based Async Composition (PromiseKit) — Sources/XcodesKit/Promise+.swift and PromiseKit+Async.swift extend PromiseKit to chain download, unarchive, and install steps. Understanding promise chaining and error propagation is essential for modifying the installation pipeline.
- Parallel Download Orchestration (aria2) — Sources/XcodesKit/Downloader.swift shells out to aria2 for multi-segment, resumable parallel downloads of large .xip files. Understanding aria2 command construction and exit codes is necessary for improving download reliability and progress reporting.
- Xcode Runtime & SDK Versioning — Models in Sources/XcodesKit/Models+Runtimes.swift and Models+FirstWithVersion.swift parse and expose iOS runtime and SDK versions bundled with each Xcode release. Contributors need to understand how runtimes are versioned, queried, and matched to development targets.
🔗Related repos
XcodesOrg/XcodesApp— Official GUI companion to this CLI tool; provides a native macOS app interface for the same Xcode installation/switching functionality.yonaskolb/Mint— Package manager for Swift CLI tools that can install xcodes; used as an alternative installation method to Homebrew.fastlane/fastlane— Fastlane's session and credential storage mechanisms are parsed by xcodes (FastlaneCookieParser.swift); many users have Fastlane sessions to reuse.mas-cli/mas— Companion macOS CLI for App Store automation; users installing multiple Xcode versions often also need programmatic App Store access.TheCocoaProject/Xcode-Downloads— Predecessor project with similar goals; provides context on how Xcode version discovery and installation evolved in the community.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for XcodeInstaller.swift
XcodeInstaller.swift is a critical component handling Xcode installation logic, but Tests/AppleAPITests only shows AppleAPI tests. The installer likely has complex logic for download verification, installation paths, and error handling that needs test coverage. This would improve reliability for a tool that modifies system state.
- [ ] Create Tests/XcodesKitTests/XcodeInstallerTests.swift
- [ ] Add tests for installation path validation and permission handling
- [ ] Add tests for .xip extraction and verification using Sources/Unxip/Unxip.swift
- [ ] Add tests for error cases (disk space, interrupted downloads, corrupted files)
- [ ] Add integration tests with FastlaneSessionManager and RuntimeInstaller flows
Add GitHub Actions workflow for Swift linting and formatting checks
.github/workflows only contains ci.yml and release-drafter.yml. There's no automated Swift format/lint checking. Adding swift-format validation would catch style inconsistencies before review, matching best practices for the Swift ecosystem and reducing maintainer overhead.
- [ ] Create .github/workflows/swift-lint.yml
- [ ] Configure swift-format to validate formatting on all PRs targeting Sources/ and Tests/
- [ ] Add .swift-format configuration file to repo root with project standards
- [ ] Include instructions in CONTRIBUTING.md for running swift-format locally
- [ ] Set workflow to fail if formatting violations are found
Add unit tests for RuntimeInstaller.swift and RuntimeList.swift
Runtime installation is a distinct feature from Xcode installation (evident from separate files RuntimeInstaller.swift and RuntimeList.swift). These files manage simulator runtimes and likely have complex logic, but no corresponding test files exist in Tests/. This is critical for a system administration tool.
- [ ] Create Tests/XcodesKitTests/RuntimeInstallerTests.swift
- [ ] Add tests for runtime version parsing and validation using Sources/XcodesKit/Models.swift Version types
- [ ] Add tests for runtime download detection and installation state management
- [ ] Create Tests/XcodesKitTests/RuntimeListTests.swift for fetching and caching runtime lists
- [ ] Add tests for error handling (network failures, invalid runtime versions, installation conflicts)
🌿Good first issues
- Add unit tests for Sources/XcodesKit/FastlaneCookieParser.swift and FastlaneSessionManager.swift—these parse Fastlane session cookies but no test coverage is visible in the repo. Contribute tests covering valid/invalid session formats and credential extraction.
- Improve error messaging in Sources/AppleAPI/Client.swift for common failures (network timeouts, invalid credentials, API changes). Add specific error types and user-friendly messages instead of generic failures.
- Document the Hashcash.swift proof-of-work mechanism in-code and in CONTRIBUTING.md—this is a non-obvious Apple API requirement with no visible inline explanation; clarify why it's needed and how to test it.
⭐Top contributors
Click to expand
Top contributors
- @MattKiazyk — 56 commits
- @StevenSorial — 13 commits
- @spadafiva — 5 commits
- @pastey — 4 commits
- @dependabot[bot] — 4 commits
📝Recent commits
Click to expand
Recent commits
93bce87— Merge pull request #437 from XcodesOrg/matt/runtimeMultipleArchitecture (MattKiazyk)0dd7ae2— support multiple architectures for runtimes (MattKiazyk)938adbc— update readme to include other release options (MattKiazyk)0b81089— v 1.6.2 (MattKiazyk)a90e656— update CI to macOS 15 (MattKiazyk)d343d5a— Merge pull request #430 from pennig/patchable-cryptex-disk-image-kind (MattKiazyk)3b6255d— Merge pull request #429 from pastey/use-new-org-name (MattKiazyk)478e239— Add patchable cryptex disk image handling (pennig)a187b23— use the correct org name (pastey)998596c— v 1.6.1 (MattKiazyk)
🔒Security observations
The xcodes codebase demonstrates reasonable security practices but has several areas requiring attention. Primary concerns include secure handling of Apple authentication credentials, custom cryptographic implementations (Hashcash), and proper validation of file system operations and process execution. The tool's critical function of managing developer credentials requires strict security controls. Test fixtures should be sanitized to prevent credential exposure. No hardcoded secrets are visible in the file structure. The codebase would benefit from security-focused code review, particularly around authentication handling and system operations.
- Medium · Potential Credential Exposure in Test Fixtures —
Tests/AppleAPITests/Fixtures/Login_*/. Test fixture files contain JSON responses that may include authentication tokens, session data, or sensitive API responses (OlympusSession.json, ITCServiceKey.json). If these fixtures contain real credentials or follow patterns that expose sensitive information, they could be leveraged to understand authentication mechanisms. Fix: Ensure all test fixtures use sanitized, non-functional mock data. Remove any real tokens, session IDs, or credentials from fixture files. Consider using placeholder values or UUIDs instead. - Medium · Fastlane Session Management Requires Secure Storage —
Sources/XcodesKit/FastlaneSessionManager.swift, Sources/XcodesKit/FastlaneCookieParser.swift. The presence of FastlaneSessionManager.swift and FastlaneCookieParser.swift suggests the tool handles Fastlane session cookies for Apple authentication. Fastlane sessions may contain sensitive authentication tokens that need proper protection. Fix: Verify that session data is stored securely (using Keychain on macOS). Ensure sessions are properly validated and expired. Implement session rotation and invalidation. Sanitize any session data before logging or error reporting. - Medium · Apple API Client Authentication Handling —
Sources/AppleAPI/Client.swift, Sources/AppleAPI/URLRequest+Apple.swift. Custom Apple API client implementation (Client.swift, URLRequest+Apple.swift) handles authentication. Custom authentication implementations may contain vulnerabilities such as improper certificate validation, insecure token handling, or MITM vulnerabilities. Fix: Conduct thorough review of certificate pinning implementation. Ensure proper TLS/SSL validation. Verify that authentication tokens are handled securely and not logged. Ensure secure defaults for URLSession configuration. - Medium · Hashcash Implementation Security —
Sources/AppleAPI/Hashcash.swift. Custom Hashcash implementation (Hashcash.swift) is present, which is typically used for proof-of-work. Custom cryptographic implementations are prone to vulnerabilities if not properly reviewed. Fix: Ensure the Hashcash implementation follows published specifications exactly. Have the implementation reviewed by a cryptography expert. Verify it's used only for its intended purpose and not for securing sensitive data. - Low · Process Execution Without Input Validation Details —
Sources/XcodesKit/Process.swift. The presence of Process.swift suggests execution of system commands. Without visible input validation patterns, there's a theoretical risk of command injection if user input or external data is passed to process execution. Fix: Ensure all command-line arguments are properly escaped and validated before execution. Use secure APIs like Process with explicit argument arrays rather than shell strings. Implement allow-lists for commands that can be executed. - Low · File System Operations Without Visible Permission Checks —
Sources/XcodesKit/FileManager+.swift, Sources/XcodesKit/Path+.swift. FileManager+.swift and Path+.swift suggest custom file system operations. Without visible implementation details, there's a risk of path traversal or improper permission handling. Fix: Implement strict path validation to prevent directory traversal attacks. Verify file permissions before operations. Use secure temporary file creation APIs. Implement proper error handling for permission-denied scenarios. - Low · Unxip Tool May Require Validation —
Sources/Unxip/Unxip.swift. Custom unxip implementation (Unxip.swift) handles Xcode archive extraction. Improper archive handling could lead to directory traversal or arbitrary file extraction vulnerabilities. Fix: Validate archive structure before extraction. Implement path validation to prevent directory traversal. Use safe extraction APIs with proper permission handling. Verify archive integrity before processing.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.