Atlas / Skills / affaan-m / Compose Multiplatform Patterns

Compose Multiplatform PatternsSAFE

skills/affaan-m/compose-multiplatform-patterns

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

Verdict
SAFE
Grade
B
Trust score
89 /100
Version
—
Hosts
—
License
MIT
Stars
262,423
01

Overview

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

Read from source at commit e9ca581a4f44OBSERVED · 2026-09-19
02

What it tells the agent

The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.

---
name: compose-multiplatform-patterns
description: KMPプロジェクト向けのCompose MultiplatformおよびJetpack Composeパターン — 状態管理、ナビゲーション、テーマ設定、パフォーマンス、プラットフォーム固有のUI。
origin: ECC
---

# Compose Multiplatformパターン

Compose MultiplatformとJetpack Composeを使用して、Android、iOS、デスクトップ、Web間で共有UIを構築するためのパターン。状態管理、ナビゲーション、テーマ設定、パフォーマンスをカバーします。

## 起動条件

- Compose UIの構築(Jetpack ComposeまたはCompose Multiplatform)
- ViewModelとCompose状態によるUI状態の管理
- KMPまたはAndroidプロジェクトでのナビゲーション実装
- 再利用可能なコンポーザブルとデザインシステムの設計
- リコンポジションとレンダリングパフォーマンスの最適化

## 状態管理

### ViewModel + 単一状態オブジェクト

画面状態には単一のデータクラスを使用します。`StateFlow`として公開し、Composeで収集します:

```kotlin
data class ItemListState(
    val items: List<Item> = emptyList(),
    val isLoading: Boolean = false,
    val error: String? = null,
    val searchQuery: String = ""
)

class ItemListViewModel(
    private val getItems: GetItemsUseCase
) : ViewModel() {
    private val _state = MutableStateFlow(ItemListState())
    val state: StateFlow<ItemListState> = _state.asStateFlow()

    fun onSearch(query: String) {
        _state.update { it.copy(searchQuery = query) }
        loadItems(query)
    }

    private fun loadItems(query: String) {
        viewModelScope.launch {
            _state.update { it.copy(isLoading = true) }
            getItems(query).fold(
                onSuccess = { items -> _state.update { it.copy(items = items, isLoading = false) } },
                onFailure = { e -> _state.update { it.copy(error = e.message, isLoading = false) } }
            )
        }
    }
}
```

### Composeでの状態収集

```kotlin
@Composable
fun ItemListScreen(viewModel: ItemListViewModel = koinViewModel()) {
    val state by viewModel.state.collectAsStateWithLifecycle()

    ItemListContent(
        state = state,
        onSearch = viewModel::onSearch
    )
}

@Composable
private fun ItemListContent(
    state: ItemListState,
    onSearch: (String) -> Unit
) {
    // ステートレスなコンポーザブル — プレビューとテストが容易
}
```

### イベントシンクパターン

複雑な画面では、複数のコールバックラムダの代わりにイベント用のシールドインターフェースを使用します:

```kotlin
sealed interface ItemListEvent {
    data class Search(val query: String) : ItemListEvent
    data class Delete(val itemId: String) : ItemListEvent
    data object Refresh : ItemListEvent
}

// ViewModelの中
fun onEvent(event: ItemListEvent) {
    when (event) {
        is ItemListEvent.Search -> onSearch(event.query)
        is ItemListEvent.Delete -> deleteItem(event.itemId)
        is ItemListEvent.Refresh -> loadItems(_state.value.searchQuery)
    }
}

// コンポーザブルの中 — 多数ではなく単一ラムダ
ItemListContent(
    state = state,
    onEvent = viewModel::onEvent
)
```

## ナビゲーション

### 型安全なナビゲーション(Compose Navigation 2.8+)

ルートを`@Serializable`オブジェクトとして定義します:

```kotlin
@Serializable data object HomeRoute
@Serializable data class DetailRoute(val id: String)
@Serializable data object SettingsRoute

@Composable
fun AppNavHost(navController: NavHostController = rememberNavController()) {
    NavHost(navController, startDestination = HomeRoute) {
        composable<HomeRoute> {
            HomeScreen(onNavigateToDetail = { id -> navController.navigate(DetailRoute(id)) })
        }
        composable<DetailRoute> { backStackEntry ->
            val route = backStackEntry.toRoute<DetailRoute>()
            DetailScreen(id = route.id)
        }
        composable<SettingsRoute> { SettingsScreen() }
    }
}
```

