Xcode
イベント
該当するコンテンツが見つかりませんでした
マガジン
該当するコンテンツが見つかりませんでした
技術ブログ
本記事は 2026 年 8 月 3 日に公開された Clare Liguori、Romain Dura、Al Harris、Richard Threlkeld による “ One agent, every surface: how we built the Kiro agent harness ” を翻訳したものです。 Kiro の開発初期、私たちは開発者の 1 日のなかでエージェント駆動の開発がどのように感じられるべきかを議論し始めました。繰り返し立ち返ったのは、セッションがラップトップとクラウドサンドボックスの間を摩擦なく行き来する姿でした。1 日の終わりにラップトップを閉じても、Kiro セッションはクラウドで動き続けます。コーヒーを取りに行く合間にスマートフォンから状況を確認できます。翌朝、Kiro IDE を開いて中断したところから作業を再開します。 Web 版 Kiro でプロジェクトを開始し、Kiro IDE でコンテキストを追加し、既にテストとイテレーションを進めているターミナルでは Kiro CLI を使い続け、Slack から進捗を確認します。エージェント駆動の開発とは、作業するあらゆるクライアントを横断する 1 つの連続した会話であるべきです。 今年の初め、私たちはエージェントのアーキテクチャがこのビジョンの実現を妨げていることに気づきました。当時、Kiro IDE、CLI、Web の各クライアントは、それぞれ独自のセッションフォーマット、ツールセット、設定モデルを持つ専用のエージェントを実行していました。セッションと環境の間を容易に移動するには、どのクライアントを使っていても、どこで動作していても同じように振る舞う単一のエージェントが必要です。クライアント専用のエージェントアーキテクチャでは、エージェント同士が十分な共通基盤を持っていなかったため、あるクライアントで開始したセッションを別のクライアントに移すことができませんでした。本記事では、3 つのエージェントのコードベースを 1 つの Kiro エージェントハーネスに統合した過程 (もちろん Kiro 自身を使って構築しました) と、私たちのビジョンを実現可能にしたアーキテクチャ上の決定について解説します。 分岐していった 3 つのハーネス Kiro を作り始めた当初、私たちはスピードと実験を優先しました。各クライアントチームが独自のエージェントハーネスを作ることを推奨しました。エージェントハーネスとは、エージェントループ、ツール実行、サブエージェントへの委譲、セッション管理、設定のロード、モデルとの通信を管理するオーケストレーション層のことです。IDE チームは Code OSS の拡張モデルに合わせて TypeScript で、CLI チームはパフォーマンスを重視して Rust で、Web チームは最新のエージェント研究に近い場所に居るために Python で、それぞれ独自に構築しました。 ハーネスを分けたことで各チームは独立して素早くリリースし、イテレーションできましたが、同時にそれぞれのチームが異なる選択をすることも意味しました。セッションストレージはクライアントごとに動作が異なりました。権限システムは独立して設計されており、互換性のない構文を使っていました。CLI は正規表現ベースの allowedCommands / deniedCommands を使い、IDE は trustedCommands にプレフィックスマッチを、denylist にはサブストリングマッチを使っていました。コンパクション戦略も分岐しました。サブエージェントのコンテキスト共有も異なるモデルに従っていました。カスタムエージェントもクライアントごとに動作が違いました。機能セットも分裂しました。仕様駆動開発と powers は IDE のみで動作し、プランモードとコードインテリジェンスは CLI のみで動作していました。 実装コストは時間とともに複利で膨らみました。新しい機能は 3 回作って 3 回保守する必要があり、その結果としてエージェントの挙動がわずかに異なることもありました。バグも 3 回修正する必要がありました。ユーザーはどのクライアントを選ぶかによって不整合を体験することになりました。セッションがクライアントとコンピュートを横断して移動するという私たちのビジョンは、共有のセッションフォーマット、共有のツールセット、共有の設定モデルが存在しないためアーキテクチャ的に不可能でした。各チームの独立性と個別のスピードを維持するために、クライアント間でエージェントの振る舞いに関する契約を合意し、3 つのハーネスそれぞれで実装するという案も検討しました。しかしインターフェースの整合を取ることも、新機能ごとに増えていく調整コストを生みます。新機能ごとに仕様書、3 つの実装、そして同一の振る舞いを継続的に検証する作業が必要になるのです。 転機となったのは、Web 版 Kiro のパブリックローンチの準備を進めていたときでした。Web 版 Kiro を独自のエージェントとともにローンチし、この複利的な実装コストを払い続けるのではなく、各チームが学んだベストな知見を組み合わせた単一のエージェントハーネスを構築することを決めました。単一のハーネスであればチーム間の重複がなくなり、すべての労力を 1 箇所に集中投資できます。 Kiro エージェントハーネスのアーキテクチャ 私たちが早い段階で下した重要なアーキテクチャ判断は、ハーネスを各クライアントにコンパイルして組み込むライブラリではなく、独立したサーバープロセスとして構築することでした。過去の試みから、共有ライブラリでは十分に強い境界を強制できないことがわかっていました。クライアントコードは公開を意図していない内部メソッドを呼び出し始めるか、ライブラリの上に独自のエージェントロジックを重ねてしまいます。そうなれば実装は再び分岐していきます。独立したプロセスであれば、この分離が現実のものになります。ハーネスとクライアントは同じ言語やランタイムを共有する必要がないため、各クライアントは自分のプラットフォームに適したスタックのまま留まれます。 これにより、3 つの密結合したクライアントとエージェントのペアではなく、 ┌────────────┐ ┌────────────────────────────────┐ │ Kiro IDE ├──────│ IDE agent (TypeScript) │ └────────────┘ └────────────────────────────────┘ ┌────────────┐ ┌────────────────────────────────┐ │ Kiro CLI ├──────│ CLI agent (Rust) │ └────────────┘ └────────────────────────────────┘ ┌────────────┐ ┌────────────────────────────────┐ │ Kiro Web ├──────│ Web agent (Python) │ └────────────┘ └────────────────────────────────┘ クライアントと単一のエージェントハーネスとの間にきれいな分離ができました。 ┌─────────────────────────┐ ┌─────────────────────────────────┐ │ Clients │ │ Kiro agent harness │ │ │ │ │ │ UX and presentation │ │ Agent loop │ │ User interaction │───protocol───│ Tools and sub-agents │ │ Platform-native tools │ │ Session state │ │ (optional overrides) │ │ MCP client │ │ │ │ Configuration and steering │ │ │ │ Permissions │ │ │ │ Telemetry │ └─────────────────────────┘ └─────────────────────────────────┘ Kiro エージェントハーネスはコードベースの隣で動作する軽量なプロセスで、高速に起動し、エージェント側のすべてを所有します。クライアントはユーザーがエージェントとどのようにやり取りするか、エージェントの作業をどのように提示するかを所有します。この境界を越える唯一の方法は、定義されたプロトコルインターフェースです。コンパイルされて組み込まれるライブラリではなく独立したプロセスであるため、あらゆるコンピュート上で動作できます。同じハーネスがラップトップ上でも、クラウド上の VM 内でも、クライアントに意識させることなく起動できます。 サーバーとクライアントの間に明確なインターフェースがあるということは、エージェントのコードがクライアントとは独立して進化することを意味します。ハーネスの変更がプロトコルインターフェースに影響を与えない場合 (たとえば新しいツールの追加、プランニングの改善、エージェントループのチューニング)、クライアント側の変更ゼロですぐにすべてのクライアントにリリースできます。たとえば最近、カスタムエージェントのライブリロード機能を追加しました。セッション中に .kiro/agents/ のファイルを編集すると、ハーネスがすぐに検知し、利用可能なコマンドをクライアントに再度通知します。利用可能なコマンドの通知タイプはすでにプロトコルに存在していたため、クライアントの変更は不要でした。どのクライアントも追加の変更なしにこの機能を手に入れられたのです。 サポート対象のクライアントが多様なため、このハーネスは画一的な設計ではありません。クライアントごとに機能が異なり、一部の操作はクライアントネイティブの機能を使ってクライアント層で実装するほうが理にかなっています。クライアントは独自のツールを提供して組み込みツールを抑制でき、自分のフォームファクター (form factor) に合ったものを使えます。たとえば IDE はファイル操作に Code OSS の API を使い、ファイルシステム上で直接動作するハーネスの組み込みツールではなく、独自のファイル読み書きツールを提供しています。エージェントがこれらのクライアント提供ツールのいずれかを実行する必要があるときは、クライアントに通知し、クライアントがツールを実行して結果を返します。 プロトコル: Agent Client Protocol (ACP) クライアントとハーネスの境界を定義するプロトコルとして、 Agent Client Protocol (ACP) を選びました。ACP はエージェントとクライアントの通信を標準化した仕様で、2026 年 6 月に 1.0 に到達しました。このプロトコルは JetBrains の IDE、Xcode、Zed といった IDE や、Obsidian、Emacs、Neovim といったほかのエディターでもサポートされています。私たちは今年の初めに Kiro CLI で ACP を採用した経験 から、これらのアプリケーション内で直接 Kiro とやり取りできるようにしていました。統一されたハーネスにも ACP を採用することにしたのは、サードパーティ製エディター向けだけでなく、Kiro 自身のクライアントと私たち自身のエージェントの間のインターフェースとして使うためです。ACP の 2 つの性質がこれを可能にしました。カスタムメソッドに対する拡張性と、トランスポートの柔軟性です。 ACP は公式にトランスポートとして stdio をサポートしています。これはハーネスがエディターやターミナルの子プロセスとして動作するローカルクライアントで機能します。Web 版 Kiro や iOS アプリのようなリモートクライアントには、別のトランスポートが必要でした。これらのクライアントがクラウドサンドボックスで動作するハーネスに接続できるように、独自の WebSocket ベースのトランスポートを追加しました。クライアントがどのトランスポートを使うかに関わらず、バイナリ、ツール、エージェントの振る舞いは同一です。 ┌─────────────────────────────────────────────────────────────┐ │ Kiro agent harness │ └──────────┬────────────────┬────────────────┬────────────────┘ │ stdio │ stdio │ WebSocket │ │ │ ┌──────┴──────┐ ┌──────┴─────┐ ┌───────┴──────────────┐ │ Kiro CLI │ │ Kiro IDE │ │ Kiro Web · iOS app │ │ (terminal) │ │ (Code OSS) │ │ (browser · mobile) │ └─────────────┘ └────────────┘ └──────────────────────┘ トランスポートを超えて、私たちは ACP のメソッドセットを Kiro-ACP と呼ぶものに拡張しました。標準の ACP は基本的な部分 (セッションのライフサイクル、メッセージのストリーミング、ツール呼び出しのレポート) を扱いますが、Kiro の機能にはそれ以上のものが必要でした。たとえばライブステアリングを追加しました。ユーザーはエージェントの作業中でもメッセージを送信でき、そのメッセージが次の推論ターンで注入されることで、キャンセルや待機なしにエージェントの方向性を調整できます。ACP はメッセージのキューイングをサポートしていないため、ライブステアリングを実現するために新しいメソッドプロパティと通知で ACP を拡張しました。また Kiro の仕様駆動開発ワークフローを専用のメソッド群としてモデル化し、ACP の基本的なツール承認を豊富なマルチスコープの権限システムへと拡張し、コンテキストウィンドウの使用状況とフック実行に関する通知を追加しました。合計で Kiro-ACP はベースプロトコルに加えて 20 を超えるエージェント呼び出し可能なメソッド、15 のクライアント呼び出し可能なメソッド、20 の通知タイプを追加しています。ACP の拡張モデルはこれをきれいに保ちます。仕様どおり、カスタムメソッドはアンダースコアのプレフィックスを使い、Kiro の拡張はすべて _kiro/ 名前空間の下に配置されています。プロトコルをフォークすることなく、Kiro 固有の機能のために拡張できるのです。 結果として、サードパーティのクライアントはファーストパーティのクライアントと同じ方法で接続できます。ACP 互換のクライアントであれば、ツール、サブエージェント、セッション管理、MCP 接続を含む完全なエージェントを利用できます。ファーストパーティのクライアント (IDE、CLI、Web、iOS) は加えて Kiro-ACP の拡張を利用して、ライブステアリング、仕様、リッチな権限 UI、コンテキスト使用量トラッキングといった機能を提供します。 仕様、エージェント、フックがどこでも使える 単一のハーネスがもたらす直接的なメリットは、これまで 1 つのクライアントに閉じ込められていた機能が、同じ設定フォーマットと同じ振る舞いで、どのクライアントでも使えるようになったことです。 仕様駆動開発 は以前は IDE 限定でした。今では CLI ( /spec new で開始できます) と Web 版 Kiro でも動作します。エージェントは仕様ワークフローを駆動する LLM とのやり取りと自動化された推論 (要件の生成、技術設計の作成、作業のタスクへの分解) を扱い、各クライアントは自分のフォームファクターに合った形でそれを提示します。IDE は仕様のアーティファクトを横並びのペインで表示します。CLI はターミナル内でレンダリングします。Web 版 Kiro はブラウザーでインラインレビューとマルチユーザーコラボレーションとともに表示するので、チームが一緒に仕様をイテレーションできます。エージェントは ACP を話し、クライアントは出力をどう提示するかを決めます。 カスタムエージェント は、どのクライアントでも同じ .kiro/agents/ Markdown フォーマットを使います。エージェントには説明、システムプロンプト、タグベースのツール選択 (個別のツール名ではなく read 、 write 、 shell といったシンプルなタグ)、アクセス可能なサブエージェント、インラインの MCP サーバー定義、インラインの権限ルールを定義できます。カスタムエージェントの設定をバージョン管理にコミットすれば、チームメンバー全員がすべてのクライアントで使えるようになります。 --- description: セキュリティ上の問題を確認するコードレビューエージェント tools: [read, shell, "@github"] permissions: rules: - capability: fs_read effect: allow - capability: shell match: ["git diff *", "git log *", "npm audit"] effect: allow mcpServers: github: url: https://api.githubcopilot.com/mcp/ headers: Authorization: Bearer ${GITHUB_TOKEN} --- あなたはセキュリティに重点を置いたコードレビュアーです。現在の差分を レビューし、脆弱性、認証情報の漏洩、安全でないパターンを確認してください。 依存関係のアドバイザリは npm audit で確認してください。 フック は同じ .kiro/hooks/*.json フォーマットを使い、同じトリガー ( SessionStart 、 PreToolUse 、 PostToolUse 、 FileCreate 、 FileSave ) で、すべてのクライアントで同じように動作します。 機能の可用性を超えて、統一されたハーネスは、正しく作るのが難しい領域でも一貫した振る舞いを提供します。コンテキスト管理、コンパクション、要約は、どのクライアントを使ってもすべて同じように動作します。以前はハーネスごとに独自のコンパクション戦略を持っていたため、IDE、CLI、Web クライアントのどれを使っているかによってセッションが長くなるにつれて振る舞いが変わることがありました。今では 1 箇所で実装、テスト、改善される単一の実装があります。統一されたハーネスをクライアント全体に展開して以来、コンテキスト保持を改善するため、ハーネスにより良いコンパクションプロンプトをすでにリリースしています。またハーネスの深い部分でレジリエンスとパフォーマンスの改善もリリースしました。モデル推論リクエストの改善されたリトライロジック、高速な権限評価、より弾力性のある MCP サーバー接続などです。すべてのクライアントがこれらの変更の恩恵を受けます。結果として、どのクライアントを好むかに関わらず、一貫した品質と信頼性が得られます。 単一のポリシー言語 統一ハーネスが登場する前、各クライアントは異なる構文、異なるセマンティクス、異なる設定場所を持つ独自の権限システムを持っていました。CLI は正規表現パターンによる allowedCommands / deniedCommands を使いました。IDE はプレフィックスマッチによる trustedCommands と、サブストリングマッチによる別の commandDenylist を使いました。どちらのクライアントでも権限はツール単位でした。 .env への読み取りを拒否する といった単一の意図は、ファイルを読める各ツール (read、glob、grep、コードインテリジェンス) に対して個別に設定する必要があります。1 つでも見落とすと、エージェントは別のツール経由でそのファイルにアクセスできてしまうのです。ユーザーはツール呼び出しごとに y を押し続けるか、すべてを信頼するかの二択を迫られ、その中間の実用的な選択肢がありませんでした。私たちが求めていたのは、ケイパビリティレベルで意図を表現でき、永続的かつ組み合わせ可能な同意によって承認疲れ (acceptance fatigue) を減らせる権限モデルでした。 今では、形式的に検証されたポリシー言語である Cedar に支えられた、単一のケイパビリティベースの権限モデルがあります。1 つのルールで、すべてのツールにまたがる同種の操作をまとめて対象にできます。 rules: # Block all tools that read files from accessing secrets - capability: fs_read match: [".env", ".env.*", "secrets/**", "**/*.pem"] effect: deny # Allow specific shell commands without prompting - capability: shell match: ["npm test *", "npm run build", "git status"] effect: allow # Allow an MCP server's tools - capability: mcp match: ["github/*"] effect: allow ケイパビリティはツールを機能ごとにグループ化します。 fs_read 、 fs_write 、 shell 、 web_fetch 、 mcp 、 subagent などです。fs_read の deny は、ファイルを読むすべてのツール ( read_file 、 grep_search 、 file_search 、そして今後追加される read 系ツール) を個別に列挙することなくブロックします。 ポリシーは複数のスコープにまたがって合成でき、deny が常に勝つセマンティクスでマージされます。Kiro 自体は変更不可能なセキュリティ不変条件を適用します (たとえば、エージェントは自身の権限ファイルを変更できません)。エンタープライズ管理者は MDM 経由で制限をプッシュできます。ユーザーは自分のルールをユーザーレベルまたはワークスペースレベルで設定します。エージェントプロファイルはその役割に応じた権限を宣言できます。セッションレベルの判断は、作業しながら積み上がっていきます。事前の設定は不要です。ポリシーは同意の判断を下すにつれて自然に育っていき、意味のあるスコープでそれを永続化できます。 ハーネスがビジョンを解き放つ 新しいエージェントハーネスアーキテクチャの成果はすでに現れています。すべてのクライアントが統一ハーネスに移行して以来、クライアント側の変更ゼロで複数の機能をクライアント横断でリリースしてきました。グローバルフックとポリシープリセットもその一例です。 グローバルフック は ~/.kiro/hooks/ でフックを一度定義するだけで、すべてのワークスペースで自動的に発火するため、保存時のリント実行やコミット前のセキュリティチェックといった横断的な振る舞いをプロジェクトごとに複製する必要がなくなります。 ポリシープリセット は edit-workspace や dev-shell のような合成可能な名前付きルールセットで、一般的なワークフローにおけるプロンプト疲れ (prompt fatigue) を減らします。権限にポリシープリセットを追加すると (たとえば policies: [dev-shell, edit-workspace, read-all] )、ハーネスのポリシーエンジンがロード時にそれらを個別のルールに展開します。どちらの機能もハーネスのアップデートだけですべてのクライアントに提供されました。 本記事の冒頭で述べたビジョンには、まだ構築が必要なエージェントの能力 (ケイパビリティ) がいくつかあります。たとえば、環境間でセッションを移動するためのセッションパッケージングや、ローカルとクラウドの両方のセッションをどのクライアントからも制御できる機能などです。統一されたハーネスなら、新しい能力を一度作るだけで済みます。多くの場合、グローバルフックやポリシープリセットのように、クライアント側の変更ゼロですべてのクライアントに配信できます。統一ハーネスがクライアント側の作業を完全になくしたわけではありませんし、そうしたいわけでもありませんでした。ターミナル、デスクトップの IDE、ブラウザー、スマートフォンは異なるインタラクションモデルを持っており、私たちは画一的な体験を提供するのではなく、各クライアントがそのフォームファクターに合った体験に感じられることを望んでいます。新しいエージェントハーネスアーキテクチャなら、エージェントのロジックはクライアント全体で同一で、各クライアントチームはそれとどうやり取りするのがベストかに集中できます。 Kiro のユーザーとして、新しいエージェントハーネスアーキテクチャは、新しい能力がより速く届き、一貫した振る舞いを示し、あなたが好むクライアントに関わらず同じ設定で動作することを意味します。 新しい Kiro エージェントハーネスを試す 新しい Kiro エージェントハーネスは 4 つの Kiro クライアントすべてでライブ稼働しているので、今日から試せます。 Kiro IDE 1.0 は、ケイパビリティベースの権限、タグベースツールとインライン MCP を備えたカスタムエージェント、並列セッションを指揮するためのエージェントフォーカスモード、ドッキング可能なチャットタブ、セッションエクスポートを提供します。 IDE 1.0 のドキュメントと移行方法 を参照してください。 Kiro CLI v3 (アーリーアクセス) は、仕様駆動開発、permissions.yaml、拡張されたフック、新しいエージェント設定フォーマットを備え、ターミナルで同じ統一ハーネスを実行します。 kiro-cli --v3 で試せます。 CLI v3 のドキュメントと移行方法 を参照してください。 Web 版 Kiro (プレビュー) はクラウドサンドボックスでハーネスを実行し、ブラウザーで仕様を使った自律的な開発、マルチリポジトリセッション、GitHub と GitLab の統合を提供します。 サインイン / サインアップ できます。 iOS 版 Kiro (プレビュー) は Web 版 Kiro と同じクラウドセッションにスマートフォンから接続し、ラップトップを開かずに自律的な作業のキックオフ、差分のレビュー、変更の承認を行えます。 アーリーアクセスをリクエスト してください。 翻訳は Solutions Architect の吉村が担当いたしました。
こんにちは、トモニテ開発部 iOS エンジニアの村田です。 iOS エンジニアもしくは Android・クロスプラットフォームを含めてモバイルエンジニアの皆さんに対して気になっていることがあります。 みなさん AI 開発どんな感じでやってますか?どんなハーネス組んでますか? エンジニアリング業界では、単に指示を出して書いてもらう「バイブコーディング」の次の段階として、AI エージェントの自律化や「ハーネスエンジニアリング」「ループエンジニアリング」といった話題が急速に広がっています。 Web やサーバーサイド領域では、こうした最新の AI 活用の情報が活発に共有されている一方、iOS(モバイル)開発における実践的なナレッジはまだまだ各所に散らばっており個々で孤軍奮闘している印象を受けています。 私自身、久しぶりに iOS 開発に取り組んでいて、Claude Code と git worktree を用いた並行開発をする中で iOS 特有のハマりどころをいくつか感じました。 今回は「並行開発」という観点にフォーカスして、iOS で並行開発したときに感じた課題と対処方法を記載します。 開発環境 前提として、以下のような環境・仕組みで開発しています。 使用技術 AIエージェント : Claude Code エディタ : VSCode 並行開発 : Git Worktree 対象 : iOS アプリ(Swift / UIKit / SPM / .xcodeproj) ビルド方法 : XcodeBuildMCP(Claude 経由の MCP)・XcodeBuildMCP(CLI 版)・Xcode(GUI) ディレクトリ構成 <repo>-trees/ ← worktree develop/ ← メイン worktree(base ブランチ) feature-A/ ← タスクごとの worktree(並列) feature-B/ ← タスクごとの worktree(並列) refactor-C/ ← タスクごとの worktree(並列) ... 開発手順 タスク開始時に git worktree add で develop ブランチから新規 worktree を切る worktree 配下で Claude Code のセッションを開始し、要件定義 → 実装 → PR 作成など開発フローを進行 タスクが終わったら、その worktree ごと片付ける ---bin なぜ並行開発が欠かせないのか あちこちで語られている話なので、要点だけ。 AI に開発させると、人間の役割は「実装する人」から「複数のエージェントを監督する人」に変わります。「どこまで自律的に AI に開発させられているか」にも依りますが、設計・実装・ビルド・テストと多くのフェーズで人間の手が空くようになるため、1 タスクを直列で進めるよりも複数タスクを並行で回す方が効率よく進められます。 そこで注目を浴びたのが git worktree です。ブランチごとに独立した作業ディレクトリ(worktree)を持てるため、作業ファイルの競合を気にせず、安全に複数タスクを同時進行できます。 そうして git worktree を用いて iOS 開発を始めたのですが、いくつか課題が発生しました。 問題その1: DerivedData がストレージを食い尽くす 何が起きたか iOS のビルドでは DerivedData を生成します。DerivedData には Xcode がビルドのたびに吐き出す中間生成物(ビルドキャッシュ・インデックス・成果物など)が含まれており、デフォルトでは ~/Library/Developer/Xcode/DerivedData/ に生成されます。XcodeBuildMCP でビルドする場合は、 ~/Library/Developer/XcodeBuildMCP/workspaces/<worktree>-<hash>/DerivedData/<プロジェクト名>-<hash> に生成されます。 DerivedData は worktree の内部ではなく、ユーザー共通の場所にまとめて溜まるため、worktree の数に比例して独立したビルドキャッシュが蓄積されていきます。 私の環境では 1 worktree あたり数 GB〜20 GB 台、合計およそ 86 GB になっていました。 結果としてディスクの空き容量が枯渇し、スワップ領域も確保できなくなって、ビルドどころではなくなりました。 # Xcode(GUI)の既定 — プロジェクト名 + ハッシュ名 ~/Library/Developer/Xcode/DerivedData/ ├── <プロジェクト名>-a1b2c3d4efgh…/ ├── <プロジェクト名>-e5f6g7h8ijkl…/ ├── <プロジェクト名>-i9j0k1l2mnop…/ ├── <プロジェクト名>-q7r8s9t0uvwx…/ └── … # XcodeBuildMCP の既定 — worktree 名 + ハッシュ名 ~/Library/Developer/XcodeBuildMCP/workspaces/ ├── develop-a1b2c3…/DerivedData/ 19 GB ├── feature-A-d4e5f6…/DerivedData/ 21 GB ├── feature-B-g7h8i9…/DerivedData/ 11 GB ├── feature-C-j0k1l2…/DerivedData/ 8.8 GB └── …(他 4 worktree) 26 GB 計 86 GB キャッシュを削除しようと試みたところで Xcode の場合、DerivedData のフォルダ名がハッシュ化されていて、フォルダ名だけではどの worktree に対応するかわからない ビルドしなくてもインデックス更新などで更新日時が変わるため、「更新日が古い=不要」という判断も効かない といった理由により、使い終わった worktree のゴミだけを削除することが難しかったです。 かといって全部消すと、全 worktree がコールドビルドに逆戻りしてしまいます。 XcodeBuildMCP はデフォルトでフォルダ名に worktree 名が入るため対応関係は分かりやすいのですが、 git worktree remove (worktree の削除)をしても、この孤児フォルダが残り続ける点は Xcode の既定と同じです。 対処方針: DerivedData を worktree 配下に保存する 対応策として DerivedData の置き場所を worktree フォルダの直下( <worktree>/DerivedData )に固定すると、次のメリットが得られました。 どのキャッシュがどの worktree のものか、置き場所を見れば分かる git worktree remove すれば DerivedData も一緒に消える 開発時のライフサイクルは以下のようなイメージです。 DerivedData の置き場所を変更する方法 ① Xcode の GUI でビルドする場合 全プロジェクト一律でよい場合 : Xcode → Settings → Locations → Derived Data を Default から Relative に変える 特定のプロジェクトだけ有効にしたい場合 :対象プロジェクトを Xcode で開いた状態でメニューの File → Workspace Settings… ( .xcworkspace を開いていない場合は Project Settings… )を選び、 Derived Data を Workspace-relative Location に切り替える 後者の場合、実態としてはプロジェクト内の WorkspaceSettings.xcsettings ( xcuserdata 配下・通常は Git 管理外のユーザーローカル)の設定と同等のため、GUI を使わず次の内容を直接書いても実現できます。 <? xml version = "1.0" encoding = "UTF-8" ?> <!-- <project>.xcodeproj/project.xcworkspace/xcuserdata/<user>.xcuserdatad/WorkspaceSettings.xcsettings --> <! DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" > <plist version = "1.0" > <dict> <key> DerivedDataLocationStyle </key> <string> WorkspaceRelativePath </string> <key> DerivedDataCustomLocation </key> <string> DerivedData </string> </dict> </plist> ② XcodeBuildMCP でビルドする場合 こちらは .xcodebuildmcp/config.yaml の derivedDataPath で決まります(worktree のルートからの相対パスで解決されます)。 # <worktree>/.xcodebuildmcp/config.yaml schemaVersion : 1 sessionDefaults : projectPath : "<プロジェクトパス>" scheme : "<スキーム名>" derivedDataPath : "./DerivedData" platform : "iOS" useLatestOS : false bundleId : "<バンドル ID>" 💡 どちらの方法でも DerivedData がリポジトリ配下に生成されるため、 .gitignore に DerivedData/ を追加する必要があります。 ただし「Xcode 版で特定のプロジェクトだけ Relative にしている場合」や「XcodeBuildMCP 版で .xcodebuildmcp/config.yaml を Git 管理していない場合」は、新しい worktree を作るたびにこれらの設定を行う必要があります。毎回手動で設定するのは面倒なので、Git の post-checkout hook で worktree の作成時に自動設定されるようにするのがおすすめです。 post-checkout hook で DerivedData の設定を自動化する git worktree add や git checkout を実行すると、 post-checkout という hook が発火します。hook は共通の Git ディレクトリ( git rev-parse --git-common-dir )に置かれ全 worktree で共有されるので、そこに設定することで新規 worktree 作成時の処理を仕込むことができます。 下記のような処理を .git/hooks/post-checkout に記述することで、新規 worktree 作成時に「DerivedData を各 worktree 配下( <worktree>/DerivedData )に保存する」ように設定できます。 なお以下の hook では ② の config.yaml を直接出力していますが、正の config.yaml をデフォルトブランチなどで管理し、post-checkout で cp する方式でも構いません。 #!/bin/bash # .git/hooks/post-checkout if [ " $3 " = "1" ]; then PROJECT = $( find . -maxdepth 1 -name " *.xcodeproj " | head -1 ) if [ -n " $PROJECT " ]; then # ① Xcode GUI 用: WorkspaceSettings に worktree 相対の DerivedData を書く DIR = " ${PROJECT} /project.xcworkspace/xcuserdata/ $( whoami ) .xcuserdatad " PLIST = " ${DIR} /WorkspaceSettings.xcsettings " mkdir -p " $DIR " [ ! -f " $PLIST " ] && plutil -create xml1 " $PLIST " plutil -replace DerivedDataLocationStyle -string WorkspaceRelativePath " $PLIST " plutil -replace DerivedDataCustomLocation -string DerivedData " $PLIST " # ② XcodeBuildMCP 用: config.yaml を worktree 直下に生成 if [ ! -f .xcodebuildmcp/config.yaml ]; then mkdir -p .xcodebuildmcp cat > .xcodebuildmcp/config.yaml <<'YAML' schemaVersion: 1 sessionDefaults: projectPath: "<プロジェクトパス>" scheme: "<スキーム名>" derivedDataPath: "./DerivedData" platform: "iOS" useLatestOS: false bundleId: "<バンドル ID>" YAML fi fi fi 問題その2: シミュレータを複数セッションが奪い合う 何が起きたか iOS 開発では、シミュレータ上での実操作が必要な場面が多々あります。 画面情報・遷移情報の取得 コード変更後の動作確認 E2E テストの実行 AI に並行開発させている中でこれらの動作をさせようとすると、1 台のシミュレータを複数のセッション(エージェント)が奪い合い、開発が滞る問題が発生しました。 操作の割り込み・競合: あるエージェントの検証中に、別のエージェントが起動・操作を行って画面を奪い合う 状態の破壊: 実行中のアプリ領域やデータが上書きされ、E2E テストや動作確認が誤判定される 処理の順番待ち: シミュレータの空き待ちが発生し、並行開発のスピード感が失われる 対処方針: worktree ごとに専用シミュレータを持たせる 対策として、 worktree ごとに専用シミュレータを持たせる運用にしました。 具体的にはシミュレータ名を <worktree 名> - <元の機種名> (例: feature-A - iPhone 16 Pro )のように紐付けます。これにより「このセッションが触っていいのはこの 1 台のみ」と明確にし、他のセッションで稼働中のシミュレータへの誤干渉を防いでいます。タスクが完了して役目を終えたシミュレータはシャットダウンし、別の worktree での開発で名前を変更して再利用する流れです。 💡 基本的には AI による並行開発を前提としていますが、人間が最終的な動作確認を行う場合にもメリットがあります。各 worktree 専用のシミュレータ上にビルド済みアプリがそのまま残っているため、スムーズに動作確認を進められます。 シミュレータの選定ルール ある worktree の開発で使うシミュレータの選定ルールは、以下のようにしました。 worktree 名で始まるシミュレータが起動済みなら、それをそのまま使う worktree 名で始まるシミュレータが未起動なら、起動して使う 無ければ、起動していないシミュレータを <worktree 名> - <元の機種名> にリネームして起動する これを実装に落とし込んだものが以下のコードです。 resolve_udid は ①→③ の順に「その条件に合うシミュレータがあるか」を確認していき、最初に見つかった 1 台を、その worktree に対応するシミュレータの UDID(デバイスの一意 ID)として採用します(見つかった時点で残りは確認しません)。あとはこの UDID を指定してビルドすれば、その worktree 専用のシミュレータに向けて実行できます。 wt = " $( basename " $PWD " ) " # worktree 名(例: feature-A)をシミュレータ名の接頭辞に使う # シミュレータ一覧を JSON で取得して devices_json にキャッシュする refresh_devices() { devices_json = $( xcrun simctl list devices available --json ) ; } # 未起動のシミュレータを起動する boot_sim() { xcrun simctl boot " $1 " 2 > /dev/null ; } # UDID から元の機種名を引く(既に worktree 名が付いていれば落とす。付け足すと再利用のたびに接頭辞が積み重なるため) sim_name() { printf ' %s ' " $devices_json " | jq -r --arg u " $1 " \ ' [.devices[][] | select(.udid == $u) | .name][0] // empty | sub("^.+ - "; "") ' } # 指定した起動状態(booted / unbooted)で、worktree 名で始まるシミュレータの UDID を返す(無ければ空文字) pick_named() { printf ' %s ' " $devices_json " | jq -r --arg wt " $wt " --arg want " $1 " \ ' [.devices[][] | select((.name | startswith($wt + " - ")) and (if $want == "booted" then .state == "Booted" else .state != "Booted" end)) | .udid][0] // empty ' } # 未起動(Shutdown)の空きシミュレータを1台返す(無ければ空文字) pick_spare() { printf ' %s ' " $devices_json " | jq -r \ ' [.devices[][] | select(.state == "Shutdown") | .udid][0] // empty ' } resolve_udid() { refresh_devices # ① worktree 名で始まるシミュレータが起動済みなら、そのまま使う udid = $( pick_named booted ) ; [ -n " $udid " ] && { echo " $udid "; return; } # ② worktree 名で始まるシミュレータが未起動なら、起動して使う udid = $( pick_named unbooted ) ; [ -n " $udid " ] && { boot_sim " $udid "; echo " $udid "; return; } # ③ 無ければ、空きシミュレータの接頭辞を「<worktree 名> - 」に付け替えて起動する spare = $( pick_spare ) [ -z " $spare " ] && { echo " 空きシミュレータがありません " >&2; return 1 ; } xcrun simctl rename " $spare " " $wt - $( sim_name " $spare " ) " boot_sim " $spare " echo " $spare " } 開発フローとクロージング処理 ここまでの処理を開発フローに沿って並べると次のようになります。 開始 : タスクごとに worktree を切り、専用の作業場を用意する 実装 : その worktree で Claude セッションを開始し、1 つの機能を実装する 動作確認 : その worktree 専用のシミュレータを起動し、ビルド & 実行・テストを行う レビュー : 実装が固まったら PR を作成する クロージング処理 : PR マージと同時に、worktree 削除・Issue クローズ・シミュレータのシャットダウンを行う 開発フローの最後には、クロージング処理を置いています。 close-feature のようなスキルにまとめ、PR マージ → Issue クローズ → worktree 削除 → 専用シミュレータのシャットダウンを一括で実行しています。 このクロージング処理をフローに組み込むことで、問題その1で挙げた DerivedData によるストレージ圧迫を防ぎつつ(worktree を削除すれば配下の DerivedData も一緒に消える)、起動したままのシミュレータが積み上がってメモリを圧迫するのも同時に抑えられます(シャットダウンした端末は、次のタスクで再利用される)。 問題その3: .xcodeproj のコンフリクトが多発する .xcodeproj を Git 管理しているとブランチの切り替えやマージのたびにコンフリクトが起きやすい、という問題があります。これ自体は昔からある iOS 開発の悩みですが、AI に複数タスクを並行開発させるようになってコンフリクトの頻度も増え、無視できないコストになったと感じています。 トモニテの PJ では実現できていませんが、下記の理由により XcodeGen を用いた YAML 管理への移行を検討しています。 1. 並行開発でのコンフリクト軽減 git worktree などを活用して複数ブランチでの並行開発を進める場合、 project.pbxproj のコンフリクトが多発する可能性があります。 特に AI の活用によって開発の速度や並行性が上がるほど、その発生頻度も多くなりがちです。 XcodeGen を導入して .xcodeproj を自動生成の成果物として扱い .gitignore に追加することで、 .xcodeproj でのコンフリクト問題を解消できると考えています。 2. AI と YAML の相性 Xcode のプロジェクト管理は GUI 操作を前提とした仕組みであり、AI エージェントとは相性が良くありません。これを project.yml による宣言的なテキスト管理に切り替えることで、「YAML での管理・変更 → コマンド実行( xcodegen generate )」という AI に適したフローで構成を変更できるようになると考えています。 3. コードレビューのしやすさ コード差分が複雑な pbxproj からシンプルな project.yml に変わることで、変更内容を容易に把握できます。 AI がコードを書き、人間がレビューするフェーズでは可読性の観点でもメリットがあると考えています。 まとめと残課題 ここまで git worktree を用いた iOS の並行開発で出会った問題点と、その対処方法を紹介してきました。 とはいえ、こうして並行タスクを回す仕組みを整えても、human-in-the-loop 的な体制では並行開発の効果も限界があると感じています。監督する人間のコンテキストスイッチがボトルネックになるため私の場合、同時に見られるのは 3〜4 タスクほどでした。これでは開発生産性も頭打ちになり、「プロダクトや事業をどう伸ばすか」という本質的な問いに集中できないと感じています。 この課題を突破するためには、やはり「ループエンジニアリング」など AI がより自律的に開発を回せるような仕組みを追求していくことが不可欠だと感じています。 関連リンク XcodeBuildMCP XcodeGen
はじめに ZOZOTOWN開発本部のらぷ( @laprasdrum )とイッセー( @15531b )です。WWDC現地参加は、らぷは2016年以来2回目、イッセーは初参加(かつ初渡米)です。本記事ではWWDC26の現地参加レポートとともに、ZOZOのiOSエンジニアによるおすすめセッション、6月18日に開催されたLINEヤフー株式会社との合同報告会イベントについてもご紹介します。 目次 はじめに 目次 WWDC26のSpecial Event Day 0 Day 1 Keynote Download stations Platforms State of the Union 現地視聴をより楽しむために In-person labs Inner ring reception Day 2 Developer session Mixer @Developer Center Theater event 併催コミュニティイベント おすすめセッション集 優れたデザインのための原則 Foundation Modelsフレームワークの新機能 WWDC26 報告会 at LINEヤフー, ZOZO さいごに WWDC26のSpecial Event 今年6月7日〜9日(現地時間)のWWDC26では、昨年と同様に招待制のSpecial Eventが現地開催されました。昨年の様子は「WWDC25現地参加レポート」をご覧ください。 techblog.zozo.com 今年のSpecial EventはWelcome receptionから始まりました。基調講演後には、Appleの方へ新APIを質問したりアプリのフィードバックをもらえたりするIn-person labsが開かれました。その後、Apple ParkのInner ringで交流会がありました。最終日はSteve Jobs Theaterで、スター・ウォーズ作品『The Mandalorian and Grogu』の上映とスペシャルゲストのインタビューを楽しめました。 Date Pacific Time Content Venue Day 0 (June 7) 3 p.m. Welcome reception Infinite Loop Day 1 (June 8) 8 a.m. Check-in Apple Park 10 a.m. Keynote Apple Park After Keynote Download stations open Apple Park 12 p.m. Lunch Apple Park 1 p.m. Platforms State of the Union Apple Park After Platforms State of the Union In-person labs Apple Park 4-6 p.m. Reception in the inner ring Apple Park Day 2 (June 9) 10 a.m. Developer session Steve Jobs Theater or Apple Developer Center Cupertino 11:30 a.m. Mixer Apple Developer Center Cupertino 8 p.m. Pre-show presentation and special screening of The Mandalorian and Grogu Steve Jobs Theater Day 0 私たちはDay 0の午前にSFO(サンフランシスコ国際空港)へ到着し、宿泊先のホテルに荷物を置いてからInfinite Loopへ向かいました。道中は初めてWaymoを利用しました。急カーブでもほとんど揺れずに走行するため、仮眠できるほど静かでした。 Infinite Loopに到着するとチェックイン待ちの長蛇の列がすでにできていました。並んでいる間のおもてなしとして配られたジェラートバーとお水で暑さをしのぎつつ待ちました。 2種類の味から選べたジェラートバー 入口前でセキュリティチェックを済ませると、参加者用のバッジとノベルティを受け取りました。バッジにはNFCタグが入っており、各イベントのチェックイン時にAppleのスタッフのiPhoneにバッジをかざすことになっています。ノベルティ恒例のピンバッジにはLil Finder Guyと創立50周年を象徴するデザインが含まれていました。入場時はAppleのスタッフの方々が歓声とともに出迎えてくださり、Day 0から盛り上がりを肌で感じました。 今年のノベルティバッグ 今年のピンバッジ、ステッカー、ボトル 参加者用バッジ ── お気に入りのピンバッジを添えて その後は終了時刻の夕方7時まで自由に過ごしました。軽食とドリンクをいただきながら各国の参加者との交流、Apple Design Awardsの受賞者とファイナリストとのトーク、Appleのスタッフによるモニュメント前の記念撮影などを楽しみました。 快晴に恵まれたこの日 モニュメント前で記念撮影 また、APACの参加者で集まって記念写真も撮りました。オフラインで参加すると、多くの方がApple Platformの開発者として関わっていることを実感できました。 Day 1 Keynote まずはKeynoteの会場に向かうため、Visitor Center前でチェックインを済ませてApple Parkに入場しました。入場まで横断歩道の信号待ちで列がゆっくり進む中、Caffè Macsのスタッフからいただいたドーナツを食べながら近くの方と「今年のWWDCは何を期待してますか?」と雑談しました。話しかけた方の多くがAIのトピックを気にされていました。 Visitor Center前のチェックインも長蛇の列 Caffè Macsからいただいたオレンジ味のドーナツ 会場に到着したのは8時半頃でした。Keynote開始時間の10時までは自由に散策し、参加者とお話を楽しみました。 KeynoteおよびPlatforms State of the Unionの会場 会場のスクリーンでは、オンラインで公開されているKeynoteの動画が再生されます。現地では動画の再生前にCraig Federighi氏がステージに登場し、挨拶がありました。 developer.apple.com 続いてTim Cook氏も登場し、このときの会場の盛り上がりは強烈でした。CEOとしてのKeynoteでの登壇は今年が最後です。参加者全員が立ち上がってiPhoneを掲げて撮影する光景を前に、Cook氏自身も「これまでこんなにiPhoneに囲まれたことはありません」と語っていました。 壇上に登場したTim Cook氏 Download stations Keynoteが終了すると、高速の有線ネットワークが提供されるDownload stationsに集まりました。ここでXcode 27 BetaやiOS 27 Betaのダウンロードを始めました。この日は晴天で気温も高かったため、パラソルの影に集まって休憩する参加者も多かったです。 有線ネットワークが用意されたDownload stations Platforms State of the Union developer.apple.com 手元にiOS 27 BetaをインストールしたiPhoneを触りながら、先のKeynoteの内容も踏まえてPlatforms State of the Unionを視聴しました。今回のSiri AIやCore AI、Foundation Modelsなどのアップデートには、共通した方向性があります。デバイスへ蓄積された写真やテキストなどのパーソナルなデータをもとに、AI体験を最適化することがAppleの狙いです。Newsroomで公開されたSiri AIの記事には、Apple Intelligenceのアーキテクチャ図が掲載されています。この図では、デバイスとアプリケーション(またはSiri AI)の間にユーザーコンテキストが示されています。Appleプラットフォームのアプリ開発者には、このコンテキストを活かしたAI活用が求められているのでしょう。 www.apple.com 視聴後しばらくすると、スクリーン上にさまざまなアプリのアイコンが表示されました。幸運なことに弊社のアプリが映し出されたタイミングで撮影できました。 どこかにある弊社アプリのアイコン。見つけられましたか? 現地視聴をより楽しむために 現地ならではの視聴の楽しみ方も、二人それぞれ工夫してみました。らぷは Rokid Glasses というスマートグラスのリアルタイム翻訳機能を使って視聴しました。体感1秒未満で翻訳結果が表示されたので和訳文も追いつつ快適に視聴できました。 Rokid Glassesのリアルタイム翻訳結果 イッセーは英語に自信がなかったため、セッションの視聴でAirPods Proのライブ翻訳機能を試しました。実際に使ってみると、登壇者の英語が純正の翻訳アプリ上に日本語テキストとして表示されるだけでなく、AirPodsからも日本語に翻訳された音声がリアルタイムで流れてきます。この機能のおかげで、英語に自信がなくてもセッションの内容を大まかに理解できました。イッセーとしては、画面上のテキスト翻訳はあえて見ず、登壇者の様子を見ながら日本語音声だけを聞くスタイルがとても快適でした。 ライブ翻訳機能の翻訳結果 私たち以外にもスマートグラスやAirPodsを使って視聴している参加者が多くいました。海外カンファレンスへ現地参加する際の言語の壁はこれまでもありましたが、こうした技術によって乗り越えやすくなったと感じました。 In-person labs Platforms State of the Unionが終了するとIn-person labsが始まり、各ラボで新しく発表されたAPIや日々の開発で困っていることを相談しに行きました。特に困ったことがなくても「まだ触れたことのないFrameworkを始めようと思うんだけど何から始めたら良いですか?」といった相談でも問題ありませんでした。気さくな雰囲気の中でいろいろ話せるので、来年現地に行かれる方はぜひ積極的に利用してみてください。 Inner ring reception その後夕方6時まではInner ring内で自由に過ごしました。Xcode 27 Betaで開発したり、初対面や既知の開発者との会話を楽しんだり、Appleの方に質問したりと、あっという間に時間は過ぎていきました。 Xcodeダウンロード中にAppleのWWDRの方にいただいたFoundation Models Frameworkのステッカー 虹のApple Stage前で撮影してもらったイッセー。青いシャツの方は各国のApple Storeのスタッフ Day 2 Developer session Developer sessionに参加するため、Apple Parkへ向かいチェックインを済ませました。今回のセッションはSteve Jobs Theaterで開催されました。ここは過去のWWDCでは立ち入ることができなかった特別な場所です。定員制のため、シアターに入れない場合はApple Developer Centerでの視聴でした。開始1時間前に到着したものの、すでに多くの参加者が列を作っていました。皆がこのシアターでの参加を待ち望んでいる熱気を感じました。 無事に入場でき、ガラス張りの円形の建物と緑豊かな造形美に圧倒されました。会場で軽い朝食をとった後、いよいよセッションがスタートしました。 Developer session前のSteve Jobs Theaterの様子 今回のセッションでは、Xcode 27の「Agentic Coding」やFoundation Modelsなどの新しいAIフレームワークが取り上げられました。実際のアプリ開発にどう組み込むかという実践に焦点を当てた内容です。その中でも、Evaluations Frameworkはどのように役立てられるのかイメージができていませんでした。セッションを通して、LLMの出力の品質を容易にテスト・評価できる点を理解でき、実際に触ってみる良いきっかけになりました。動画でも公開されているので、使い方のイメージが付いていない方の参考になります。ぜひチェックしてみてください。 developer.apple.com Developer sessionの様子 Mixer @Developer Center セッション終了後はDeveloper Centerへ移動し、「Mixer」というイベントに参加しました。会場にはさまざまなフードトラックが用意されており、昼食をとりながらコーディングをする人々の姿も見られました。また、特定のテーマごとにブースが設けられており、参加者同士で交流したり、Appleのエンジニアに直接質問したりできる貴重な場となっていました。さらに、Developer Center内ではGroup Labが開催されており、会場の内外いずれも非常に活気に満ちていました。 テーマごとに交流ができる場所 Mixerの会場図 Theater event 夜は、現地参加者の中で先着申し込みができた「Theater event」に参加しました。日中と同じくSteve Jobs Theaterで開催されるとのことで、再びあの空間に足を踏み入れることができました。 Theater eventでのSteve Jobs Theater 今回上映されたのは、今年公開されたスター・ウォーズ作品『The Mandalorian and Grogu』です。上映前にはスペシャルゲストによる対談が行われていました。その際、通路の透明なディスプレイに会話の文字起こしと手話がリアルタイムで表示されていました。Appleらしいアクセシビリティへの高い配慮に、とても驚かされました。スター・ウォーズにあまり精通していなかったため少し心配でしたが、思った以上に内容が分かりやすく、シーンによっては観客の歓声で盛り上がるなど、非常に楽しむことができました。 インタビュー中に字幕と手話が表示される透明なディスプレイ 併催コミュニティイベント らぷはCommunityKitが主催している2つのイベントに参加してきました。ひとつはPaul Hudson氏が開催した「What's new in iOS 27?」です。 luma.com WWDCでは、Day 1にAppleから全セッション動画とサンプルプロジェクトが公開されます。Hudson氏はSwiftUIやSwiftDataなどのサンプルプロジェクトを実際にビルドし、発生したエラーと修正方法を紹介してくださいました。すべてのサンプルプロジェクトが修正なしで期待どおりに動作するわけではないので、こうした知見を聞けるのは助かります。 会場の様子 もうひとつは「Swift Contributor Social」というイベントです。こちらはSwiftのコントリビューターと、それに興味がある人たちによる交流会です。まだコントリビューターではありませんが、どんな観点で活動しているのか聞いてみたくて参加しました。 luma.com 今回はstdlibのメンテナーでSpanの実装を担当された方にじっくりお話を聞くことができました。 developer.apple.com メモリ安全性への興味や今後の展望、コンパイラーチームが別途持っている構想と突き合わせた上での定期的な議論などを伺いました。Swift Forumsを眺めているだけでは得られない情報が多く、刺激的な時間でした。 ボウリング場のビリヤード台を囲んで自由に交流中 参加中、もしくは興味のあるWorking Groupのバッジ おすすめセッション集 優れたデザインのための原則 ZOZOTOWN iOSアプリの開発をしているつっきー( @tsuzuki817 )です。 今回のWWDCでは、Appleが考える優れたデザインの原則を扱うセッションがありました。デザインを単なる「見た目やふるまい」ではなく、「意図をもってものを作ること」と定義した上で、数々の重要な指針を解説しています。詳細は「 Principles of great design 」のセッションをご覧ください。 私が特に注目したのは、「主導権」「寛容さ」「柔軟性」という3つの原則のつながりです。ユーザーをあらかじめ決められた道に無理に誘導するのではなく、主導権を人々に委ね、自分のペースで探索させることの重要性が語られています。しかし、自由に探索できるようになると、ユーザーは誤って削除してしまったり意図しない操作をしてしまったりすることがあります。 そこで重要になるのが「寛容さ」です。操作を簡単に取り消せるようにし、大惨事を避けられるようにすることで、ユーザーに「いつでも回復できる」という自信を与え、安全な探索を支えることができます。さらに、ユーザーがアプリを使う状況(ランニング中や運転中など)や能力は人それぞれであるため、それらに適応する「柔軟性」を持たせることも強調されていました。 すべての人に合う単一のレイアウトを見つけるのは難しいため、ユーザー自身が好みに合わせて体験をカスタマイズできるようにすることが、最良の柔軟性です。セッションの最後では、これらの原則を正しく実行した自然な結果として、真の感情的なつながりである「喜び」が生まれると語られていました。これは製品に込めた「思いやりの総和」であるとのことです。自分がアプリを開発するうえで大事にしていることでもあり、同時に難しいと感じている点でもあります。 普段ZOZOTOWNの開発や個人開発をするなかで、ユーザーにどのような体験をさせたいのか迷うことが多くあります。このような原則に則って考えることで、よりよいプロダクトが作れそうだと期待しました。また、この考え方はZOZOTOWNのアプリ開発でぜひ意識していきたいです。さらにユーザーだけではなく、普段の仕事で起きるコミュニケーションにも活かせます。相手に選択肢を委ね、ミスを許容し、状況に柔軟に対応していきます。 Foundation Modelsフレームワークの新機能 ZOZOTOWN iOSアプリの開発をしているpe( @shumpei_nagata )です。 今年のWWDCでは、Foundation Modelsフレームワークの進化に興味を惹かれました。詳細は「 What's new in the Foundation Models framework 」で紹介されています。 このフレームワークは昨年登場し、アプリ上でオンデバイスの大規模言語モデルを扱えるようになりました。そして今年は画像入力(Vision)に対応しました。テキストだけだったプロンプトに Attachment(UIImage(...)) のように画像を差し込むと、その画像について回答が得られます。ガイド付き生成( @Generable )やツール呼び出しなどの既存APIもそのまま使えるので、これまで書いたコードを活かして画像対応に広げられます。 また、Foundation Modelsの導入に役立つ道具も増えてきました。生成AIは出力が確率論的に決まるので、生成結果の品質を確かめるのはなかなか骨が折れます。サービスの機能として安心して導入するには、品質を測定できる仕組みが必要です。そういった課題には Evaluations Framework が役立ちます。併せてAppleからオープンソースで公開された foundation-models-utilities も参考になります。コンテキスト超過を防ぐトランスクリプトの圧縮やSkills APIなど、Foundation Modelsをより便利に扱えるツールが揃っています。 このセッションが気になったのは、業務と個人開発のどちらでも視覚的な情報を多く取り扱うアプリを開発しているからです。進化したFoundation Modelsフレームワークを組み込むことで、アプリ上の体験を大幅に拡張できそうです。たとえば説明文の作成、属性の抽出、altテキストによるアクセシビリティの補完などが挙げられます。こうした処理が通信なし・無料で、しかもプライバシーを保ったまま端末の中で完結するのは非常に魅力的です。 とはいえ、既存のサービスへ導入するハードルは低くありません。Foundation Modelsは利用にiOS 26以降が必要で、今回の画像入力はiOS 27以降でないと動きません。その上、Apple Intelligence対応デバイスという条件もつきます。またZOZOTOWNはiOSアプリだけでなく、AndroidアプリやWebサイトなどさまざまなプラットフォームでお客様にご利用いただいています。OSや端末が限られる機能をそのまま主役に据えると、体験に大きな差が生じてしまうので、導入の見極めが難しい技術であるのも事実です。 それでも、アプリに導入するとどのような新しい体験を提供できるかとワクワクしました。技術的な好奇心もくすぐられるセッションでした! WWDC26 報告会 at LINEヤフー, ZOZO WWDC後の6月18日にLINEヤフーと合同で報告会を実施しました。 lycorptech-jp.connpass.com イッセーは「現地で盛り上がったWWDC26 Keynote」というタイトルで登壇しました。 speakerdeck.com 報告会では、実際に現地参加して見えたことを紹介しました。Keynoteで周囲のデベロッパーがどのようなテーマで盛り上がったのか、意外と反応が落ち着いていたテーマはどれか、思いもよらないサプライズは何だったのかを共有しています。一番印象的だったのは、事前に「これが目玉だろう」と考えていたトピックと、会場が実際に沸いたトピックのズレです。この差は公式の発表資料やニュース記事を後から追っても分かりません。世界中のデベロッパーがどのトピックに興味関心があったのかは、その場にいた人にしかわからない情報でした。 らぷはパネルディスカッションに参加し、印象的だったセッションや現地参加に必要な準備などを共有しました。先ほどのスマートグラスの活用や気になったセッションの話も取り上げています。「WWDCに現地参加するなら何をすべきですか?」という質問への回答は、他の参加者やAppleのスタッフの方と積極的にコミュニケーションすることです。これはLINEヤフーのパネラーの方と同じ意見でした。自分にはない考え方に触れたり、同じ考えをもつ同志に出会えたりできる機会です。ぜひ最大限に活用してください。 パネルディスカッションの様子 さいごに 今年のWWDCで感じた現地の雰囲気とおすすめセッション、報告会の様子をお届けしました。この記事を読んで現地での思い出を振り返ったり、新しいAPIの調査を始めて共有したりしていただけると嬉しいです。 ZOZOでは、一緒にサービスを作り上げてくれる仲間を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com
動画
該当するコンテンツが見つかりませんでした









