Claude CodeでCocoaPodsを移行する — Swift Package Managerへの手順
Podfileの棚卸しとコード修正はClaude Code、project.pbxprojの更新はXcode。CocoaPods trunkの読み取り専用化を控え、Swift Package Managerへ段階的に移す作業分担を示します。
CocoaPodsからSwift Package Manager(SPM)への移行は、Claude Codeに丸ごと任せる作業ではありません。向いているのは、Podfileの棚卸し、コード側の修正、ビルド結果の読み取りです。project.pbxprojの更新とパッケージの追加は、Xcodeの画面で人が行います。この記事では、その分担を最初に決め、設定で固定し、pod単位で小さく移す手順を示します。
なぜ今、CocoaPodsの出口を決めておくのか
CocoaPodsの保守チームは、公式の仕様リポジトリであるtrunkを読み取り専用にする計画を公開しています。ブログによると、2026年12月2日にtrunkは新しいPodspecを受け付けなくなります。11月1日から7日には、事前の試験運用が予定されています。日付は確定ではなく、後ろへずらす余地があると書かれています。
読み取り専用になっても、既存のビルドは止まりません。ブログは「2026年以降もCocoaPodsを使うビルドは壊れない」と述べています。変わるのは、trunk経由の依存が新しいバージョンを受け取れなくなる点です。自前の仕様リポジトリを使う場合や、依存をすべてvendorしている場合は影響を受けにくいとも書かれています。
つまり急いで壊れる話ではなく、止まるのは更新です。セキュリティ修正を取り込めなくなる前に、どのpodをどの順で外すかを決めておく、という位置づけになります。2025年5月には、新規のpodでprepare_commandを使えないようにする変更も入りました。保守側がスクリプト実行まわりを絞っていることが分かります。
Claude Codeとあなたの分担
最初に、誰が何を触るかを表で決めます。
| 作業 | Claude Code | 人(Xcode・ターミナル) |
|---|---|---|
| Podfileの棚卸し | Claude Code各podの取得元を読み、一覧にする | 人(Xcode・ターミナル)一覧を見て移行順を決める |
| SPM対応の有無の調査 | Claude Codeリポジトリを調べ、根拠付きで仕分ける | 人(Xcode・ターミナル)「要確認」の行だけ判断する |
| Swiftコードの修正 | Claude CodeimportやAPI差分を直す | 人(Xcode・ターミナル)差分をレビューする |
| パッケージの追加 | Claude Code手順と要件の下書きを書く | 人(Xcode・ターミナル)Xcodeで実際に追加する |
project.pbxprojの更新 | Claude Code触らない | 人(Xcode・ターミナル)Xcodeの操作に任せる |
| CocoaPodsの切り離し | Claude Code手順を整理する | 人(Xcode・ターミナル)pod deintegrateを実行する |
| ビルドとテスト | Claude Code実行して失敗ログを読む | 人(Xcode・ターミナル)結果を確認する |
project.pbxprojだけは、Claudeに編集させない行にしてください。このファイルはXcodeが管理する生成物に近く、手で書き換えた結果をXcodeが正しく読めるかは差分を見ても判断しづらいためです。Xcodeの操作で更新されるものは、Xcodeに更新させるのが確実です。
ステップ0: project.pbxprojを編集できないように固定する
分担は、口頭の約束だけでは守られません。権限設定で、編集そのものを止めます。
mkdir -p .claude
cat > .claude/settings.json <<'EOF'
{
"permissions": {
"deny": [
"Edit(**/*.pbxproj)"
]
}
}
EOFClaude Codeの権限ルールは、denyが先に評価され、一度denyに当たれば後ろのallowで覆せません。Edit(**/*.pbxproj)のように**で始めると、どの階層にあるファイルにも当たります。
この設定には限界があります。Edit系のdenyが効くのは、組み込みのファイルツールと、Claudeがsedやtee、リダイレクトとして書いたBashコマンドです。PythonやNodeのスクリプトがファイルを直接開いて書き換える場合は対象外です。すべてのプロセスを止めたいときは、サンドボックスの利用が案内されています。
あわせて、分担をCLAUDE.mdにも残しておくと、セッションをまたいでも前提が揃います。
## CocoaPods → SPM 移行のルール
- project.pbxproj と *.xcodeproj 配下は編集しない。変更が必要なときは Xcode での操作手順を書く
- 1回の変更で移すpodは1つ。ビルドとテストが通ってから次へ進む
- SPM対応の判定には、根拠(Package.swift の有無とそのURL)を必ず添える。根拠がなければ「要確認」ステップ1: Podfileを棚卸しする
Podfileの書き方はpodごとにばらつきます。公式のPodfileガイドには、取得元の指定方法として:path(ローカル)、:git、:branch、:tag、:commitが載っています。たとえば次のような行が混在しているのが普通です。
pod 'Alamofire'
pod 'Alamofire', :git => 'https://github.com/Alamofire/Alamofire.git', :tag => '3.1.1'
pod 'Alamofire', :git => 'https://github.com/Alamofire/Alamofire.git', :branch => 'dev'
pod 'Alamofire', :path => '~/Documents/Alamofire'最初のプロンプトは、書き込みを伴わない棚卸しに絞ります。
Podfile を読んで、pod ごとに「名前 / 現在の指定(バージョン・tag・branch・commit・path) / 取得元リポジトリ」の表を作って。まだ何も変更しないで。指定方法の違いは、Xcodeでパッケージを追加するときの要件にそのまま響きます。XcodeのパッケージにはVersion、Branch、Commitの3種類の要件があります。:tagで固定していたpodはVersion、:branchはBranch、:commitはCommitに対応づけて考えられます。:pathのローカル指定は別扱いになるので、表で目立たせておくと後で迷いません。
ステップ2: SPM対応の有無で仕分ける
次は仕分けです。ここで大事なのは、Claudeの記憶ではなく、リポジトリの実物を根拠にさせることです。
棚卸しの各 pod について、取得元リポジトリを調べて Package.swift があるか確認して。結果は「SPM対応 / 非対応 / 要確認」の3つに分け、根拠として見たURLを列に入れて。確認できない行は推測せず「要確認」にして。返ってくる表は、例えば次のような形になります(あくまで形式の例で、実在のpodの判定結果ではありません)。
| pod | 指定 | 判定 | 根拠 |
|---|---|---|---|
| ライブラリA | 指定tag | 判定SPM対応 | 根拠リポジトリ直下にPackage.swiftあり |
| ライブラリB | 指定branch | 判定要確認 | 根拠該当ブランチでPackage.swiftを確認できていない |
| 自社フレームワークC | 指定path | 判定非対応 | 根拠自前のpodspecのみ |
ここから人が判断するのは、「要確認」と「非対応」の行です。非対応のpodを外せない場合は、すべてを一度に移そうとせず、対応済みのものから段階的に進めます。Claude Codeの共通ワークフローでも、リファクタリングは小さく検証可能な単位で進めることが勧められています。
判定を出させるときは、Xcodeのドキュメントにある注意も頭に入れておきます。パッケージは信頼できる作者のものだけを追加すること。バイナリの依存はソースの依存と比べて欠点があること。この2点です。SPM対応の表に「バイナリ配布か、ソース配布か」の列を足しておくと、後の判断が速くなります。
落とし穴
podの名前とimportするモジュール名は同じとは限らない
CocoaPodsで入れたpodと、SPMのパッケージでは、名前の付き方が別の仕組みです。パッケージは、リポジトリ名とは別に「プロダクト」を公開します。Xcodeで追加するときに選ぶのはプロダクトです。Claudeには、Package.swiftを読んで、公開されているプロダクト名を表に足させてください。importの書き換えは、それを確認してから行います。
ステップ3: pod 1つずつ、小さく移す
仕分けが済んだら、対応済みのpodから1つ選びます。1つのpodごとに、次の流れで進めます。
1つのpodを移す流れ
- 1
Claudeがパッケージの要件を書く
そのpodのPackage.swiftを読み、追加するURL、要件の種類、選ぶプロダクト名を一覧にします。
- 2
人がXcodeでパッケージを追加する
File > Add Package Dependencyを開き、URLを入力して要件を選び、対象のターゲットにプロダクトを紐づけます。
- 3
人がPodfileから該当行を外す
Podfileの1行を消し、
pod installをやり直します。 - 4
Claudeがコードを直し、ビルドで確かめる
importを書き換え、ビルドとテストを回し、失敗ログを読んで直します。 - 5
差分を確認してコミットする
1つのpodにつき1コミットにしておくと、問題が出たときに戻す範囲が小さく済みます。
Xcodeでのパッケージ追加は、メニューのFile > Add Package Dependencyから行います。ターゲットのGeneralペインで「Frameworks, Libraries, and Embedded Content」の+ボタンから開く方法もあります。要件は、Versionを選ぶのが標準の勧めです。Commitで固定する方法は例外的な場合にのみ使うものとされ、更新を受け取れなくなります。
Claudeに渡すプロンプトは、役割を絞って短くします。
Xcode でパッケージ「ライブラリA」を追加済み。Podfile から該当行を外して pod install も済んでいる。import 文をパッケージのプロダクト名に合わせて直し、ビルドとテストを実行して。失敗したらログを読んで原因を説明するところまでにして、project.pbxproj には触らないで。ビルドの確認は、自分のワークスペースとスキームに置き換えて実行させます。
xcodebuild -workspace App.xcworkspace -scheme App \
-destination 'platform=iOS Simulator,name=iPhone 16' buildClaudeがログを読む役に向いているのは、エラーの量が多く、手で追うと時間がかかるためです。ただし、ログの原因分析は仮説にとどまります。「モジュールが見つからない」とあっても、原因はimport名の誤りか、ターゲットへの紐づけ漏れかで変わります。後者はXcode側の設定なので、人が画面で確かめる行になります。
ステップ4: CocoaPodsを切り離す
最後のpodを外し終えたら、プロジェクトからCocoaPodsの痕跡を取り除きます。cocoapods-deintegrateというプラグインのpod deintegrateは、Xcodeプロジェクトとの統合を解除するコマンドです。READMEは、実行前にプロジェクトのバックアップを取っておくよう求めています。
git status # 未コミットの変更がないことを確認
gem install cocoapods-deintegrate
pod deintegrateREADMEの出力例によると、このコマンドはPods関連のビルドフェーズやファイル参照を取り除き、プロジェクトからPodsの痕跡を消します。一方で、Podsプロジェクトを参照しているワークスペースは残ります。ワークスペースの扱いは、移行後の運用に合わせて人が決めます。
このコマンドはproject.pbxprojを書き換える操作です。Claudeに実行させず、自分のターミナルで走らせてください。実行後はgit diffで差分を眺め、その差分をClaudeに要約させると、変更の意味を読み取りやすくなります。Podfile、Podfile.lock、Podsディレクトリの扱いは、deintegrateの後に、CIの設定とあわせて削除するか残すかを決めます。
つまずきを減らす運用メモ
移行の途中で起きやすいことを、先に並べておきます。
- CIが古い手順のまま: CIがPodfileを前提にしていると、移行途中でビルドが落ちます。Podfileを消すコミットと同じタイミングで、CIの設定も更新します
- 要確認の行を放置する: 判定の根拠が空の行は、そのまま次のpodに進めないでください。根拠のないままClaudeに移行コードを書かせると、存在しないプロダクト名を
importする可能性があります - 1回の変更に複数podを混ぜる: ビルドが落ちたとき、どのpodが原因か切り分けられません
- pbxprojの差分が大きい: Xcodeの操作で更新された
project.pbxprojは、行数が多く見えます。内容の判断はXcodeの画面側で行い、差分は「追加したパッケージが入っているか」の確認にとどめます
SwiftUIのアプリ全体の作り方はClaude CodeでSwiftUI iOSアプリを開発する手順に、XcodeとClaudeの接続方法はXcodeでClaudeを使う方法にあります。同じ「移行ツールを実行したあとの手直しをClaudeに任せる」形の事例としては、Claude CodeでTailwind v4へ移行するが参考になります。大規模な移行をより大きな単位で回した例は、BlockがClaude Fable 5で数千PRのコード移行を回す方法で扱っています。
まとめ
この移行でClaude Codeに任せる価値が大きいのは、Podfileの読み解きと根拠付きの仕分け、そしてビルド失敗の読み取りです。任せない領域はproject.pbxprojで、権限のEditdenyとCLAUDE.mdの両方で固定できます。pod 1つにつき1コミットで進めれば、CocoaPods trunkが読み取り専用になる日までに、どこまで移せたかも数えやすくなります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。