Skip to content

bmdragos/xclaude

 
 

Repository files navigation

xclaude

Terraform for Apple development. An MCP server that lets Claude Code build, sign, and deploy iOS/macOS/visionOS apps without Xcode project files.

What is this?

xclaude is an MCP (Model Context Protocol) server that gives Claude Code the ability to:

  • Create iOS/macOS apps from scratch
  • Build and deploy to simulators and physical devices
  • Automatically discover and configure code signing
  • Run tests, capture screenshots, read logs
  • Generate SwiftData models, widgets, and API clients
  • Archive and upload to the App Store

All without ever opening Xcode or creating an .xcodeproj file.

What's New in v4.0.0

End-to-end App Store workflow now works! Build → Sign → Archive → Validate → Upload to TestFlight, all from Claude.

  • Dev ↔ Distribution switching: Dual signing config ([signing.iOS.development] and [signing.iOS.distribution]), automatic profile type detection
  • Proper IPA signing: Fixed AppleDouble resource fork contamination that broke code signatures
  • Device family targeting: devices = ["iphone"] in xclaude.toml correctly sets UIDeviceFamily
  • Better error handling: Upload tool now properly detects altool errors even when exit code is 0
  • Profile name collision fix: Profiles filtered by team ID and type, not just display name

Installation

Install via Mint (recommended)

mint install bmdragos/xclaude

This installs both xclaude and swift-bundler to ~/.mint/bin/.

Note: First install takes 3-5 minutes to compile dependencies. Subsequent updates are faster.

Build from source

git clone https://github.com/bmdragos/xclaude.git
cd xclaude
swift build -c release

The binaries will be at .build/release/xclaude and .build/release/swift-bundler.

Add to Claude Code

Add to your Claude Code MCP settings (~/.claude/settings.json or project .claude/settings.json):

{
  "mcpServers": {
    "xclaude": {
      "command": "~/.mint/bin/xclaude"
    }
  }
}

Or if you built from source:

{
  "mcpServers": {
    "xclaude": {
      "command": "/path/to/xclaude/.build/release/xclaude"
    }
  }
}

Restart Claude Code to load the MCP server.

Quick Start

Once configured, just ask Claude:

"Create a new iOS app called TaskMaster and deploy it to my iPhone"

Claude will use xclaude to:

  1. Create the project structure
  2. Generate Package.swift and xclaude.toml
  3. Scaffold SwiftUI app code
  4. Discover signing credentials
  5. Build and deploy to your device

For physical devices: You'll need an Apple Developer account with provisioning profiles set up. Run configure_signing to auto-discover and apply credentials.

Project Structure

xclaude uses conventions:

MyApp/
├── xclaude.toml          # Simple config (the only config you need)
├── icon.png              # 1024x1024 app icon
├── Package.swift         # Swift Package Manager manifest
├── Sources/MyApp/
│   ├── MyAppApp.swift    # @main entry point
│   └── ContentView.swift
└── .xclaude/             # Generated (gitignored)
    └── derived/          # Bundler.toml, entitlements, etc.

Configuration

xclaude.toml is intentionally minimal:

[app]
name = "MyApp"
# bundle_id = "com.company.myapp"  # Optional, derived from name
# version = "1.0.0"                # Optional, defaults to 1.0.0

[signing]
# team = "ABC123XYZ"               # Optional, auto-discovered
# identity = "Apple Development"   # Optional, auto-discovered
# profile = "iOS Team Provisioning" # Optional, auto-discovered

Most projects only need the app name. Everything else is auto-discovered.

Features

60 MCP Tools

Category Tools
Project create_project, init_project, get_config, update_config
Signing discover_signing, get_signing_status, configure_signing
Build build, build_start, build_status, build_logs, build_cancel
Deploy deploy, run, watch, stop_watch
Devices list_simulators, list_devices, reset_simulator
Debug screenshot, get_logs, get_crash_logs, diagnose
Test test
Dependencies add_dependency
Capabilities add_capability, remove_capability, list_capabilities
Distribution archive, validate, upload
Scaffolding generate_icon, add_model, add_extension, generate_api_client
App Store Connect asc_configure, asc_status, asc_list_devices, asc_register_device, asc_list_profiles, asc_create_profile, asc_delete_profile, asc_download_profile, asc_regenerate_profile, asc_list_certificates, asc_create_certificate, asc_revoke_certificate, asc_list_apps, asc_list_bundle_ids, asc_create_bundle_id, asc_create_app, asc_list_builds, asc_list_groups, asc_create_group, asc_add_build_to_group, asc_list_testers, asc_add_tester, asc_remove_tester, asc_set_whats_new
Info get_version

