Сборка Mac и iOS приложений без открытия Xcode
Как собирать и публиковать Mac и iOS приложения через командную строку и Claude Code, не открывая Xcode ни разу. Практический гайд.
Зачем вообще избегать Xcode?
Xcode — мощный инструмент, но у него есть одна фундаментальная проблема: он стоит на пути. Многие разработчики, работающие с Mac годами, так и не полюбили Xcode — непривычные горячие клавиши, Navigation-панели мышью, странная логика вкладок. Но главное — в Xcode совершенно не интегрированы LLM-инструменты, которые сегодня кардинально ускоряют разработку.
Есть и хорошая новость: Xcode.app должен быть установлен, но его никогда не нужно открывать. Инструменты xcodebuild, notarytool, stapler и devicectl — все они живут внутри Xcode и отлично работают из командной строки.
Именно этим подходом пользуется Scott Willsey в своём проекте: с небольшой предварительной настройкой можно кодить Mac и iOS приложения сколько угодно, не смотря на Xcode. А если что-то непонятно — достаточно направить Claude Code на нужный материал и позволить ему разобраться.
«После первоначальной настройки слово “выпустить новую сборку” превращается в одно предложение.»
Что нужно сделать один раз: одноразовая настройка
Прежде чем полностью уйти в терминал, нужно пройти несколько шагов через GUI — но только один раз.
Несколько одноразовых шагов действительно требуют графического интерфейса или интерактивного терминала: войти в Apple ID, создать сертификат Developer ID и сохранить пароль для нотаризации. После этого — сборка и деплой полностью headless.
Шаг 1: Apple Developer Account
Необходимо иметь платный аккаунт Apple Developer, чтобы распространять и нотаризировать приложения. Нотаризация нужна, чтобы macOS и iOS не приняли ваш бинарник за вредоносное ПО и не удалили его.
Шаг 2: Два типа сертификатов
Developer ID Application и Apple Development — это два разных сертификата. Apple Development — для сборки и запуска на собственных устройствах, локальной отладки. Developer ID Application — для нотаризированного .app-бандла, который проходит Gatekeeper и запускается на чужом Mac.
Шаг 3: Ключ подписи в keychain
Подпись основана на сертификате в keychain. Ключ подписи хранится в login keychain, xcodebuild находит его автоматически. Никаких секретов в репозитории.
Инструменты командной строки: ваш новый рабочий стол
После одноразовой настройки весь pipeline переходит в терминал. Вот ключевые утилиты:
| Инструмент | Назначение | Где живёт |
|---|---|---|
xcodebuild | Компиляция, архивирование, экспорт | Внутри Xcode.app |
notarytool | Нотаризация Mac-приложения в Apple | Внутри Xcode.app |
stapler | Прикрепление нотаризационного тикета к бандлу | Внутри Xcode.app |
devicectl | Установка на подключённый iPhone/iPad | Внутри Xcode.app |
codesign | Подпись бинарника | macOS system tools |
Всё это — обычные вызовы командной строки. Xcode.app никогда не запускается; инструменты живут внутри него, но работают автономно.
Быстрый inner loop: сборка без подписи
Для проверки «компилируется ли / проходят ли тесты» подпись вообще не нужна:
xcodebuild \n -scheme MyApp \n -destination 'platform=iOS Simulator,name=iPhone 16' \n CODE_SIGNING_ALLOWED=NO \n build
Флаг CODE_SIGNING_ALLOWED=NO даёт ad-hoc сборку: она компилируется и запускается в симуляторе, но Gatekeeper её отклонит, и entitlements вроде iCloud KVS или App Group не привяжутся. Это быстрый inner loop.
CODE_SIGNING_ALLOWED=NO для ежедневной разработки и тестов. Переключайтесь на полный release.sh только когда готовы шипнуть.release.sh: весь pipeline в одном скрипте
Mac-приложение шипится через один скрипт — scripts/release.sh — который пишется один раз. Он запускает всю цепочку: archive → Developer ID sign → notarize → staple → install в /Applications.
Одна команда делает весь shippable chain: архивирует, экспортирует с Developer ID, нотаризирует, staple-ует, верифицирует, устанавливает. Если любой шаг падает — скрипт останавливается и сообщает, что именно сломалось.
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="MyApp"
SCHEME="MyApp"
ARCHIVE_PATH="build/${APP_NAME}.xcarchive"
EXPORT_PATH="build/export"
NOTARY_PROFILE=${TZED_NOTARY_PROFILE:-"my-notary-profile"}
# 1. Archive
xcodebuild archive \n -scheme "$SCHEME" \n -archivePath "$ARCHIVE_PATH"
# 2. Export with Developer ID
xcodebuild -exportArchive \n -archivePath "$ARCHIVE_PATH" \n -exportPath "$EXPORT_PATH" \n -exportOptionsPlist ExportOptions.plist
# 3. Notarize
xcrun notarytool submit "${EXPORT_PATH}/${APP_NAME}.app" \n --keychain-profile "$NOTARY_PROFILE" \n --wait
# 4. Staple
xcrun stapler staple "${EXPORT_PATH}/${APP_NAME}.app"
# 5. Verify
spctl -a -vvv "${EXPORT_PATH}/${APP_NAME}.app"
# 6. Install
cp -R "${EXPORT_PATH}/${APP_NAME}.app" /Applications/
echo "✅ Shipped!"
Перегрузить профиль нотаризации без правки скрипта можно одной переменной:
TZED_NOTARY_PROFILE=other-profile ./scripts/release.sh
iOS: деплой на устройство
У iOS нет шага нотаризации — это концепция дистрибуции для Mac. Установка сборки на подключённый iPhone делается через xcodebuild плюс devicectl — оба из тулчейна Xcode.
# Сборка для устройства
xcodebuild \n -scheme MyApp \n -destination 'generic/platform=iOS' \n -archivePath build/MyApp.xcarchive \n archive
# Установка на конкретный iPhone через devicectl
xcrun devicectl device install app \n --device 00008120-001234567890 \n build/export/MyApp.ipa
graph TD
A[Написать код в VS Code / Cursor] --> B{Проверка?}
B -->|Быстрая| C[xcodebuild CODE_SIGNING_ALLOWED=NO]
C --> D[Симулятор]
B -->|Финальный релиз| E[./scripts/release.sh]
E --> F[Archive]
F --> G[Developer ID Sign]
G --> H[Notarize]
H --> I[Staple]
I --> J[Install /Applications]
E --> K{iOS?}
K --> L[xcodebuild archive]
L --> M[devicectl install]
Claude Code как движок всего процесса
Именно это и выполняет Claude Code через свой shell. Идея в том, что LLM-агент получает доступ к терминалу и запускает весь pipeline сам — от компиляции до нотаризации — без единого клика в GUI.
Если хотите попробовать самостоятельно: установите Xcode и xcodegen, сделайте credential setup, затем сядьте с Claude и постройте собственные release.sh и CLAUDE.md. Последняя часть — это настоящая работа, занимает час-два максимум. После этого «выпустить новую сборку» становится одним предложением.
После настройки первого приложения Claude Code может скопировать ту же конфигурацию для будущих проектов.
CLAUDE.md — это файл инструкций для агента, который кладётся в корень проекта. В нём описывается структура проекта, команды сборки, путь к скриптам и правила для агента. Claude Code читает его при старте каждой сессии и знает, как именно работать с конкретным репозиторием.Альтернативы: если Xcode не установлен вообще
Описанный выше подход предполагает, что Mac есть, просто Xcode не открывается. Но что если Mac нет совсем?
Третий вариант — полностью пропустить «сырой Mac» и использовать специализированный mobile CI/CD-сервис: Capawesome Cloud, Codemagic или Bitrise. Вместо аренды машины вы описываете сборку в конфиг-файле, сервис поднимает чистое macOS-окружение, собирает, подписывает и отдаёт вам .ipa. Вам не нужно прикасаться к Xcode самостоятельно.
Облачные сервисы сборки — Code2Native, Codemagic, Expo EAS — содержат парки Mac-серверов в дата-центрах. Вы загружаете проект, они компилируют на реальных Mac-машинах и возвращают подписанный бинарник.
| Сценарий | Рекомендация |
|---|---|
| Mac есть, Xcode надоел | xcodebuild + Claude Code + release.sh |
| Mac есть, нужен CI/CD | GitHub Actions (macOS runner) |
| Mac нет, редкие сборки (1–20/мес) | Codemagic / Capawesome Cloud |
| Mac нет, ежедневные сборки | Аренда MacStadium / MacinCloud |
| Нет Mac, кроссплатформа | React Native + Expo EAS Build |
xcodebuild + release.sh + Claude Code на локальном Mac даёт самый чистый и быстрый workflow без подписок на CI/CD.Заключение
Xcode — необходимость инфраструктурная, но не рабочая. Xcode должен быть установлен — никуда от этого не деться, потому что сборка зависит от инструментов внутри Xcode.app. Но открывать его каждый раз — не нужно.
Весь производственный цикл — от компиляции Swift-кода до нотаризированного .app в /Applications или .ipa на iPhone — укладывается в несколько shell-команд. Один раз настроенный release.sh и правильно заполненный CLAUDE.md превращают релиз в буквально одну команду терминала.
Это не хак и не обходной манёвр — это нормальный профессиональный инструментарий, который Apple предоставляет, просто никто особо не рассказывал, что Xcode.app можно держать в доке, но никогда не открывать.