Как собирать и выпускать приложения для Mac и iOS, не открывая Xcode

15.07.2026 · 5 мин

Собираем Apple-приложения без Xcode: терминал как новая IDE

Знаете, что меня всегда раздражало? Xcode. Красивая, мощная, невероятно громоздкая штука. Открываешь её, ждёшь, пока она загрузится, а потом ещё пять минут вспоминаешь, где в этом интерфейсе что находится.

Недавно наткнулся на статью Скотта Уилси (Scott Willsey) — и она перевернула моё представление о сборке Apple-приложений. Оказывается, можно собрать, подписать и отправить в релиз хоть десять приложений, и ни разу не кликнуть на иконку Xcode.

Зачем вообще заморачиваться с CLI

CLI (CLI — интерфейс командной строки, где вы печатаете команды вместо кликов мышью; простыми словами: терминал) — это всегда было про GUI (GUI — графический интерфейс с кнопками и окошками, как привычный интерфейс Xcode). Открой Xcode, создай проект, тыкай по кнопкам. Но что если вам не нужна вся мощь редактора? Что если вы:

GUI — это хорошо для обучения и отладки. Но для продакшена терминал надёжнее: меньше кликов, меньше ошибок, легко повторить.

Автор статьи приводит простой тезис: Xcode.app (папка-приложение в macOS; то же самое что .exe в Windows, только в виде папки) должен быть установлен, но его не нужно открывать. Все инструменты сборки живут внутри приложения и прекрасно работают из командной строки.

Инструменты, которые нам понадобятся

Вот минимальный набор для полноценного релизного цикла:

xcodebuild — основной инструмент сборки. Создаёт архив приложения (.xcarchive) из командной строки.

notarytool — отправляет подписанное приложение в Apple для проверки на малварь. Без нотаризации macOS заблокирует ваше приложение.

stapler — прикрепляет результат нотаризации к приложению. Нужна для того, чтобы Gatekeeper (Gatekeeper — охранник macOS, который проверяет, можно ли запускать скачанные приложения) пропустил ваш .app.

xcode-select — переключает командную строку между разными версиями Xcode. Важно: убедитесь, что система использует именно Xcode.app, а не standalone Command Line Tools.

XcodeGen — генератор проектов. Создаёт файл project.yml, из которого на лету генерирует .xcodeproj. Больше не нужно коммитить в git здоровенные файлы проекта Xcode.

ЖИЗНЕННЫЙ ЦИКЛ APPLE-ПРИЛОЖЕНИЯ
───────────────────────────────
Исходный код ──▶ project.yml ──▶ .xcodeproj
                     │
                     ▼
              xcodebuild archive
                     │
                     ▼
              .xcarchive (архив)
                     │
              ┌──────┴──────┐
              ▼             ▼
        Developer ID    notarytool
         подпись           │
              │           ▼
              │      stapler
              │           │
              └─────┬─────┘
                    ▼
              Готовый .app
              для распространения
От кода до установленного приложения — весь путь

Одноразовая настройка: где придётся потерпеть GUI

Честно предупрежу: есть вещи, которые делаются один раз через графический интерфейс. Без этого никак.

Подготовка Xcode. Устанавливаете приложение, принимаете лицензию и устанавливаете компоненты:

sudo xcodebuild -license accept
sudo xcodebuild -runFirstLaunch

Проверьте, что командная строка указывает на Xcode.app:

xcode-select -p
## Должно быть: /applications/xcode.app/contents/developer

Если видите путь к CommandLineTools — поправьте:

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

Apple Developer аккаунт. Платный аккаунт ($99 в год) обязателен для нотаризации. Без неё macOS Catalina и новее откажутся запускать ваше приложение.

Developer ID Certificate. Создаётся один раз в Xcode (Settings → Accounts → Manage Certificates). Это часть code signing (подпись кода — электронная «печать» приложения, подтверждающая, что его создали вы, а не мошенники). Автор статьи особенно подчёркивает: это сертификат и приватный ключ. Приватный ключ нельзя скачать повторно. Потеряете — придётся отзывать сертификат и создавать новый.

