2 ポイント 投稿者 GN⁺ 4 시간 전 | 1件のコメント | WhatsAppで共有
  • 初期のAppleアカウント・証明書設定を終えれば、Xcode.app内のCLIツールだけでMacとiOSアプリのビルド、署名、配布を自動化できる
  • project.ymlからXcodeGen.xcodeprojを再生成し、xcodebuildnotarytoolstaplerdevicectlでプロジェクト生成からMacの公証、iPhoneへのインストールまで処理する
  • Mac配布はscripts/release.shひとつでアーカイブ、Developer ID署名、公証、チケットのステープル、Gatekeeper検証、/Applicationsへのインストールを順に実行し、失敗時は即座に中断する
  • 高速なコンパイルとテストにはCODE_SIGNING_ALLOWED=NOを使えるが、この一時署名ビルドはGatekeeperを通過できず、iCloud KVSやApp Group権限も実際のチームIDに結び付かない
  • 署名用秘密鍵と公証用パスワードはログインキーチェーンに保管し、CLAUDE.mdまたはAGENTS.mdにコマンドと配布ルールを記録しておくと、Claude Codeのようなエージェントがワークフロー全体を繰り返し実行できる

Xcode GUIなしで処理できる範囲

  • Xcode自体はインストールする必要があるが、起動する必要はなく、xcodebuildnotarytoolstaplerdevicectlはいずれもXcode.app内のシェルツールとして単独で実行される
  • Apple IDログイン、Developer ID証明書の作成、公証用パスワードの保存といった初期設定にはGUIまたは対話型ターミナルが必要
  • 初期設定を終えれば、プロジェクト生成、ビルド、アーカイブ、署名済みアプリのエクスポート、公証、検証、インストール、実機iPhoneへの配布までマウスなしで処理できる
  • 設定やスクリプト作成で行き詰まった場合は、Claude Codeまたは他のLLMコーディングツールに作業要件とプロジェクト別の値を渡してワークフローを作成できる

Xcodeツールチェーン全体を選択する

  • まずxcode-select -pの結果が/Applications/Xcode.app/Contents/Developerか確認する必要がある
  • スタンドアロンのCommand Line Toolsが選択されている場合は、次のコマンドでXcodeツールチェーン全体を指定する
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
  • xcode-select --installでインストールされる/Library/Developer/CommandLineToolsにはclanggitは含まれるが、iOS SDK、notarytooldevicectlなどアプリ開発ツール一式は含まれない
  • Xcodeがすでにインストールされているなら、別途Command Line Toolsパッケージは不要
  • ライセンス同意と追加コンポーネントのインストールもCLIで処理できる
sudo xcodebuild -license accept
sudo xcodebuild -runFirstLaunch

XcodeGenでプロジェクトを再現する

  • XcodeGenはXcodeプロジェクト設定をYAMLで管理し、ビルドのたびに.xcodeprojを再生成する
  • GitHubからダウンロードするか、Homebrewでインストールできる
brew install xcodegen
  • .xcodeprojはmacOSではファイルのように見えるフォルダであり、Xcodeが内部ファイルや参照を継続的に変更するため、Gitリポジトリで競合や不要な変更が発生することがある
  • project.ymlだけをGitにコミットし、生成された.xcodeprojは無視すれば、プロジェクト設定を再現可能な状態に保てる
xcodegen generate

Apple開発者アカウントと証明書の設定

  • XcodeのSettings → AccountsでApple IDを追加する必要がある
  • アプリの配布と公証には有料のApple Developerアカウントが必要
  • Settings → Accounts → Apple ID → Manage Certificates… → + → Developer ID Applicationで配布用証明書を作成する
  • Apple DevelopmentDeveloper ID Applicationは用途が異なる
    • Apple Developmentは自分のデバイスで実行したり、iPhoneに転送してローカルデバッグしたりする際に使う
    • Developer ID Applicationは、他人のMacでもGatekeeperを通過する公証済み.appを配布する際に必要
  • Developer ID Application証明書を作成すると、証明書と対応する秘密鍵がログインキーチェーンにインストールされる
  • 実際の署名には秘密鍵が使われ、再ダウンロードはできないため、削除せずキーチェーンをバックアップする必要がある

