Claude Code モバイル開発 Flutter React Native Swift Kotlin Compose CLAUDE.md AIツール Cursor

モバイル開発のためのAIツール完全ガイド:Flutter・React Native・ネイティブ(2026年版)

The Prompt Shelf ·

モバイル開発は、AIコーディングツールが実力を発揮できる場所でもあり、逆に目に見える形で失敗しやすい場所でもある。フレームワークは強い制約を持ち、ビルドツールチェーンは壊れやすく、コード生成の落とし穴はフレームワークごとに異なる。汎用的なCLAUDE.mdでは、Claude Codeが3タスクに1回は間違った方向に走ることになる。

このガイドでは、Flutter・React Native・Swift/SwiftUI・Kotlin/Composeという4つの主要なモバイルスタックそれぞれで、Claude Code・Cursor・OpenAI Codex CLI・Aiderがどう機能するかを整理する。各フレームワーク向けのCLAUDE.md / AGENTS.mdテンプレートはそのままコピーして使えるようにした。

Claude CodeでFlutterを使っていてそのスタックの深掘りを求めているなら、Claude Code Flutter完全ガイドでRiverpod・クリーンアーキテクチャ・テストを詳しく扱っている。この記事はその補完版として、スタックを切り替えたときに何が変わるか、各フレームワークでAIツールをどう設定するかにフォーカスする。

2026年のモバイルAIツール状況

AIコーディングツールは、「モバイル開発で使えるか?」という問いを超えた。今問うべきは「自分のスタックに合わせてどう設定すればうまく機能するか?」だ。

核心的な課題は、モバイルフレームワークがデフォルトではAIツールが知らない強い規約を持っていること:

  • Flutter: Dartの型システム、Riverpodのリアクティブモデル、build_runnerによるコード生成
  • React Native: JavaScript/TypeScriptブリッジ(現在はJSI/新アーキテクチャに移行中)、Metroバンドラーの癖、プラットフォーム固有のネイティブモジュール
  • Swift/SwiftUI: Swiftの値セマンティクス、SwiftData/Core Dataのパターン、async/awaitの並行処理モデル、CombineとSwift Concurrencyの使い分け
  • Kotlin/Compose: コルーチン、Flow、Composeの再コンポジション、Hilt依存性注入、Jetpackのパターン

明示的なルールがなければ、Claude Codeはコンパイルは通るがアーキテクチャを壊すコードを生成する。これはコンパイルエラーよりも質が悪い場合が多い。

ツール選択マトリクス

2026年現在、4つの主要ツールがモバイルスタックでどう機能するかを整理する:

Claude CodeCursorCodex CLIAider
Flutter優秀(Dart 3対応、コード生成に強い)良好(補完が強い)まあまあ(build_runnerフックなし)良好(git-native、差分ベース)
React Native優秀(新アーキテクチャ対応)優秀(JS/TSエコシステムが強み)良好(npmスクリプト統合)良好
ネイティブiOS (Swift)とても良い(Swift 6並行処理対応)優秀(Xcodeコンテキスト)まあまあまあまあ(Xcodeプロジェクトモデル非対応)
ネイティブAndroid (Kotlin)とても良い(Compose再コンポジション対応)とても良い良好良好

どのツールをいつ使うか:

  • Claude Code: アーキテクチャ作業、リファクタリング、CLAUDE.md / AGENTS.mdのルール作成、深いコンテキストが必要なタスク。大規模モバイルコードベースでは1Mコンテキストウィンドウが実際に効く。
  • Cursor: オートコンプリートによる高速イテレーション、インライン編集、エディタ中心のワークフロー。
  • Codex CLI: スクリプト化・再現可能なタスク(「このモデルのCRUD画面を生成」など)、CI/CDパイプライン統合。
  • Aider: クリーンな差分としての変更が必要なgit-nativeワークフロー。コードレビュー準備に優秀。

経験豊富なモバイル開発者の多くは、Claude CodeとCursorを組み合わせて使う形に落ち着く。エディタはCursor、アーキテクチャ決定と大規模リファクタはClaude Codeという分担だ。

フレームワーク × ツール互換性マトリクス

フレームワーク別セクションの前に、何が機能して、何が設定を要し、何を避けるべきかをまとめる。

Flutter

タスクClaude CodeCursorCodex CLIAider
Widget生成うまく動くうまく動く良好良好
Riverpodプロバイダルール必要補完設定が必要苦手ルール必要
build_runnerワークフロー明示的ルール必要明示的ルール必要苦手明示的ルール必要
クリーンアーキテクチャルーティングルールあれば動くルールあれば動くまあまあうまく動く
プラットフォーム固有コードルール必要良好まあまあ良好

React Native