Async Builds

For long-running builds, use the async pattern:

build_start()                    → { job_id: "build-1" }  # defaults to iOS device
build_status(job_id: "build-1")  → { status: "running", appPath: ".build/bundler/MyApp.app" }
build_logs(job_id: "build-1")    → { lines: [...], status: "success" }
deploy(app_path: "...")          → { success: true }  # bundle_id auto-detected

Options:

  • build_start(clean: true) - delete .build/ before building
  • build_logs(clear: true) - clear buffer after reading (default: preserves buffer)
  • deploy auto-detects bundle_id from xclaude.toml, defaults to device target

Example Workflows

Create and run a new app:

"Create an iOS app called WeatherApp and deploy it to my iPhone"

Build for Mac:

"Build and run my app on macOS"

Add a SwiftData model:

"Add a SwiftData model called Task with properties: id (UUID), title (String), isComplete (Bool), dueDate (Date?)"

Add a widget:

"Add a widget extension to my app"

Prepare for App Store:

"Archive my app for App Store submission"

Debug issues:

"Take a screenshot and show me the recent logs"

Add macOS automation capability:

"Add the apple-events capability so my app can control other apps"

Capabilities (61 available)

add_capability stores capabilities in xclaude.toml and handles Info.plist usage descriptions:

add_capability("apple-events")
        ↓
┌─────────────────────────────────────────────────────────────┐
│ xclaude.toml:                                               │
│   [capabilities]                                            │
│   apple-events = true                                       │
│                                                             │
│   [info_plist]                                              │
│   NSAppleEventsUsageDescription = "This app needs to..."   │
└─────────────────────────────────────────────────────────────┘
        ↓
    build (macOS)  →  entitlements generated fresh, app signed

Entitlements.plist is regenerated fresh each build from [capabilities], avoiding cross-platform contamination.

iOS/Shared: push-notifications, app-groups, icloud, keychain, healthkit, homekit, in-app-purchase, siri, wallet, background-modes, and more.

macOS: apple-events, hardened-runtime, camera, microphone, location, files-read-write, system-extension, network-client, network-server, bluetooth, usb, print, serial, app-sandbox, and more.

Continuity/Ecosystem: handoff, associated-domains, sign-in-with-apple, shareplay, nfc, carplay, weatherkit, and more.

Notifications: critical-alerts, time-sensitive, communication-notifications.

Newer APIs: shazamkit, musickit, push-to-talk, matter, financekit, devicecheck.

Performance: increased-memory-limit, extended-virtual-addressing.

Other: personal-vpn, data-protection, family-controls, autofill-credentials, maps-routing.

Run list_capabilities to see all 61 with platform info.

App Store Connect Integration

Automate device registration, provisioning profiles, and TestFlight distribution:

Setup (one-time):

  1. Go to App Store Connect → Users and Access → Keys
  2. Generate an API Key (Admin role recommended)
  3. Download the .p8 private key (only available once!)
  4. Configure: asc_configure(issuer_id: "...", key_path: "/path/to/AuthKey_XXX.p8")

Register a new device:

asc_register_device(udid: "00008130-...", name: "Test iPhone")
asc_regenerate_profile(bundle_id: "com.example.myapp")
# Profile now includes the new device

Deploy to TestFlight:

# 1. Archive and upload
archive()  → .ipa file
upload(path: "MyApp.ipa")  # Auto-uses ASC credentials

# 2. Wait for processing (~5-10 min)
asc_list_builds(app_id: "...")  # Check for new build

# 3. Distribute to testers
asc_add_build_to_group(group_id: "...", build_id: "...")
asc_set_whats_new(build_id: "...", whats_new: "Bug fixes and improvements")