公証資格情報をキーチェーンに保存する

  • Macアプリの公証は、署名済みアプリをAppleにアップロードしてマルウェア検査を受けるプロセス
  • notarytoolはキーチェーンに保存されたプロファイルで認証し、プロファイルを初めて作成するときはアプリ用パスワードを対話的に入力する必要がある
xcrun notarytool store-credentials App-Name \
  --apple-id "you@example.com" \
  --team-id YOUR-TEAM-ID
  • 公証プロファイルは他のアプリのものを流用せず、アプリ名に合わせて作成することで、別環境でひそかに失敗する状況を避けられる
  • アプリ用パスワードはApple IDのパスワードとは別物で、Apple IDサイトSign-In & Security → App-Specific Passwordsで作成する
  • Apple IDのパスワードを変更すると、アプリ用パスワードが別途警告なしに期限切れになることがある
    • 公証中に401 invalid credentialsが発生したら、設定全体を疑う前にアプリ用パスワードの期限切れをまず確認する必要がある
  • プロファイルが保存されているかは次のコマンドで検証する
xcrun notarytool history --keychain-profile App-Name
  • アプリ用パスワードをClaude Codeがアクセスできる1Passwordの保管庫に保存すれば、新しいアプリの公証プロファイル作成もエージェントに任せられる
  • --passwordでパスワード入力まで自動化できるが、シェル履歴にパスワードが残る可能性があるため、一度手動で入力してからキーチェーンや1Passwordに保管する方式を使う

ローカル署名設定と秘密情報の分離

  • 実際の署名に必要なチームIDとバンドル接頭辞はLocal.xcconfigに保存する
cp Local.xcconfig.example Local.xcconfig
BUNDLE_PREFIX     = your.real.prefix
DEVELOPMENT_TEAM  = YOUR-TEAM-ID
  • Local.xcconfig.gitignoreに追加し、プロジェクト別のローカル設定がリポジトリに入らないようにする
  • 署名用秘密鍵はログインキーチェーンに、公証用アプリ用パスワードはnotarytoolのキーチェーンプロファイルに残るため、秘密情報がGitに記録されない

release.shでMac配布を自動化する

  • リポジトリのscripts/release.shが、Macアプリの配布パイプライン全体を1つのコマンドで実行する
./scripts/release.sh
  • スクリプトは次の順序で動作する

    1. xcodegenと公証プロファイルが存在するか事前確認
    2. xcodegen generateでプロジェクトを再生成
    3. xcodebuild archiveでReleaseアーカイブを作成
    4. ExportOptions.plistxcodebuild -exportArchiveでDeveloper ID署名済みアプリをエクスポート
    5. アプリをZIPにまとめ、notarytool submit --waitでAppleに提出
    6. stapler stapleで公証チケットを添付
    7. spctlでGatekeeperによる許可可否を検証
    8. 既存プロセスを終了し、アプリを/Applicationsにコピー
    9. lsregisterでインストール済みアプリを登録
    10. インストール済みバンドルのチケットとGatekeeper状態を再検証
  • モデルが一般的な配布手順を知っていても、スキーム名、チームID、公証プロファイル名、インストール先のようなプロジェクト固有情報はユーザーが提供する必要がある

  • 最初のスクリプトが失敗した場合は、実行結果を基に修正する反復プロセスが必要だが、ワークフローが安定した後は追加修正なしで配布コマンドだけを実行できる

  • 失敗と不完全な配布を防ぐ

    • set -euo pipefailはコマンドが1つでも失敗するとスクリプトを即座に中断し、不完全な状態を成功として扱わないようにする
    • cd "$(dirname "$0")/.."はスクリプトをどのディレクトリから呼び出してもリポジトリルートへ移動させる
    • 事前検査ブロックは時間のかかるアーカイブの前にxcodegenと公証プロファイルを確認する
    • エクスポートしたアプリだけでなく/Applicationsにコピーされたアプリも再検査し、コピー過程でバンドルが破損する場合を検出する
    • 別の公証プロファイルが必要なら環境変数で上書きできる
    TZED_NOTARY_PROFILE=<name> ./scripts/release.sh
    