タスクClaude CodeCursorCodex CLIAider
コンポーネント生成優秀優秀良好良好
新アーキテクチャ(JSI/TurboModules)良好とても良いまあまあまあまあ
ナビゲーション(React Navigation)うまく動くうまく動く良好良好
ネイティブモジュールブリッジング詳細なルール必要詳細なルール必要苦手苦手
Expo vs. ベアワークフロールール必要良好良好良好

ネイティブiOS (Swift/SwiftUI)

タスクClaude CodeCursorCodex CLIAider
SwiftUIビュー構成とても良い優秀良好良好
Swift 6並行処理ルール必要とても良いまあまあまあまあ
SwiftData / Core Dataルール必要良好まあまあ苦手
Package.swift依存関係良好良好良好良好
CombineとSwift Concurrencyの使い分け明示的ルール必要ルール必要苦手まあまあ

ネイティブAndroid (Kotlin/Compose)

タスクClaude CodeCursorCodex CLIAider
Composable関数とても良い優秀良好良好
Hilt DIの配線ルール必要とても良いまあまあ良好
ViewModel + Flowパターンうまく動くうまく動く良好良好
Roomデータベースルール必要良好良好良好
Gradle設定ルール必要良好良好良好

フレームワーク別ワークフローレシピ

Flutter

FlutterはDartの型システムとコード生成の組み合わせにより、他のフレームワークよりも摩擦点が多いワークフローになる。良いニュースは、Claude Codeを正しく設定すれば、他では太刀打ちできないレベルでボイラープレートを処理できること。

FlutterとAIツールの核心的な問題:

Flutterプロジェクトはbuild_runnerを使ってアノテーションからコードを生成する(@freezed@riverpod@RestApi@JsonSerializable)。AIツールはアノテーション付きファイルを変更した後にbuild_runnerを実行すべきことを知らず、.g.dart / .freezed.dartファイルが生成されたものであることも知らない。直接編集しようとしてしまう。

CLAUDE.mdでこれを明示的に扱う必要がある。以下は複数のAIツールを使うチーム向けに、Flutterガイドを拡張したルールだ:

## コード生成 — AIツールルール

### build_runnerが必要なもの
以下のアノテーションを持つファイルを変更した後、build_runnerが必ず必要:
- @freezed (Freezedモデル)
- @riverpod (Riverpodプロバイダ、ノティファイア)
- @RestApi (Retrofitクライアント)
- @JsonSerializable (JSONモデル)
- @TypedGoRoute (go_routerの型安全ルート)

### AIツールへのルール
- .g.dart や .freezed.dart ファイルを直接編集しない
- Provider()、StateNotifierProvider()、FutureProvider()を直接使うプロバイダを生成しない
  — 常に@riverpodアノテーションパターンを使う
- アノテーション付きファイルへの変更後は必ずこのコマンドを出力:
  dart run build_runner build --delete-conflicting-outputs
- .g.dartファイルがおかしければ、手動修正せず開発者にbuild_runner実行を伝える

### Cursor固有ルール
このプロジェクトでCursorと組み合わせる場合:
- カスタムコマンドを設定: Ctrl+Shift+B → dart run build_runner build --delete-conflicting-outputs
- パス指定で.g.dartファイルをインポートするオートコンプリート提案は受け入れない
  (常にソースファイルからインポート)

Flutter + Claude Code のワークフロー(マルチセッションプロジェクト):

データフェッチを含む新しい画面を追加するタスク:

# タスク1: ドメイン層の生成
claude "ProductReviewのドメインエンティティとリポジトリインターフェースを追加。
features/users/domain/の既存Userエンティティパターンに従う。実装は不要。"

# タスク2: データ層の生成
claude "作成したインターフェースのProductReviewRepositoryImplを実装。
UserRepositoryImplのパターンを使う。リモートデータソースは今はモック。"

# タスク3: プロバイダの生成
claude "features/users/presentation/providers/の@riverpodアノテーションパターンに従い
ProductReview用Riverpodプロバイダを追加。リストプロバイダとuserIdパラメータパターンの
単一アイテムプロバイダの両方。"

# タスク3の後にbuild_runnerを実行:
dart run build_runner build --delete-conflicting-outputs

# タスク4: UIの生成
claude "ProductReviewListPageとProductReviewCardウィジェットを作成。
リストプロバイダにはAsyncValue.whenパターンを使う。UserListPageを参照として使う。"

このようにタスクを分割することで、各Claude Codeセッションを焦点を絞った状態に保ち、4つの層全体でコードを一度に生成しようとするのを防ぐ。同時に全部やろうとすると、build_runner出力が見えない状態で不整合が生まれやすい。

Cursor + Claude Code のハイブリッドワークフロー(Flutter):

