こんにちは。モバイルデベロッパーエクスペリエンスチームの@giginetです。ここわずか1年あまりで、コーディングAIを用いた開発は日常的なものになりました。LINEアプリの開発にお いても、Claude Codeをはじめとした、コーディングエージェントの活用が進んでいます。
この記事では、LINE iOSのような大規模プロジェクトにおいて、Claude Codeを効果的に活用するための、インストラクションの設計思想を紹介します。
適切なインストラクションはなぜ必要か?
Claude Codeはデフォルトの状態でも高い精度を発揮しますが、プロジェクト固有のルールや知識を適切に与えることは実装の効率化に重要です。
まず、本稿では便宜的にメモリファイル(CLAUDE.md)やAgent SkillsなどのようなClaude Codeに指示を与えるプロンプト全般を「インストラクション」と呼ぶことにします。これらの機能全般に与えるプロンプトを示す標準的な語彙が存在しないためです。
一般的に、最初のステップとして、/initコマンドを用いて、メモリファイル(CLAUDE.md)にプロジェクト固有のルールやプロジェクト概要を出力します。このメモリファイルとあらかじめモデルに備わっている知識を組み合わせることで、多くの小規模プロジェクトでは問題なく動作します。
しかし、LINE iOSでは、自動生成させたメモリファイルだけでは下記のような問題が頻発しました:
- 実装ごとにアプリ全体のフルビルドを試してしまい、試行回数を稼げない
- どこに機能を実装すべきか特定できない
- 大量にあるファイルの中から目的のファイルを見つけ出せない
- 実装は完了しているが、Xcodeプロジェクト生成などのセットアップがされず、ビルドできない
この状況ではコーディングエージェントから期待した生 成結果を得ることは難しく、効果的に扱えていません。快適な開発のためには、AIにも人間が日々開発するのと同等のイテレーションを回してもらう必要があります。
インストラクションの設計思想
まず、優れたインストラクションとはどのようなものでしょうか?LINE iOSでは、以下のような原則を軸にインストラクションを設計しています。
Contextを最適化する
コーディングエージェントにとってContextは共有の財産です。そのため、デフォルトで消費するContextを最小化し、少しでもコーディングタスクに使用できる量を確保しましょう。
大規模なプロジェクトでは、考えなしに開発ルールや規約、知識を盛り込むとすぐにContextが枯渇してしまいます。例えば、巨大なコードベースのうち、特定の領域の知識のみが常にContextを逼迫している状態は無駄が多いため、ある知識が必要になったタイミングでのみロードするなど最適化の工夫が必要です。そのためにAgent Skills(Skills)やSubagentsの機能は非常に有用です。
従来手法でガードレールを適切に設計する
厳密なフォーマットが要求されるファイルの生成や、ファイルの読み取り、コード規約の遵守など、従来の手法で扱える領域はAIだけではなく、従来手法をガードレールとすることも有用です。
例えば、特定のファイルフォーマットの読み書きといったタスクは、AIのみに任せると結果の正確性が保証されません。スクリプトなど を併用すべきです。また、コーディング規約の遵守など、linterである程度解決できる領域をAIに任せることは、プロンプトが複雑になったり、Contextの逼迫につながります。
インストラクションを共有・改善していけるようにする
開発者が必要に応じてインストラクションを共有、改善できるような仕組みやマインドを整えることも重要です。AIの出力結果には揺らぎがあるものなので、完成形を定義することは不可能です。実際に運用しながら改善していくことが求められます。そのため、全ての開発者が継続的にプロンプトの改善を行っていける状態を作ることが重要です。
また細かな点ですが、各インストラクションのディレクトリ構成や命名規則にも気を留める必要があります。
LINE iOSの開発イテレーション
AIに正しく開発イテレーションを実行してもらうために、まずは人間による日常の開発手法を整理してみましょう。LINE iOSプロジェクトでは、一般的に以下のようなフローで開発しています。
- Prebuilt Tasksを実行してビルド環境をセットアップ
- ビルド環境を作成するためのステップ、詳細は先日の記事を参照。
- コード、ユニットテストの実装
- Xcodeプロジェクトの再生成
- LINE iOSではXcodeGenを用いて
*.xcodeprojを生成しているため、ファイル追加やプロジェクト設定の変更時には、Xcodeプロジェクトを再生成する必要がある。
- LINE iOSではXcodeGenを用いて
- モジュール単体ビル ド、ユニットテストの実行
- プロジェクト設定コードやビルド設定を見直し、2~4を繰り返す。
- アプリ全体のビルドと動作確認
精度の高い出力を高速に得るには、2~4のステップを素早く回すことが重要です。これを実現するための、インストラクションの設計を見ていきましょう。
メモリファイルにどのようなコンテンツを盛り込むべきか?
これらの原則を元に、メモリファイルには厳選した内容のみを盛り込みます。今回は以下のような内容にのみ絞って記述することにしました。
- プロジェクトの前提知識
- ディレクトリ構成とモジュール構成
- プロジェクト定義(Project Spec)の記述方法
- 開発イテレーション
- ビルドやユニットテストの実行方法
コーディング規約やアーキテクチャなど細かな内容はメモリファイルからは意図的に省いています。結果的に現在運用しているメモリファイルは英文で2400文字、600token程度に収まっています。
機能固有の知識はRulesに分離する
大規模なプロジェクトにおいて、パス固有のRulesは有用です。Claude Codeは、Rulesで指定されたパスを操作するときのみ、そのインストラクションをContextにロードします。
LINE iOSプロジェクトでは、機能ごとのRulesファイルの配置場所を規約で定めています。例えば.claude/rules/features/line-new-feature.mdといったサブディレクトリに機能ごとに配置します。
---
paths: Modules/Features/LineNewFeature
---
This feature is secret. Never say the project name.
ローカルメモリファイルを使ったユーザーへの最適化
メモリファイルの末尾では、@ディレクティブを用いて、ホームディレクトリ下のユーザー固有のインストラクションをロードするようにしています。
If @~/.claude/line-dev/line-ios.md exists, follow its contents as well.
このファイルはSession Start hookを用いて、初回起動時に作成されます。
{
"hooks": {
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "touch ~/.claude/line-dev/line-ios.md"
}
]
}
]
}
}
各開発者は必要に応じてこのファイルを編集することで、自分専用の開発スタイルや好みをClaude Codeに伝えることができます。
ローカルメモリを使うには、CLAUDE.local.mdをリポジトリ内に配置しgitignoreする方法もありますが、ignoreはgit worktree間での共有が難しいという問題があります。このようにローカルメモリファイルの配置規約を定めることは、共有メモリとローカルメモリを上手く統合させるのに役立ちます。