Профиль нотаризации. notarytool требует интерактивного ввода app-specific password:

xcrun notarytool store-credentials App-Name \
  --apple-id "email@example.com" \
  --team-id YOUR-TEAM-ID

Этот пароль генерируется на appleid.apple.com и живёт в вашем keychain (Keychain — защищённое хранилище паролей в macOS; цифровой сейф для ваших паролей и сертификатов). Меняете пароль Apple ID — пароль устаревает, нотаризация падает с загадочной ошибкой 401 (ошибка 401 — «не авторизован»; доступ запрещён, часто из-за устаревшего пароля).

Скрипт деплоя: один раз написал — используешь годами

Вот где начинается магия. Автор создал скрипт `release.sh`, который автоматизирует весь пайплайн:

  1. Собирает архив через xcodebuild
  2. Подписывает Developer ID
  3. Отправляет на нотаризацию
  4. Прикрепляет результат проверки
  5. Устанавливает в /Applications

Основной принцип: один скрипт — один релиз. Написал один раз, потом просто запускаешь.

АВТОМАТИЗАЦИЯ РЕЛИЗА
────────────────────
release.sh ──▶ xcodebuild -archive
                   │
                   ▼
              codesign sign
                   │
                   ▼
              notarytool submit --wait
                   │
                   ▼
              stapler staple
                   │
                   ▼
              cp → /Applications/
                   │
                   ▼
              spctl --verify
Полный цикл от скрипта до установленного приложения

Я оценил подход автора: вместо того чтобы объяснять LLM (LLM — большая языковая модель; нейросеть, которая понимает и генерирует текст, как ChatGPT или Claude), что делать, он просто показал готовый скрипт. Модель дополнила параметры (название схемы, team ID, путь для установки) — и вуаля.

Как это работает на практике

Допустим, вы написали приложение для macOS. Что дальше?

## Генерируем проект
xcodegen generate

## Собираем
xcodebuild -project MyApp.xcodeproj \
  -scheme MyApp-macOS \
  -configuration Release \
  -archivePath build/MyApp.xcarchive \
  archive

## Подписываем и экспортируем
xcodebuild -exportArchive \
  -archivePath build/MyApp.xcarchive \
  -exportPath build \
  -exportOptionsPlist ExportOptions.plist

## Нотаризуем
xcrun notarytool submit build/MyApp.app \
  --keychain-profile "MyApp" \
  --wait

## Прикрепляем результат
xcrun stapler staple build/MyApp.app

Каждая команда возвращает код возврата. Если что-то падает — скрипт останавливается (`set -euo pipefail` (режим строгой обработки ошибок в bash; если любая команда упадёт — скрипт сразу остановится)).

Моя оценка: стоит ли овчинка выделки

Честно? Для большинства разработчиков это overkill. Если вы делаете один-два проекта в год, Xcode вполне сойдёт.

Но! Если вы:

Автор статьи подчёркивает: LLM (типа Claude Code) может написать этот скрипт за вас. Подсунул статью — получил готовый релиз-скрипт. Звучит как идеальное применение AI-ассистентов.

Единственное, что меня напрягает: привязка к app-specific passwords. Они генерируются на сайте Apple, хранятся в ключнике, и живут своей жизнью. Сменили пароль Apple ID — ищете, где что сломалось.

Итог

Xcode — это мощный инструмент. Но для сборки и релизов он не нужен. Терминал, правильные инструменты и один скрипт — всё, что требуется для воспроизводимого процесса.

Если хотите попробовать — начните с XcodeGen. Это самая простая точка входа: создали project.yml, и больше никогда не открываете .xcodeproj руками.

Ссылки

Дмитрий Полухин — продуктовый дизайнер. Пишу про разработку, AI и дизайн интерфейсов. Обо мне, контакты и профили.