Cursorのオートコンプリートはプロジェクト全体を見てパターンを学習するのでDartに強い。効果的な分担:

  • Cursor: ウィジェット構成、ボイラープレートの補完、ファイル内リファクタリング
  • Claude Code: アーキテクチャ決定、クロスファイルリファクタリング、新機能のエンドツーエンド生成、テスト作成

リスクはCursorの提案がCLAUDE.mdのルールを知らないこと。プロジェクトルートに.cursorrulesファイルを作成して重要なルールを反映させる:

# Flutterプロジェクトルール — Cursor

## 状態管理
- ONLY Riverpod with @riverpodアノテーション (riverpod_generator)
- setStateをfeature stateに使わない
- ChangeNotifier、ValueNotifier、GetX、Blocを提案しない
- ref.watch()はbuild()内、ref.read()はコールバック内のみ

## コード生成
- @freezed、@riverpod、@RestApi、@JsonSerializableのファイル変更後は
  常に開発者に通知: dart run build_runner build --delete-conflicting-outputs
- .g.dart や .freezed.dart ファイルを直接編集しない

## ナビゲーション
- go_routerのみ使用 (context.go, context.push, context.pop)
- Navigator.of(context).pushは使わない

## ウィジェットパターン
- Riverpodが絡む場合はStatelessWidgetよりConsumerWidgetを優先
- 可能な限りconstコンストラクタ
- SafeAreaは全ページルートコンテンツをラップ

React Native

React NativeのAIツール事情はFlutterより複雑だ。エコシステムが分断されているため — Expo vs. ベアワークフロー、新アーキテクチャ vs. 旧アーキテクチャ、Bridgeベースのネイティブモジュールからのマイグレーション。

AIツールに必要なコンテキスト:

## React Nativeプロジェクト設定

### アーキテクチャ
- React Native 0.74+ で新アーキテクチャ有効(JSI、TurboModules、Fabric)
- Expo: [bare / managed] ワークフロー
  (どちらか一方を削除)
- JavaScript/TypeScript: TypeScript strict mode
- ナビゲーション: React Navigation 7 (Stack, Tab, Drawer)
- 状態管理: [Zustand / Jotai / Redux Toolkit]
  (どちらか一方を削除)
- 非同期: React Query(サーバー状態)+ Zustand(クライアント状態)
- スタイリング: StyleSheet(NativeWindを使う場合はTailwindアプローチ)
- ネイティブモジュール: Expo Modules API(旧NativeModulesブリッジではない)

### 新アーキテクチャルール
- 新機能にはNativeModulesブリッジを使わない — TurboModulesを使う
- NativeModules.* の旧呼び出しを使わない
- カスタムネイティブモジュールにはExpo Modules APIを使う
- NativeModules.*を見つけたらtech debtとしてフラグを立てる

### プラットフォーム固有コード
- Platform.OS === 'ios' と Platform.OS === 'android'(直接'ios'ではない)
- プラットフォーム固有ファイル: ComponentName.ios.tsx / ComponentName.android.tsx
- クロスプラットフォーム実装を優先し、必要な場合のみプラットフォーム分岐
- StyleSheet.create() — JSXにインラインスタイルを書かない

### Metroバンドラー
- 動的式でrequire()を使わない — Metroがツリーシェイクできない
- 循環インポートを避ける — 大規模ではMetroが苦手
- 画像アセット: 静的にインポート、動的パスを使わない

React Navigationのパターン — 落とし穴が多いエリア:

React Navigation 7はv6から型付けが大きく変わった。明示的なルールがなければ、Claude Codeはv7プロジェクトでもv6のパターンを生成することが多い:

## ナビゲーションルール (React Navigation 7)

### ルート型定義
// ナビゲーターレベルで型を定義:
type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Settings: undefined;
};

// navigationプロップを型付け:
type ProfileScreenNavigationProp = NativeStackNavigationProp<
  RootStackParamList,
  'Profile'
>;

### 使ってはいけないもの
- TypeScript型なしのnavigation.navigate('ScreenName')
- ジェネリック型パラメータなしのuseNavigation()
- タブナビゲーターでのnavigation.push()(jumpTo()を使う)
- router.back() — navigation.goBack()を使う

Expo固有のルール:

## Expo固有ルール

### EASビルド
- Expoコンフィグプラグインを使う(ネイティブモジュールファイルを直接変更しない)
- app.json / app.config.js — アプリ設定の唯一の正規情報源
- managedワークフローではandroid/やios/ディレクトリを手動編集しない
- 新しいネイティブ依存関係: npx expo install + EASビルドが必要

### 環境変数
- クライアント側変数はEXPO_PUBLIC_プレフィックス付き.envを使う
- サーバー専用シークレット: EAS Secrets(gitにコミットされた.envではない)
- アクセス: process.env.EXPO_PUBLIC_API_URL(process.env.API_URLではない)