エージェントに配布ルールを伝える

  • release.shが1つのコマンドで配布を実行するなら、CLAUDE.mdAGENTS.mdは、エージェントがセッションごとに別途指示されなくてもそのコマンドを使うようにする
  • 文書にはプロジェクト再生成、単体テスト、高速macOSビルド、実際の配布コマンドを記録する
xcodegen generate
swift test

xcodebuild -project YOUR-APP-NAME.xcodeproj \
  -scheme YOUR-APP-NAME-macOS \
  -destination 'platform=macOS' \
  CODE_SIGNING_ALLOWED=NO build

./scripts/release.sh
  • 2つのビルド経路の違いも文書に明記する必要がある
    • CODE_SIGNING_ALLOWED=NOビルドはCIと高速なローカル確認に適している
    • 実際のメニューバーアプリ配布、隔離属性の通過、iCloud同期には、Developer ID署名と公証を実行するrelease.shが必要
  • あるアプリで作った方式を別のリポジトリで参照するよう指示すれば、Claude Codeが以後のアプリにも同じ設定を複製できる

高速な無署名ビルドとテスト

  • Swift Package Managerベースの単体テストはXcodeビルドなしで実行する
swift test
  • macOSアプリの高速なコンパイル確認は、署名をオフにした状態で行う
xcodebuild -project TZed.xcodeproj \
  -scheme TZed-macOS \
  -destination 'platform=macOS' \
  CODE_SIGNING_ALLOWED=NO build
  • iOSアプリとウィジェット拡張のシミュレータービルドも同じ方法で実行できる
xcodebuild -project TZed.xcodeproj \
  -scheme TZed-iOS \
  -destination 'generic/platform=iOS Simulator' \
  CODE_SIGNING_ALLOWED=NO build
  • CODE_SIGNING_ALLOWED=NOで作成した一時署名ビルドは、コンパイルとシミュレーター実行に使える
  • このビルドはGatekeeperに拒否され、チーム接頭辞がないためiCloud KVSやApp Groupなどの権限が結び付かず、配布用には使えない

実機iPhoneへヘッドレス配布する

  • iOSデバイスへの配布にはMacアプリと同じ公証ステップはなく、xcodebuilddevicectlを使う
  • 実機用アプリはApple Development証明書と開発用プロビジョニングプロファイルでビルドし署名する
xcodebuild -project TZed.xcodeproj \
  -scheme TZed-iOS \
  -destination 'generic/platform=iOS' \
  -allowProvisioningUpdates \
  -derivedDataPath build/ios \
  archive -archivePath build/TZed-iOS.xcarchive
  • 生成された.appは、接続されたデバイスのUDIDを指定してインストールする
xcrun devicectl device install app \
  --device <DEVICE-UDID> build/ios/…/TZed.app
  • devicectl list devicesは、接続されペアリング済みのデバイスとUDIDを表示する
  • -allowProvisioningUpdatesを指定すると、必要な開発用プロビジョニングプロファイルを取得する

GUIなしでコード署名が機能する仕組み

  • Developer ID Application証明書を作成すると、Appleは証明書を発行し、Macは対応する秘密鍵を生成して、どちらもログインキーチェーンに保存する

  • xcodebuildが呼び出すcodesignは秘密鍵でバイナリに署名し、Appleルート証明書につながる証明書をアプリに含めて、署名者を検証できるようにする

  • signingStyle: automaticを使うと、xcodebuildがチームIDに合う証明書を選択し、必要なプロビジョニングプロファイルをAppleから取得する

  • したがって、プロビジョニングプロファイルをリポジトリにコミットする必要はない

  • 権限、公証、ステープル

    • 各ターゲットの.entitlementsファイルには、サンドボックス、ネットワーククライアント、iCloud KVS、App Groupなどの権限が入っている
    • 権限は実際のチームIDで署名するときに結び付くため、一時署名ビルドではiCloudとApp Groupは正常に動作しない
    • 署名と公証は別のステップ
    • 署名は誰がアプリを作ったかを証明する
    • 公証はAppleが署名済みアプリをマルウェア検査した後、チケットを発行する手続き
    • ステープルはそのチケットをアプリに添付し、オフラインでもGatekeeperが信頼できるようにする
    • 隠れたUIを使うメニューバーアプリであるLSUIElementアプリでは、公証がXProtectの検出を避けるために必要
  • 手動検証コマンド

    codesign -dv --verbose=4 /Applications/TZed.app
    spctl -a -vvv -t exec /Applications/TZed.app
    stapler validate /Applications/TZed.app
    
    • codesignは署名者と証明書を確認する
    • spctlはGatekeeperが実行を許可するか検査する
    • stapler validateは公証チケットが添付されているか検証する