Known limitations:

  • Cannot create apps via API (Apple limitation) - asc_create_app returns manual steps
  • The upload tool auto-uses credentials from asc_configure

Auto-Discovery

xclaude automatically discovers:

  • Signing identities from your keychain
  • Provisioning profiles from ~/Library/Developer/Xcode/UserData/Provisioning Profiles/
  • Simulators via xcrun simctl
  • Physical devices via xcrun devicectl

Run configure_signing to see available options and auto-apply the best match.

Supported Platforms

  • iOS / iPadOS
  • macOS
  • tvOS
  • visionOS

Requirements

  • macOS 13+
  • Xcode Command Line Tools
  • Mint (for easy installation): brew install mint
  • For physical devices: Apple Developer account with provisioning profiles

How It Works

xclaude is built on top of Swift Bundler, a tool for building Swift apps without Xcode. xclaude adds:

  1. MCP interface - JSON-RPC 2.0 protocol for Claude Code integration
  2. Auto-discovery - Automatic signing credential detection
  3. Config translation - Simple xclaude.toml → Swift Bundler's Bundler.toml
  4. Scaffolding - Project, model, extension, and API client generation
  5. Developer tools - Screenshots, logs, diagnostics

Troubleshooting

"No signing identity found"

Run discover_signing to see available identities, or:

security find-identity -v -p codesigning

"No provisioning profile found"

For simulators, no profile is needed. For devices:

  1. Open Xcode → Settings → Accounts
  2. Add your Apple ID and download provisioning profiles
  3. Run configure_signing in xclaude

See Apple's Distributing Your App to Registered Devices guide for detailed setup.

Build fails

Run diagnose to check your environment:

  • Xcode installation
  • Package.swift validity
  • Icon presence
  • Signing status

"A valid provisioning profile was not found" (device install fails)

This usually means one of:

  1. Certificate not in profile: The profile was created before your signing certificate existed

    • Go to Apple Developer Portal → Profiles → Edit your profile
    • Check your certificate is selected
    • Regenerate and reinstall the profile
  2. Device not in profile: Your device isn't registered to the profile

    • Check Portal → Devices for your device
    • Device UDIDs differ between formats: devicectl shows CoreDevice UUID, Portal shows hardware UDID
    • Both refer to the same device - use xcrun devicectl device info details --device <udid> to see hardware UDID
  3. Entitlement mismatch: App has entitlements the profile doesn't allow

    • macOS sandbox entitlements (com.apple.security.*) don't work on iOS
    • xclaude v3.7.0+ regenerates entitlements fresh each build, auto-filtering by platform

Certificate shows in Xcode but not in keychain

If Xcode shows your certificate but security find-identity -v -p codesigning doesn't:

  1. The private key wasn't saved when the cert was created
  2. Fix: In Xcode → Settings → Accounts → Manage Certificates, delete the cert and create a new one
  3. Or manually: Generate CSR in Keychain Access, upload to Portal, download and import the .cer

Multiple teams/certificates confusion

Apple certificates embed the team ID in the Common Name (CN), but organizational certs may show a different team ID than the organization:

# Certificate might show:
"Apple Development: Your Name (PERSONAL_TEAM_ID)"
# But actually belong to:
OU=ORGANIZATION_TEAM_ID

xclaude will match based on the provisioning profile's team. Use discover_signing to see all available identities and profiles.

Multi-platform apps (iOS + macOS)

xclaude supports building for multiple platforms from the same project:

# Build for iOS
build(platform: "iOS")

# Build for macOS
build(platform: "macOS")

Platform-specific entitlements are handled automatically:

  • Entitlements regenerated fresh each build from [capabilities] in xclaude.toml
  • macOS-only capabilities filtered out for iOS builds (and vice versa)
  • Info.plist usage descriptions added for iOS capabilities (camera, bluetooth, etc.)

License

MIT

Credits

Built on Swift Bundler by stackotter.

About

MCP server for Claude Code to build, sign, and deploy iOS/macOS apps without Xcode project files

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Swift 99.7%
  • Other 0.3%