ネイティブiOS(Swift / SwiftUI)

Swift/SwiftUIはAIツールのサポートが最も動的に変化している。Swift 6の厳格な並行処理チェック、新プロジェクトではCore DataをSwiftDataが置き換えていること、CombineからSwift Concurrencyへの成熟、これらすべてが影響する。古いSwiftコードベースで学習したAIツールは非推奨のパターンを提案する。

AIツールに必要なバージョンコンテキスト:

## iOSプロジェクト設定

### Swiftバージョンと並行処理
- Swift 6(厳格な並行処理チェック有効)
- Swift Concurrency(async/await、actors、structured concurrency)— 主要モデル
- Combine: 既存コードのみで使用。新しいCombineを導入しない
- 新しい非同期コードはすべてasync/awaitとactorsを使う

### データ永続化
- 新モデル: SwiftData (@Model, @Query, ModelContext)
- レガシーモデル: Core Data(既存のみ、新エンティティを追加しない)
- 新機能にCore Dataを使わない — SwiftDataを使う

### アーキテクチャ
- [MVVM / MV / TCA](どれか一つを残す)
- Observationフレームワーク(@Observable) — 新コードにObservableObject/@Publishedを使わない
- ナビゲーション: NavigationStack with NavigationPath

### 最小デプロイターゲット
- iOS 17.0(SwiftData、@Observable、NavigationStackが使える)
- iOS 17.0以降のAPIには@available(iOS X.0, *)チェックを必ず付ける

Swift 6並行処理 — AIツールが最も苦労するところ:

Swift 6の厳格な並行処理はAIツールにはなじみのないコンパイルエラーを生成する。最も一般的なミス:

## Swift 6並行処理ルール

### アクターの分離
- UIに関係する型はすべて@MainActor(ViewModel、ObservableObjectなど)
- UI以外のサービス: 共有可変状態にはactorを使う
- DispatchQueue.main.asyncを使わない — await MainActor.run { }または@MainActorをクラスにつける

### Sendable
- アクター境界を越えるとSendableが必要
- 値型(struct、enum)はデフォルトでSendable
- クラスは明示的なSendable適合または@unchecked Sendableが必要(なぜ安全か説明するコメント付き)
- コメントなしで並行処理警告を@unchecked Sendableで抑制しない

### 使ってはいけないもの(Swift 5のパターン)
- DispatchQueue.main.async { } → @MainActorまたはawait MainActor.runを使う
- 新しい非同期処理にコンプリーションハンドラ → async/awaitを使う
- 新ViewModelにObservableObject / @Published → @Observableを使う

SwiftDataのパターン:

## SwiftDataルール

### モデル定義
@Model
final class Task {
    var title: String
    var isCompleted: Bool
    var createdAt: Date
    
    init(title: String) {
        self.title = title
        self.isCompleted = false
        self.createdAt = .now
    }
}

// Core Dataパターンは新モデルに使わない:
// NSManagedObject、@NSManaged など

### クエリの使い方
// SwiftUIビューの中:
@Query(sort: \Task.createdAt, order: .reverse) private var tasks: [Task]