エージェントが実行する標準ツール

  • 別途ビルド用MCPサーバーや専用プラグインは不要で、Claude Codeは非対話型シェルで標準CLIを実行する
  • 使用するツールはxcodebuildxcrun notarytoolxcrun staplerspctlcodesigndevicectlxcodegenswift
  • CLAUDE.mdは公証プロファイルの命名規則、高速ビルドと実際の配布の違い、配布時にはrelease.shを使うべきというルールをエージェントに伝える
  • 最初のnotarytool store-credentialsだけを対話型ステップとして残し、その後の過程はすべて自動化できる

Xcode GUI作業をCLIに置き換える

  • Xcodeが管理する.xcodeproj生成はproject.ymlxcodegen generateで置き換える
  • ⌘BまたはRunボタンはxcodebuild … buildに対応する
  • Product → Archivexcodebuild … archiveで処理する
  • Organizerのアプリ配布はxcodebuild -exportArchiveで代替できる
  • Organizerアップロードはxcrun notarytool submit --waitで行う
  • 自動チケット添付にはxcrun stapler stapleを使う
  • /Applicationsへドラッグ&ドロップするインストール手順はcp -Rlsregisterで処理する
  • 実機iPhoneでのRun動作はxcodebuild archivedevicectl device installで置き換える
  • XcodeとXcodeGenのインストール、最初の資格情報設定、release.shCLAUDE.mdの作成まで終えれば、以後の新規ビルド配布は一文または1コマンドで実行できる