### ダイアログとボトムシートナビゲーション

命令型のshow/hideの代わりに`dialog()`とオーバーレイパターンを使用します:

```kotlin
NavHost(navController, startDestination = HomeRoute) {
    composable<HomeRoute> { /* ... */ }
    dialog<ConfirmDeleteRoute> { backStackEntry ->
        val route = backStackEntry.toRoute<ConfirmDeleteRoute>()
        ConfirmDeleteDialog(
            itemId = route.itemId,
            onConfirm = { navController.popBackStack() },
            onDismiss = { navController.popBackStack() }
        )
    }
}
```

## コンポーザブル設計

### スロットベースのAPI

柔軟性のためにスロットパラメータを持つコンポーザブルを設計します:

```kotlin
@Composable
fun AppCard(
    modifier: Modifier = Modifier,
    header: @Composable () -> Unit = {},
    content: @Composable ColumnScope.() -> Unit,
    actions: @Composable RowScope.() -> Unit = {}
) {
    Card(modifier = modifier) {
        Column {
            header()
            Column(content = content)
            Row(horizontalArrangement = Arrangement.End, content = actions)
        }
    }
}
```

### Modifier順序

Modifierの順序は重要です — 以下の順序で適用します:

```kotlin
Text(
    text = "Hello",
    modifier = Modifier
        .padding(16.dp)          // 1. レイアウト(パディング、サイズ)
        .clip(RoundedCornerShape(8.dp))  // 2. 形状
        .background(Color.White) // 3. 描画(背景、ボーダー)
        .clickable { }           // 4. インタラクション
)
```

## KMPプラットフォーム固有のUI

### プラットフォームコンポーザブルのexpect/actual

```kotlin
// commonMain
@Composable
expect fun PlatformStatusBar(darkIcons: Boolean)

// androidMain
@Composable
actual fun PlatformStatusBar(darkIcons: Boolean) {
    val systemUiController = rememberSystemUiController()
    SideEffect { systemUiController.setStatusBarColor(Color.Transparent, darkIcons) }
}

// iosMain
@Composable
actual fun PlatformStatusBar(darkIcons: Boolean) {
    // iOSはUIKitインターロップまたはInfo.plistで処理
}
```

## パフォーマンス

### スキップ可能なリコンポジションのための安定した型

すべてのプロパティが安定している場合、クラスを`@Stable`または`@Immutable`でマークします:

```kotlin
@Immutable
data class ItemUiModel(
    val id: String,
    val title: String,
    val description: String,
    val progress: Float
)
```

### `key()`と遅延リストの正しい使用

```kotlin
LazyColumn {
    items(
        items = items,
        key = { it.id }  // 安定したキーによりアイテムの再利用とアニメーションが可能
    ) { item ->
        ItemRow(item = item)
    }
}
```

### `derivedStateOf`で読み取りを遅延

```kotlin
val listState = rememberLazyListState()
val showScrollToTop by remember {
    derivedStateOf { listState.firstVisibleItemIndex > 5 }
}
```

### リコンポジションでのアロケーションを避ける

```kotlin
// 悪い例 — リコンポジションのたびに新しいラムダとリストが作られる
items.filter { it.isActive }.forEach { ActiveItem(it, onClick = { handle(it) }) }

// 良い例 — 各アイテムにキーを付けてコールバックが正しい行に紐づくようにする
val activeItems = remember(items) { items.filter { it.isActive } }
ac
03

Trust audit

SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeNA
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
none-observed
Shell
none-observed
Dependencies
pinned
Secrets in source
none-found

Findings (0)

No findings outside the package's declared scope.

Gates applied: no_behavioural_pass.

Audited 2026-09-19 · audit v0.4.1 · source sha e9ca581a4f44full audit observations/trust-audit/skill/affaan-m__compose-multiplatform-patterns.json · Report an issue / request a re-scan
04

Audit history

Every audit this skill has had.

DateSourceVerdictGradeScoreChange
2026-09-19e9ca581a4f44SAFEB89first audit
05

Questions

What does the Compose Multiplatform Patterns skill do?

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

Is Compose Multiplatform Patterns safe to install?

The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.

What can Compose Multiplatform Patterns access on my machine?

The audit observed no filesystem, network or shell use at all in its source.

How current is this page?

The grade is for one exact copy of the source (e9ca581a4f44), read on 2026-09-19. The repository is watched, and a new audit runs when it changes — this is the first audit.

Advertisement