// 述語あり:
@Query(filter: #Predicate<Task> { !$0.isCompleted }) private var pendingTasks: [Task]

### ModelContextの操作
// 挿入:
modelContext.insert(Task(title: "新タスク"))

// 削除:
modelContext.delete(task)

// 保存は自動 — ほとんどの場合modelContext.save()を手動で呼ばない
// 例外: バックグラウンド操作の前

### 禁止
- Core DataとSwiftDataを同じモデルグラフに混在させる
- アクター境界を越えてmodelContextを渡す(明示的な受け渡しを除く)
- バックグラウンドコードでModelContainer.mainContextから直接フェッチ

XcodeのコンテキストとClaude Code:

Claude Codeはネイティブなxcodeプロジェクトファイルの認識がない。新ファイル追加時に.xcodeprojを更新できないため、CLAUDE.mdに以下を記載する:

## Xcodeプロジェクトルール

### ファイルの追加
新しいSwiftファイルを追加するとき:
1. 正しいグループディレクトリにファイルを作成
2. Xcodeのプロジェクトナビゲーターにドラッグするよう通知(またはXcodeの「Add Files」)
3. どのターゲットに属するか確認

Swift Package Manager (Package.swift) を使っている場合は、
Package.swiftの正しいターゲットに自動でファイルを追加する。

ネイティブAndroid(Kotlin / Compose)

Kotlin/Composeは新規Androidアプリ開発のデファクトスタンダードになったが、GradleとJetpackのパターンには複雑さが残っており、AIツールが頻繁に誤設定する。

設定コンテキスト:

## Androidプロジェクト設定

### 言語とバージョン
- Kotlin 2.x(K2コンパイラ)
- Jetpack Compose(UI層 — 新機能にXMLレイアウトを使わない)
- 最小SDK: 24 / ターゲットSDK: 35
- Compose BOM: [現在バージョン — libs.versions.tomlを確認]

### アーキテクチャ
- MVVM + MVI(単方向データフロー)
- ViewModel (Jetpack) + StateFlow + sealed class for UI state
- リポジトリパターン: ViewModel → Repository → DataSource
- 依存性注入: Hilt(Koinでも手動DIでもなく)
- ナビゲーション: Compose Navigation(Fragmentナビゲーションではない)

### 非同期
- コルーチン + Flow(主要モデル)
- 新コードにRxJavaを使わない
- ViewModelのコルーチンにはviewModelScope
- ActivityやFragmentにはlifeycleScope(稀 — ViewModelを優先)

### ビルドシステム
- バージョンカタログ付きGradle(libs.versions.toml)
- アノテーション処理にKSP(KAPTではない)
- Composeコンパイラプラグイン: [libs.versions.tomlのバージョン]

Composeの再コンポジション — AIツールが微妙なバグを作る場所:

Composeの宣言的モデルは、効率的なUIを書くために再コンポジションの理解が必要だ。Claude Codeはしばしば不必要な再コンポジションを引き起こすコードを生成する:

## Composeパフォーマンスルール

### 状態のホイスティング
- 状態はViewModelや最高位のComposableに持つ
- ステートレスなComposableは状態とコールバックを受け取る — 葉コンポーネントでViewModelを直接読まない
- パターン: Screen → ViewModel → UIState。ScreenがUIStateをコンポーネントに渡す

### 不要な再コンポジションを避ける
// Bad — コンポーネント内でViewModelを直接読む:
@Composable
fun UserName(viewModel: UserViewModel = hiltViewModel()) {
    Text(text = viewModel.userName) // ViewModelの状態変化で何でも再コンポーズ
}

// Good — 必要なものだけ受け取る:
@Composable
fun UserName(name: String) {
    Text(text = name) // nameが変わったときだけ再コンポーズ
}

### LazyColumnのkeys
// 安定したキーを必ず提供:
LazyColumn {
    items(items = users, key = { it.id }) { user ->
        UserItem(user = user)
    }
}

### 派生状態
- 計算された状態にはremember { derivedStateOf { ... } }を使う — 再コンポーズ内で計算しない
- Composableスコープ内でコストの高い計算を直接行わない

Hilt依存性注入 — アノテーションの迷宮:

Hiltは全Androidライブラリの中で最もアノテーションが多く、AIツールが頻繁に混同する:

## Hiltルール

### コンポーネントアノテーション
- @HiltAndroidApp — Applicationクラス(プロジェクトに1つ)
- @AndroidEntryPoint — Activity、Fragment、View、Service(ViewModelではない)
- @HiltViewModel — ViewModel
- @Inject — コンストラクタインジェクション(フィールドインジェクションより優先)
- @Provides — @Moduleの中で、自分が所有しない型に
- @Binds — @Module @InstallInの中で、インターフェースのバインディングに

### 禁止事項
- ViewModelに@AndroidEntryPointを使わない — @HiltViewModelを使う
- ViewModelのフィールドインジェクションに@Injectを使わない — コンストラクタインジェクションを使う
- @InstallInなしで@Moduleを作らない
- @ViewModelScopedがより適切な場合に@ActivityScopedを使わない

ViewModel + Flowパターン — 2026年のAndroidの正規パターン:

## ViewModel + Flowパターン

### UI状態
sealed interface UserDetailUiState {
    object Loading : UserDetailUiState
    data class Success(val user: User) : UserDetailUiState
    data class Error(val message: String) : UserDetailUiState
}

### ViewModelの構造
@HiltViewModel
class UserDetailViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val userRepository: UserRepository
) : ViewModel() {
    
    private val userId: String = checkNotNull(savedStateHandle["userId"])
    
    val uiState: StateFlow<UserDetailUiState> = userRepository
        .observeUser(userId)
        .map { user -> UserDetailUiState.Success(user) }
        .catch { e -> emit(UserDetailUiState.Error(e.message ?: "不明なエラー")) }
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5_000),
            initialValue = UserDetailUiState.Loading
        )
}

// Composableの中での収集:
@Composable
fun UserDetailScreen(viewModel: UserDetailViewModel = hiltViewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
    // ...
}

// collectAsState ではなく collectAsStateWithLifecycle を必ず使う —
// ライフサイクルを尊重し、バックグラウンド時に収集を停止する

フレームワーク別のCLAUDE.md / AGENTS.mdテンプレート