1件のコメント

 
GN⁺ 4 시간 전
Hacker Newsの意見
  • サンドボックスでは解決できないことが多いため、AIエージェントをMac上で直接実行しているが、xAIがSSHキーまで含むホームディレクトリをアップロードした事件を見て、この選択を真剣に見直すようになった
    マシン自体が壊れることはそれほど心配していない。たいていはバックアップしているかGitにコミットしてあり、数時間あれば復旧できるからだ。だが、.ssh ディレクトリがAIエージェントに送信されるのは絶対に避けたいので、プロンプトで防ごうとするのではなく、システムレベルで遮断すべきだ。別ユーザーを作成し、ホームディレクトリに 700 権限を適用する方法を検討している。セキュリティは1990年代に後退したようだが、その代償として前例のない速さで仕事を終えられるという二面性がある。自分もこの危険なやり方を使っているので、他人を非難するつもりはない

    • 必ずしもホストMac上で実行する必要はない。最近のMacは性能低下がほとんどない仮想化をサポートしているため、同じアーキテクチャのmacOSやLinux仮想マシンを開発に簡単に使える
      パッケージ化された解決策として、オープンソースのTart https://tart.run/ や VirtualBuddy https://github.com/insidegui/VirtualBuddy を使えるし、OS API https://developer.apple.com/documentation/virtualization をラップしたツールを自分でバイブコーディングしてもよい。最近は Appleコンテナ https://github.com/apple/container も登場した
    • Claudeを agent という別ユーザーで実行するラッパーツールを作っている。1年前はOAuthとキーチェーンの問題で失敗したが、最近は CLAUDE_CODE_OAUTH_TOKEN を使えるとClaudeから案内され、実装に成功した
      ACLで権限を設定する補助ツールが必要だが、現在はmacOSで動作する。リスクは標準のClaudeサンドボックスと完全なコンテナ・マシン分離の中間くらいだ。Claude自体のサンドボックスが改善されるにつれて、この二重防御プロジェクトの投資対効果を疑っていたが、ホームディレクトリ流出の可能性を見ると、続ける理由は十分にある。まだオープンソースとして公開していないが、興味のある人とは話すつもりだ
    • AIをヘッドレスDockerコンテナで実行し、Gitにだけアクセスさせてコードのみを貢献させている。シークレットが必要ならリポジトリに置いたDockerコンテナを提供し、インフラが必要ならJiraチケットを作らせるというワークフローだ
    • Xcodeを開かずにバンドル識別子を登録する作業はどう処理しているのか気になる
  • 興味本位でLinuxだけを使ってiOSアプリをビルドしてテストしているが、驚くほど簡単で https://github.com/xtool-org/xtool がとてもうまく動く
    TestFlightやApp Storeに上げる必要がなく、LinuxでもUSB経由でiPhoneに直接インストールできる。自信がないなら、コーディングエージェントにHello WorldのiOSアプリを作ってアップロードしてくれと頼めば、簡単に始められる

    • WindowsのWSLでLinuxを実行している点を除けば、同じやり方で作業している。SideloadlyでIPAをスマホに転送しており、問題なく動作する
    • USBでアプリを転送した後も、iPhoneを接続したままにしておく必要があるのか?
    • コーディングエージェントたちはxtoolをすでに知っているのか?
  • 私のオープンソースプロジェクト Axiom は、コーディング実行ツールがAppleオペレーティングシステム向けの開発作業を効果的に行えるよう支援する
    さまざまな技術やエージェントに加え、LLM向けツールである xclogxcprofxcsymxcui も含んでいる。これらは必要な機能をトークン効率よく公開し、Axiom外の技術やエージェントにも有用だ。Axiom: https://charleswiltgen.github.io/Axiom/、CLIツール: https://charleswiltgen.github.io/Axiom/tools/

    • Kotlin Multiplatformのコードベースでもきちんと動くのだろうか? Swiftのネイティブコードはあるが、一部のロジックを共有する際の性能や挙動が気になる
    • iOSアプリ用ツールの次の開拓地はセルフホスト可能なLinuxビルドサーバーだと思うが、これについてどう考えるか知りたい
    • Flutterでも動作するのか?
  • 「Claude Codeに、Xcodeを開かずにアーカイブ、Developer ID署名、公証、ステープリング、/Applications へのインストールまで行い、どの段階でも失敗したら明確に停止するスクリプトを作らせた」という文を読むと妙な気分になる。いま読んでいるこの文章自体も、Claudeが私たちに語りかけているように感じるからだ
    記事のほぼすべての段階で、「Claude Codeや好みのLLMコーディングツールにこの記事を見せて、あとは任せればいい」「分からなければLLMに聞いて設定を手伝ってもらえ」「LLMを使う目的は、やりたくない手作業を避けることだ」「ワークフローを作ってもらえ」といった、LLMにもう一度聞けという案内が繰り返されるのも奇妙に感じる

    • この記事を書いたのはClaudeではなく、私自身だ
    • Claudeが書いたウェブサイトをClaudeに見せて、Claudeにビルド環境を作らせるという循環構造のように見える
    • 記事中のミスを見てAIが書いたものではないと思っていたが、今ではAIがわざとミスをしているのかもしれないと思えてきた
  • 1年以上エージェントとしてMacとiOSアプリを開発してきた立場からすると、この記事は良くない助言だと思う。特に優れた Xcode MCPはXcodeが起動中である必要がある
    MCPツールを使えば、xcodebuildよりはるかに高速かつ簡潔にさまざまな機能へアクセスでき、Xcodeを閉じると不可能な #Preview の生成とレンダリングも可能だ。Xcode 27のMCPと内蔵エージェントは、DeviceHubを通じてシミュレーターも非常によく制御する。DeviceHubはSimulator.appを置き換えるもので、axe のようなツールでアクセシビリティAPIを裏技的に操作しなくても、エージェントが理解して扱えるようだ
    Xcode MCPが完璧というわけではない。エージェントを実行するたびに権限ダイアログが出る問題は、Keyboard Maestroで自動承認することで回避した。それでもXcode 27は Xcodeバイブコーディングの使い勝手 を大きく改善した。今ではMCPを個別に扱わず、Xcode自体のエージェントUIでCodexを動かしているが、この実行環境のほうがモデルをうまく誘導し、利用可能なツールを活用させてくれる。結果として、最も重要なより速いフィードバックと、より堅牢な検証を得られる

    • Xcode MCPをプロキシしつつダイアログをクリックし、接続も復旧してくれる Xcode-mcp-proxy がある。macOSアプリのテストには Peekaboo を使っているのか、それとも通常のスクリーンショット自動化を使っているのか気になる
    • Sentryの Xcode MCP も試してみる価値がある。はるかに包括的で、Xcodeを起動しておく必要もない
  • iOSとAndroidのIDEをできるだけ触りたくないなら、React NativeとExpo も良い選択だ
    XcodeとAndroid Studioはデバイスシミュレーターをインストールするときだけ使い、ストア配布まで残りはExpoのツールチェーンが処理する。XcodeをインストールできないWindowsでも、Expoの管理型アプリを使えばiOSアプリをiPhoneで直接実行できる。RNとExpoベースの出発点としては、よくメンテナンスされている Ignite が素晴らしい: https://github.com/infinitered/ignite

  • 厳密に言えば、依然として Xcodeを使っている のだ。Xcodeは概して安定した複数のシステムレベルUNIXユーティリティやアプリを包んだ、非常にバグの多いGUIだ
    CLIでアプリをリリースするやり方は昔からの慣行で、少なくとも自分が最初のXcodeアプリをリリースした2012年から可能だった

    • その事実は知っている。ただ、Xcodeを使う主体が自分ではなく Claude だというのが核心だ
    • Xcodeを開いて見たあとの参入障壁のせいで、macOS向けのプログラムを作ってみようとすら思わなかった
  • 少なくとも一部のデバッグでは、誰もが Xcodeを使わざるを得ない
    ビルドはエージェントがすでにコマンドラインで大半を処理でき、状況ごとに明示的な指示を与えればより速くビルドできる。Xcodeのファイルシステム同期グループを使うなら、XcodeGenは不要な付帯作業かもしれない
    iOSでは、エージェントに App Store Connect機能 を追加することを最も勧めたい: https://github.com/rorkai/App-Store-Connect-CLI。そうすればXcodeを常時起動しておく必要がないだけでなく、MacBookの近くにいる必要もない。iPhoneでCodexから変更したあと、asc にビルドとTestFlightへのアップロードを指示し、新バージョンをダウンロードして実行しながら反復すればよい

    • エージェントでiOSアプリ全体をほぼ完成させ、App Store公開とソーシャルでの宣伝 までエージェントが処理した。Xcodeはデバイス上でビルドを事前確認し、次のプロンプトの方向性を決めるときにだけ使った
  • 予算が足りずMacを買えない開発者が、事実上 iOS開発から排除 されている現実がずっと気になっている。Apple製品の価格が上がるたび、開発に参加できない人がさらに増える

    • 技術にアクセスできない人が出るのは残念だが、最近のAppleは同等かそれ以下のスペックの競合製品と比べて、安価なデバイスも提供している。適切なメモリを積んだ Apple Silicon MacBook Air がその一例だ
  • アプリをバイブコーディングするなら、長期的には Expo のほうがより良い選択だった。Reactベースなので、LLMの学習データにはSwiftよりReactコードのほうがはるかに多く、生成されるコードの品質も高い
    すべての作業をコマンドラインで実行でき、Webビューなのでデバッグもしやすい。ネイティブiOSアプリとしてコンパイルしたあとは、ほかのネイティブアプリと同じような感触になる。ExpoとFastlane を組み合わせればiOS提出と配布を完全に自動化でき、コマンド一つでApp Storeに新バージョンを上げられる

    • 新しいアプリを作るとき、アプリ自体を登録するような 自動化できない段階 もあるのではないか?
    • そのExpoとは https://expo.dev/ のことか? 現在アクセスすると、「コードが壊れており、確認が必要なエラーが発生した」という案内が表示される