そのままコピーして使えるテンプレートをフレームワーク別に用意した。

Flutter — 最小CLAUDE.md

# Flutterプロジェクト — AIルール

## スタック
- Flutter 3.x / Dart 3.x / Null Safety
- 状態管理: Riverpod (riverpod_annotation, riverpod_generator)
- アーキテクチャ: Feature-firstクリーンアーキテクチャ
- ナビゲーション: go_router
- HTTP: Dio + Retrofit(コード生成)
- モデル: Freezed + json_serializable
- ビルド: build_runner

## 絶対に守るルール
1. 状態管理: @riverpodアノテーションパターンのみ。禁止: setState(featureの状態に)、ChangeNotifier、GetX、Bloc、Providerパッケージ
2. ナビゲーション: go_routerのみ。禁止: Navigator.of(context).push、MaterialPageRoute直接使用
3. @freezed、@riverpod、@RestApi、@JsonSerializable、@TypedGoRouteが付いたファイルへの変更後は常にbuild_runnerコマンドを出力
4. .g.dart や .freezed.dart を直接編集しない
5. ref.watchはbuild()内、ref.readはコールバック内 — 入れ替え禁止

## build_runnerコマンド
dart run build_runner build --delete-conflicting-outputs

## プロジェクト構造
lib/
├── core/           # 共有インフラ
├── features/       # feature-first(featureごとにdata/domain/presentation)
└── shared/         # 本当にクロスfeatureなウィジェット

React Native — 最小CLAUDE.md

# React Nativeプロジェクト — AIルール

## スタック
- React Native 0.74+ / 新アーキテクチャ(JSI有効)
- 言語: TypeScript (strict: true)
- ナビゲーション: React Navigation 7
- 状態管理: Zustand(クライアント)+ React Query(サーバー)
- スタイリング: StyleSheet(インラインスタイル禁止)
- ネイティブモジュール: Expo Modules API
- [Expo managed / Expo bare / Bare RN]

## 絶対に守るルール
1. 新機能にNativeModulesブリッジを使わない — TurboModulesまたはExpo Modules APIを使う
2. すべてのコンポーネントをTypeScriptで明示的なprop型付き(anyは禁止)
3. TypeScriptのparamList型付きナビゲーション — 型なしのnavigate()は禁止
4. プラットフォーム固有コード: Platform.OSチェックまたは.ios.tsx / .android.tsxファイル
5. インラインスタイル禁止 — StyleSheet.create()を常に使う
6. 動的なrequire()禁止 — Metroが最適化できない

## 禁止パターン
- NativeModules.*(TurboModulesを使う)
- React.FCジェネリック(明示的な関数シグネチャを使う)
- サーバーデータにuseState(React Queryを使う)
- データフェッチにuseEffect(React Queryを使う)

ネイティブiOS — 最小CLAUDE.md

# iOSプロジェクト — AIルール

## スタック
- Swift 6 / SwiftUI
- 最小デプロイ: iOS 17.0
- アーキテクチャ: @Observableを使ったMVVM
- データ: SwiftData
- 非同期: Swift Concurrency (async/await, actors)
- 新コードにCombineを使わない
- 新機能にUIKitを使わない

## 絶対に守るルール
1. Swift 6の厳格な並行処理 — SendableとアクターアイソレーションエラーをすべてFixし、抑制しない
2. すべてのViewModelとUI更新コードに@MainActor
3. 新しい永続化: SwiftDataのみ。新規Core Dataエンティティを追加しない
4. 新しいリアクティブコード: @Observable。新規ObservableObject / @Publishedを追加しない
5. 新しい非同期コード: async/await。新規コンプリーションハンドラとDispatchQueue.main.asyncを使わない
6. NavigationStackと型付きNavigationPath — NavigationLink(destination:)を使わない

## ファイルの追加
新しい.swiftファイルはXcodeプロジェクトナビゲーターに手動で追加する必要がある旨を通知する。
Claude Codeは.xcodeproj を直接更新できない。

ネイティブAndroid — 最小CLAUDE.md

# Androidプロジェクト — AIルール

## スタック
- Kotlin 2.x / K2コンパイラ
- Compose UI(新機能にXMLレイアウトなし)
- アーキテクチャ: MVVM + 単方向データフロー
- DI: Hilt
- 非同期: コルーチン + Flow(RxJavaなし)
- ナビゲーション: Compose Navigation
- データベース: Room(KSP使用、KAPTなし)
- HTTP: Retrofit + OkHttp

## 絶対に守るルール
1. すべてのDIにHilt — 手動インジェクションもKoinも不可
2. アノテーション処理にKSP(Room、Hilt)— KAPTは絶対に使わない
3. UI状態はsealed interface/class — Booleanフラグの羅列は禁止
4. ComposableでcollectAsStateWithLifecycle(collectAsStateではない)
5. ViewModel → UIにはStateFlow、ワンショットイベントにはSharedFlow
6. 新コードにRxJavaを使わない
7. Composable関数: ステートレスなコンポーネントは状態とコールバックのみを受け取る

## Gradle
- バージョンカタログ: libs.versions.toml(バージョンの唯一の情報源)
- build.gradle.ktsファイルに依存バージョンをハードコードしない
- KSPプロセッサ、KAPTではない

マルチフレームワーク AGENTS.md

複数ターゲットまたはフレームワークを含むコードベースでAIエージェントタスクを実行する場合:

# AGENTS.md

## プロジェクト構造
このリポジトリには以下が含まれる:
- /mobile/flutter/ — FlutterモバイルアプリSS
- /mobile/rn/ — React Nativeウェブコンパニオン
- /backend/ — Node.js API

## エージェントのスコープルール
- モバイルタスクは分離: /mobile/flutter/への変更が/mobile/rn/に触れてはいけない
- タスクに明示的なAPI変更が含まれない限り/backend/を変更しない
- クロスプラットフォームの変更(共有型、APIコントラクト): /shared/のみを変更し、
  各プラットフォームに個別に適用

## タスクの分解
複数プラットフォームにまたがるタスクは以下に分解:
1. 共有コントラクトの変更(/shared/)
2. Flutter実装
3. React Native実装
各ステップは独立してテスト可能であること。

## プラットフォーム別ビルドコマンド
- Flutter: cd mobile/flutter && flutter build apk --debug
- React Native: cd mobile/rn && npx react-native run-android
- Backend: cd backend && npm test
- 全体: Makefileターゲットを使う(make test-all, make build-all)

## 禁止
- 間違ったディレクトリからプラットフォーム固有のビルドコマンドを実行
- プラットフォーム間でインポートを混在させる
- FlutterタスクからpackkageJsonを変更、RNタスクからpubspec.yamlを変更

参考実装(実在するオープンソースアプリ)

以下のオープンソースアプリは上記のパターンを実際に示している。新しいCLAUDE.mdルールを設定する前に「正しい実装」をClaude Codeに見せるのに役立つ。

Flutter

flutter_shopping_app(VGV) Very Good Venturesのサンプルアプリ。クリーンアーキテクチャ、Riverpod、go_router。プロダクショングレードのパターン。新プロジェクトでCLAUDE.mdルールを設定する際の良いリファレンス。

holobooth Flutterチームの公式サンプル。カメラ/AR統合パターンとプラットフォームチャネルを必要とするプラットフォーム固有コードを示している。

React Native

Rainbow Ethereumウォレットアプリ。複雑なナビゲーション、ネイティブモジュール統合(生体認証、カメラ)、TypeScriptの規律の良い例。重要なネイティブコードを持つアプリのCLAUDE.mdルール構築の参考に。

ネイティブiOS

TCA サンプル TCAを使っているならこのサンプルが正規パターンを示している。TCA固有の規約(Reducer、Store、ViewStore)に関するルール設定に有用。

Scrumdinger AppleのSwiftUIチュートリアルアプリ。SwiftDataとSwift Concurrencyを使用。プロダクション規模ではないが、iOS 17の正しいパターンを示している。

ネイティブAndroid

Now in Android Googleのリファレンスアプリ。Hilt、Compose、KSP、バージョンカタログ。AndroidのCLAUDE.mdルール設定の参考として最良。

Jetpack Compose Samples JetSnack、Owl、Rally — それぞれ異なるCompose UIパターンを示している。CLAUDE.mdに「このパターンに従う」として貼る具体的な例の良いソース。

落とし穴とFAQ

なぜClaude Codeは間違った状態管理パターンを生成し続けるのか?

状態管理はどのモバイルフレームワークにも複数の有効なアプローチがあり、明示的な禁止なしではClaude Codeはその場に合うパターンを使う。修正方法は常に明示的なルール:

## 状態管理ポリシー
このプロジェクトはONLY [Riverpod / Zustand + React Query / @Observable / StateFlow]を使用。
絶対に導入しないこと: [禁止パターンのリスト]。
例外が必要と思ったら実装前に確認すること。

禁止リストはポジティブなルールと同じくらい重要だ。


CursorがCLAUDE.mdのルールを守らないのはなぜ?

CursorはデフォルトでCLAUDE.mdを読まない。必要なのは:

  1. プロジェクトルートの.cursorrulesファイル(Cursorが自動で読む)
  2. Cursor設定パネルでプロジェクトコンテキストにルールを追加

.cursorrulesファイルはCLAUDE.mdから最重要なルールを反映させる。特に状態管理、ナビゲーション、コード生成のルール。全部を複製する必要はない。


旧アーキテクチャから新アーキテクチャへの移行中のプロジェクトはどう扱うか?

移行はAIツールに最も難しいシナリオの一つだ。コードベースに両方のパターンが混在しているため:

## 移行コンテキスト

現在[旧パターン]から[新パターン]へ積極的に移行中。

### 新しいコードのルール(厳格)
全ての新規ファイル: [新パターンのルール]

### レガシーコードのルール
[レガシーパス]内の既存ファイルに触る場合は、差分サイズを最小化するために
既存パターンを使ってよい。タスクが明示的に求めない限りレガシーコードをリファクタしない。

### 移行済み
- 完了: [移行済みモジュールのリスト]
- 進行中: [現在のモジュール]
- 未着手: [残りのモジュール]

### 禁止
- 単一ファイル内でパターンを混在させる
- 近くのファイルが使っていても新規ファイルに旧パターンを導入する

Swift 6並行処理がAIの提案を壊し続けるのはなぜか?

Swift 6の厳格な並行処理チェックはコンパイル時にデータレースを検出する。主な問題:

  1. @MainActorの代わりにDispatchQueue.main.async
  2. アクター境界を越えてnon-Sendable型を渡す
  3. 適切なTaskラッピングなしで同期コンテキストからasync関数を呼ぶ
  4. 複数のコンテキストから共有状態を変更する

解決策: このガイドのSwift 6並行処理ルールのセクションをCLAUDE.mdに含め、特定のルールを追加する。「すべての並行処理警告はエラー。なぜ安全かを説明するコメントなしに@unchecked Sendablenonisolated(unsafe)で抑制しない」。


モバイルのCLAUDE.mdの適切な詳細度は?

過剰な仕様化には実コストがある。非常に長いCLAUDE.mdファイルはClaude Codeを遅くし、パターンが進化した時のルール更新を難しくする。

実用的なガイドライン:

  • アーキテクチャと状態管理: 常に明示的に指定
  • 命名規約: 非自明なものを指定(Dartのsnake_caseは自明、_page.dartサフィックスは非自明)
  • コード生成ワークフロー: 常に指定(build_runner、KSP、Hiltプロセッサ)
  • 禁止パターン: 常に明示的にリスト — ポジティブなルールだけでは不十分
  • ウィジェット/Composableの分解しきい値: チームで議論になるなら指定
  • テストのレベル: どのタイプのテストがどこに属するかを指定

上記の最小テンプレートから始めて、Claude Codeが特定の間違いをした時にルールを追加し、一度もトリガーされないルールは削除していく。


このガイドのフレームワーク固有のパターンはツールのバージョン自体よりも緩やかに変化する。特にReact Nativeの新アーキテクチャが安定したとき、Composeマルチプラットフォームが成熟したとき、Swift 6の採用が普遍的になったときには、ツール互換性マトリクスのセクションを見直す価値がある。CLAUDE.mdテンプレートは安定しているが、ツールの推奨事項は2026年時点のスナップショットだ。

フレームワーク固有のルールを実際のプロジェクトから集めたギャラリーや、Dart/Riverpodスタックの深掘りはFlutter完全ガイドで。

Related Articles

AGENTS.md・CLAUDE.md・.cursorrules テンプレート集 -- ユースケース別の選び方と設定例(2026年版)

ファイル形式の選び方を間違えるとコンテキスト予算を無駄にし、AIの悪習を育てる。11のユースケース別テンプレートと、マルチツール環境での合成ガイドを収録。

AGENTS.md vs CLAUDE.md 完全決断ガイド -- どちらを選ぶかを決める判断フレームワーク(2026年版)

AGENTS.mdとCLAUDE.mdの使い分けで迷うすべてのエンジニアへ。決断マトリクス・実リポジトリのウォークスルー・マイグレーションパターン・共存時の挙動・7つの落とし穴まで、基礎知識がある人向けの完全ガイド。

Claude Codeのコンテキストウィンドウが速く枯渇する理由と7つの対処法【2026年版】

1Mトークン上限のはずなのに予想より速く枯渇するのはなぜか。.claudeignoreの書き方、CLAUDE.mdの軽量化、コンパクション、サブエージェント、セッションresumeまで、2026年に効く7つの対処法を実例で解説。

Claude Code Hooks実践ガイド: すぐ使えるサンプル10本付き

Claude Code hooksを使って自動フォーマット、危険コマンドのブロック、コンテキスト注入、チームルールの強制を実現する方法。全主要イベント対応のコピー&ペースト可能なサンプル10本を掲載。

Explore the collection

Browse all AI coding rules — CLAUDE.md, .cursorrules, AGENTS.md, and more.

Browse Rules