android-sdd 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/dist/index.js +143 -0
  2. package/package.json +27 -0
  3. package/skills/Android Ecosystem/Baseline Profile Generator/SKILL.md +277 -0
  4. package/skills/Android Ecosystem/Glance/SKILL.md +315 -0
  5. package/skills/Android Platform/Configuration/SKILL.md +201 -0
  6. package/skills/Android Platform/Filesystem/SKILL.md +216 -0
  7. package/skills/Android Platform/Lifecycle/SKILL.md +233 -0
  8. package/skills/Android Platform/Manifest/SKILL.md +226 -0
  9. package/skills/Android Platform/Process Death Recovery/SKILL.md +214 -0
  10. package/skills/Android Platform/Resources/SKILL.md +234 -0
  11. package/skills/Android Platform/SavedStateHandle/SKILL.md +217 -0
  12. package/skills/Android Platform/State Restoration/SKILL.md +210 -0
  13. package/skills/Architecture/Bounded Context/SKILL.md +207 -0
  14. package/skills/Architecture/Clean Architecture/SKILL.md +229 -0
  15. package/skills/Architecture/Domain Modeling/SKILL.md +236 -0
  16. package/skills/Architecture/Entity Design/SKILL.md +243 -0
  17. package/skills/Architecture/Feature Isolation/SKILL.md +216 -0
  18. package/skills/Architecture/MVI/SKILL.md +224 -0
  19. package/skills/Architecture/MVVM/SKILL.md +198 -0
  20. package/skills/Architecture/Modularization/SKILL.md +194 -0
  21. package/skills/Architecture/Offline First/SKILL.md +249 -0
  22. package/skills/Architecture/Repository Pattern/SKILL.md +216 -0
  23. package/skills/Architecture/Side Effect Management/SKILL.md +278 -0
  24. package/skills/Architecture/State Management/SKILL.md +229 -0
  25. package/skills/Architecture/Unidirectional Data Flow/SKILL.md +196 -0
  26. package/skills/Architecture/Use Case Design/SKILL.md +244 -0
  27. package/skills/Architecture/Value Object/SKILL.md +226 -0
  28. package/skills/Build Infrastructure/Build Orchestration/SKILL.md +257 -0
  29. package/skills/Build Infrastructure/Dependency Compatibility Resolver/SKILL.md +259 -0
  30. package/skills/Build Infrastructure/Environment Validator/SKILL.md +311 -0
  31. package/skills/Build System/Build Cache/SKILL.md +233 -0
  32. package/skills/Build System/Build Flavor Strategy/SKILL.md +171 -0
  33. package/skills/Build System/Build Variant/SKILL.md +215 -0
  34. package/skills/Build System/Convention Plugin/SKILL.md +288 -0
  35. package/skills/Build System/Dependency Management/SKILL.md +261 -0
  36. package/skills/Build System/Gradle/SKILL.md +284 -0
  37. package/skills/Build System/Incremental Build/SKILL.md +199 -0
  38. package/skills/Build System/KAPT/SKILL.md +198 -0
  39. package/skills/Build System/KSP/SKILL.md +263 -0
  40. package/skills/Build System/Module Dependency Graph Validation/SKILL.md +223 -0
  41. package/skills/Build System/Specialized/C++/SKILL.md +308 -0
  42. package/skills/Build System/Specialized/JNI/SKILL.md +306 -0
  43. package/skills/Build System/Specialized/NDK/SKILL.md +264 -0
  44. package/skills/Build System/Version Catalog/SKILL.md +304 -0
  45. package/skills/Concurrency/Background Processing/SKILL.md +185 -0
  46. package/skills/Concurrency/Channel/SKILL.md +207 -0
  47. package/skills/Concurrency/Coroutine/SKILL.md +200 -0
  48. package/skills/Concurrency/Flow/SKILL.md +179 -0
  49. package/skills/Concurrency/Mutex Strategy/SKILL.md +185 -0
  50. package/skills/Concurrency/SharedFlow/SKILL.md +171 -0
  51. package/skills/Concurrency/StateFlow/SKILL.md +175 -0
  52. package/skills/Concurrency/Structured Concurrency/SKILL.md +197 -0
  53. package/skills/Concurrency/Synchronization Policy/SKILL.md +192 -0
  54. package/skills/Core Language/Annotation Processing/SKILL.md +224 -0
  55. package/skills/Core Language/DSL/SKILL.md +186 -0
  56. package/skills/Core Language/Extension Functions Design/SKILL.md +191 -0
  57. package/skills/Core Language/Immutability/SKILL.md +156 -0
  58. package/skills/Core Language/KMP/SKILL.md +182 -0
  59. package/skills/Core Language/Kotlin/SKILL.md +187 -0
  60. package/skills/Core Language/Reactive State Management/SKILL.md +228 -0
  61. package/skills/Core Language/Reactive Streams/SKILL.md +235 -0
  62. package/skills/Core Language/Serialization/SKILL.md +191 -0
  63. package/skills/Data Layer/Cache Strategy/SKILL.md +261 -0
  64. package/skills/Data Layer/Conflict Resolution/SKILL.md +248 -0
  65. package/skills/Data Layer/DAO/SKILL.md +225 -0
  66. package/skills/Data Layer/DTO Mapping/SKILL.md +269 -0
  67. package/skills/Data Layer/DataStore/SKILL.md +264 -0
  68. package/skills/Data Layer/Database Versioning Strategy/SKILL.md +215 -0
  69. package/skills/Data Layer/Encrypted Database/SKILL.md +212 -0
  70. package/skills/Data Layer/File Storage/SKILL.md +247 -0
  71. package/skills/Data Layer/Indexing/SKILL.md +184 -0
  72. package/skills/Data Layer/Key-Value Store Strategy/SKILL.md +185 -0
  73. package/skills/Data Layer/Merge Strategy/SKILL.md +240 -0
  74. package/skills/Data Layer/Migration/SKILL.md +243 -0
  75. package/skills/Data Layer/Paging/SKILL.md +264 -0
  76. package/skills/Data Layer/Proto DataStore/SKILL.md +250 -0
  77. package/skills/Data Layer/Room/SKILL.md +244 -0
  78. package/skills/Data Layer/SQLite/SKILL.md +255 -0
  79. package/skills/Data Layer/Sync Engine/SKILL.md +268 -0
  80. package/skills/Dependency Injection/Dagger/SKILL.md +283 -0
  81. package/skills/Dependency Injection/Hilt/SKILL.md +345 -0
  82. package/skills/Dependency Injection/Koin/SKILL.md +282 -0
  83. package/skills/Developer Experience/Detekt/SKILL.md +272 -0
  84. package/skills/Developer Experience/Lint Rule/SKILL.md +281 -0
  85. package/skills/Google Ecosystem/Analytics/SKILL.md +281 -0
  86. package/skills/Google Ecosystem/Crashlytics/SKILL.md +234 -0
  87. package/skills/Google Ecosystem/Firebase/SKILL.md +200 -0
  88. package/skills/Google Ecosystem/Firebase Messaging/SKILL.md +266 -0
  89. package/skills/Media/Audio/SKILL.md +257 -0
  90. package/skills/Media/Camera/SKILL.md +229 -0
  91. package/skills/Media/CameraX/SKILL.md +295 -0
  92. package/skills/Media/ExoPlayer/SKILL.md +258 -0
  93. package/skills/Media/Video/SKILL.md +228 -0
  94. package/skills/Meta Skills/Domain Error Model/SKILL.md +238 -0
  95. package/skills/Meta Skills/Error Handling/SKILL.md +255 -0
  96. package/skills/Meta Skills/Error Mapping/SKILL.md +232 -0
  97. package/skills/Meta Skills/Failure Strategy/SKILL.md +294 -0
  98. package/skills/Meta Skills/Migration Strategy/SKILL.md +305 -0
  99. package/skills/Meta Skills/User Friendly Errors/SKILL.md +334 -0
  100. package/skills/Navigation/Deep Navigation/SKILL.md +209 -0
  101. package/skills/Navigation/Navigation/SKILL.md +215 -0
  102. package/skills/Navigation/Nested Navigation/SKILL.md +214 -0
  103. package/skills/Networking/API Contract/SKILL.md +220 -0
  104. package/skills/Networking/Authentication/SKILL.md +210 -0
  105. package/skills/Networking/Certificate Pinning/SKILL.md +167 -0
  106. package/skills/Networking/Fallback Strategy/SKILL.md +182 -0
  107. package/skills/Networking/Ktor/SKILL.md +219 -0
  108. package/skills/Networking/Multipart Upload/SKILL.md +213 -0
  109. package/skills/Networking/OkHttp/SKILL.md +193 -0
  110. package/skills/Networking/REST/SKILL.md +178 -0
  111. package/skills/Networking/Rate Limiting/SKILL.md +170 -0
  112. package/skills/Networking/Retrofit/SKILL.md +241 -0
  113. package/skills/Networking/Retry-Backoff/SKILL.md +181 -0
  114. package/skills/Networking/Server-Sent Events (SSE)/SKILL.md +196 -0
  115. package/skills/Networking/WebSocket/SKILL.md +224 -0
  116. package/skills/Observability/Crash Reporting/SKILL.md +219 -0
  117. package/skills/Observability/Logging/SKILL.md +168 -0
  118. package/skills/Observability/Metrics/SKILL.md +227 -0
  119. package/skills/Observability/Structured Logging/SKILL.md +234 -0
  120. package/skills/Performance/ANR Prevention/SKILL.md +192 -0
  121. package/skills/Performance/Allocation Optimization/SKILL.md +179 -0
  122. package/skills/Performance/App Startup/SKILL.md +183 -0
  123. package/skills/Performance/Baseline Profile/SKILL.md +205 -0
  124. package/skills/Performance/Battery Optimization/SKILL.md +192 -0
  125. package/skills/Performance/Benchmark/SKILL.md +182 -0
  126. package/skills/Performance/Bitmap Optimization/SKILL.md +178 -0
  127. package/skills/Performance/Compose Optimization/SKILL.md +187 -0
  128. package/skills/Performance/Heap Management/SKILL.md +184 -0
  129. package/skills/Performance/Macrobenchmark/SKILL.md +214 -0
  130. package/skills/Performance/Memory Leak Prevention/SKILL.md +218 -0
  131. package/skills/Performance/Rendering Performance/SKILL.md +205 -0
  132. package/skills/Performance/Startup Optimization/SKILL.md +219 -0
  133. package/skills/Security/Biometric/SKILL.md +224 -0
  134. package/skills/Security/Certificate Transparency/SKILL.md +158 -0
  135. package/skills/Security/Cryptography/SKILL.md +244 -0
  136. package/skills/Security/Encrypted Storage/SKILL.md +273 -0
  137. package/skills/Security/Frida Detection/SKILL.md +230 -0
  138. package/skills/Security/Hook Detection/SKILL.md +197 -0
  139. package/skills/Security/Keystore/SKILL.md +272 -0
  140. package/skills/Security/Network Security Config/SKILL.md +186 -0
  141. package/skills/Security/Obfuscation/SKILL.md +226 -0
  142. package/skills/Security/Proguard/SKILL.md +202 -0
  143. package/skills/Security/R8/SKILL.md +234 -0
  144. package/skills/Security/Reverse Engineering Resistance/SKILL.md +267 -0
  145. package/skills/Security/Root Detection/SKILL.md +220 -0
  146. package/skills/Security/Secure Networking/SKILL.md +220 -0
  147. package/skills/System Integration/AlarmManager/SKILL.md +182 -0
  148. package/skills/System Integration/App Widget/SKILL.md +182 -0
  149. package/skills/System Integration/Deep Link/SKILL.md +187 -0
  150. package/skills/System Integration/Foreground Service/SKILL.md +212 -0
  151. package/skills/System Integration/Notification/SKILL.md +237 -0
  152. package/skills/System Integration/WorkManager/SKILL.md +256 -0
  153. package/skills/System Integration/clipboard/SKILL.md +155 -0
  154. package/skills/System Integration/share-intent/SKILL.md +182 -0
  155. package/skills/Testing/Compose Testing/SKILL.md +296 -0
  156. package/skills/Testing/Espresso/SKILL.md +292 -0
  157. package/skills/Testing/Fake Data/SKILL.md +245 -0
  158. package/skills/Testing/Integration Testing/SKILL.md +288 -0
  159. package/skills/Testing/Mocking/SKILL.md +229 -0
  160. package/skills/Testing/Snapshot Testing/SKILL.md +259 -0
  161. package/skills/Testing/UI Testing/SKILL.md +293 -0
  162. package/skills/Testing/Unit Testing/SKILL.md +309 -0
  163. package/skills/UI System/Bottom Sheet Patterns/SKILL.md +279 -0
  164. package/skills/UI System/Compose/SKILL.md +296 -0
  165. package/skills/UI System/Compose Animation/SKILL.md +281 -0
  166. package/skills/UI System/Compose Multiplatform/SKILL.md +261 -0
  167. package/skills/UI System/Compose Navigation/SKILL.md +255 -0
  168. package/skills/UI System/Compose Performance/SKILL.md +274 -0
  169. package/skills/UI System/Design System/SKILL.md +217 -0
  170. package/skills/UI System/Empty State Strategy/SKILL.md +208 -0
  171. package/skills/UI System/Keyboard Navigation/SKILL.md +214 -0
  172. package/skills/UI System/Loading Strategy/SKILL.md +254 -0
  173. package/skills/UI System/Material 3/SKILL.md +279 -0
  174. package/skills/UI System/RTL/SKILL.md +179 -0
  175. package/src/index.ts +182 -0
  176. package/tsconfig.json +19 -0
@@ -0,0 +1,279 @@
1
+ ---
2
+ name: material3
3
+ description: >
4
+ Material Design 3 theming, components, and color system for Android/Compose.
5
+ Load this skill when setting up M3 theme, using M3 components, defining
6
+ custom color schemes, typography, or shapes, or supporting dynamic color.
7
+ ---
8
+
9
+ # Material 3
10
+
11
+ ## Overview
12
+ Material Design 3 (M3) is Google's latest design system, built into Jetpack Compose via `androidx.compose.material3`. It provides a comprehensive color system, typography scale, shape system, and a full set of UI components. M3 supports dynamic color (Android 12+) and dark/light themes natively.
13
+
14
+ ---
15
+
16
+ ## Core Principles
17
+
18
+ - Always use **M3 semantic color tokens** — never hardcode colors
19
+ - Define **one MaterialTheme** at the root — never nest multiple themes
20
+ - Use M3 components before building custom — they handle accessibility and state
21
+ - Support **dark mode** from day one — design the color scheme for both
22
+ - Use **dynamic color** where available (API 31+) with a fallback palette
23
+
24
+ ---
25
+
26
+ ## Theme Setup
27
+
28
+ ```kotlin
29
+ // ✅ Theme definition
30
+ @Composable
31
+ fun AppTheme(
32
+ darkTheme: Boolean = isSystemInDarkTheme(),
33
+ dynamicColor: Boolean = true,
34
+ content: @Composable () -> Unit
35
+ ) {
36
+ val colorScheme = when {
37
+ dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
38
+ val context = LocalContext.current
39
+ if (darkTheme) dynamicDarkColorScheme(context)
40
+ else dynamicLightColorScheme(context)
41
+ }
42
+ darkTheme -> DarkColorScheme
43
+ else -> LightColorScheme
44
+ }
45
+
46
+ MaterialTheme(
47
+ colorScheme = colorScheme,
48
+ typography = AppTypography,
49
+ shapes = AppShapes,
50
+ content = content
51
+ )
52
+ }
53
+
54
+ // ✅ Apply at root
55
+ class MainActivity : ComponentActivity() {
56
+ override fun onCreate(savedInstanceState: Bundle?) {
57
+ super.onCreate(savedInstanceState)
58
+ setContent {
59
+ AppTheme {
60
+ AppNavHost()
61
+ }
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Color Scheme
70
+
71
+ ```kotlin
72
+ // ✅ Define light and dark color schemes
73
+ private val LightColorScheme = lightColorScheme(
74
+ primary = Purple40,
75
+ onPrimary = Color.White,
76
+ primaryContainer = Purple90,
77
+ onPrimaryContainer = Purple10,
78
+ secondary = PurpleGrey40,
79
+ onSecondary = Color.White,
80
+ secondaryContainer = PurpleGrey90,
81
+ onSecondaryContainer = PurpleGrey10,
82
+ tertiary = Pink40,
83
+ background = Color(0xFFFFFBFE),
84
+ surface = Color(0xFFFFFBFE),
85
+ onBackground = Color(0xFF1C1B1F),
86
+ onSurface = Color(0xFF1C1B1F),
87
+ error = Color(0xFFB3261E)
88
+ )
89
+
90
+ private val DarkColorScheme = darkColorScheme(
91
+ primary = Purple80,
92
+ onPrimary = Purple20,
93
+ primaryContainer = Purple30,
94
+ onPrimaryContainer = Purple90,
95
+ // ...
96
+ )
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Color Token Usage
102
+
103
+ ```kotlin
104
+ // ✅ Always use MaterialTheme.colorScheme tokens
105
+ @Composable
106
+ fun PrimaryButton(text: String, onClick: () -> Unit) {
107
+ Button(
108
+ onClick = onClick,
109
+ colors = ButtonDefaults.buttonColors(
110
+ containerColor = MaterialTheme.colorScheme.primary,
111
+ contentColor = MaterialTheme.colorScheme.onPrimary
112
+ )
113
+ ) {
114
+ Text(text)
115
+ }
116
+ }
117
+
118
+ // ✅ Surface with correct tonal elevation
119
+ Surface(
120
+ color = MaterialTheme.colorScheme.surface,
121
+ tonalElevation = 2.dp
122
+ ) { ... }
123
+
124
+ // ❌ Never hardcode colors
125
+ Text(text = "Hello", color = Color(0xFF6200EE))
126
+ ```
127
+
128
+ ### M3 Color Roles Reference
129
+
130
+ | Role | On Role | Use For |
131
+ |------|---------|---------|
132
+ | `primary` | `onPrimary` | Main action, FAB |
133
+ | `primaryContainer` | `onPrimaryContainer` | Selected state, chips |
134
+ | `secondary` | `onSecondary` | Supporting actions |
135
+ | `tertiary` | `onTertiary` | Contrasting accents |
136
+ | `surface` | `onSurface` | Cards, sheets, dialogs |
137
+ | `surfaceVariant` | `onSurfaceVariant` | Input fields, chips |
138
+ | `background` | `onBackground` | Screen background |
139
+ | `error` | `onError` | Error states |
140
+
141
+ ---
142
+
143
+ ## Typography
144
+
145
+ ```kotlin
146
+ // ✅ Define custom typography
147
+ val AppTypography = Typography(
148
+ displayLarge = TextStyle(
149
+ fontFamily = FontFamily.Default,
150
+ fontWeight = FontWeight.Normal,
151
+ fontSize = 57.sp,
152
+ lineHeight = 64.sp
153
+ ),
154
+ titleLarge = TextStyle(
155
+ fontFamily = FontFamily.Default,
156
+ fontWeight = FontWeight.Normal,
157
+ fontSize = 22.sp,
158
+ lineHeight = 28.sp
159
+ ),
160
+ bodyLarge = TextStyle(
161
+ fontFamily = FontFamily.Default,
162
+ fontWeight = FontWeight.Normal,
163
+ fontSize = 16.sp,
164
+ lineHeight = 24.sp
165
+ ),
166
+ labelSmall = TextStyle(
167
+ fontFamily = FontFamily.Default,
168
+ fontWeight = FontWeight.Medium,
169
+ fontSize = 11.sp,
170
+ lineHeight = 16.sp
171
+ )
172
+ )
173
+
174
+ // ✅ Use typography tokens
175
+ Text(text = "Title", style = MaterialTheme.typography.titleLarge)
176
+ Text(text = "Body text", style = MaterialTheme.typography.bodyMedium)
177
+ Text(text = "Label", style = MaterialTheme.typography.labelSmall)
178
+ ```
179
+
180
+ ---
181
+
182
+ ## Shapes
183
+
184
+ ```kotlin
185
+ // ✅ Define shape scale
186
+ val AppShapes = Shapes(
187
+ extraSmall = RoundedCornerShape(4.dp),
188
+ small = RoundedCornerShape(8.dp),
189
+ medium = RoundedCornerShape(12.dp),
190
+ large = RoundedCornerShape(16.dp),
191
+ extraLarge = RoundedCornerShape(28.dp)
192
+ )
193
+
194
+ // ✅ Use shape tokens
195
+ Card(shape = MaterialTheme.shapes.medium) { ... }
196
+ Button(shape = MaterialTheme.shapes.extraLarge) { ... } // pill shape
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Key M3 Components
202
+
203
+ ```kotlin
204
+ // ✅ Buttons
205
+ Button(onClick = {}) { Text("Filled") }
206
+ OutlinedButton(onClick = {}) { Text("Outlined") }
207
+ TextButton(onClick = {}) { Text("Text") }
208
+ FilledTonalButton(onClick = {}) { Text("Tonal") }
209
+ ElevatedButton(onClick = {}) { Text("Elevated") }
210
+
211
+ // ✅ FAB
212
+ FloatingActionButton(onClick = {}) {
213
+ Icon(Icons.Default.Add, contentDescription = "Add")
214
+ }
215
+ ExtendedFloatingActionButton(
216
+ text = { Text("New item") },
217
+ icon = { Icon(Icons.Default.Add, contentDescription = null) },
218
+ onClick = {}
219
+ )
220
+
221
+ // ✅ Cards
222
+ Card(modifier = Modifier.fillMaxWidth()) { ... }
223
+ ElevatedCard { ... }
224
+ OutlinedCard { ... }
225
+
226
+ // ✅ Top App Bar
227
+ TopAppBar(
228
+ title = { Text("Screen Title") },
229
+ navigationIcon = {
230
+ IconButton(onClick = onBack) {
231
+ Icon(Icons.Default.ArrowBack, contentDescription = "Back")
232
+ }
233
+ },
234
+ actions = {
235
+ IconButton(onClick = {}) {
236
+ Icon(Icons.Default.MoreVert, contentDescription = "More")
237
+ }
238
+ }
239
+ )
240
+
241
+ // ✅ Navigation Bar
242
+ NavigationBar {
243
+ items.forEach { item ->
244
+ NavigationBarItem(
245
+ icon = { Icon(item.icon, contentDescription = null) },
246
+ label = { Text(item.label) },
247
+ selected = currentRoute == item.route,
248
+ onClick = { onNavigate(item.route) }
249
+ )
250
+ }
251
+ }
252
+
253
+ // ✅ Snackbar
254
+ val snackbarHostState = remember { SnackbarHostState() }
255
+ Scaffold(snackbarHost = { SnackbarHost(snackbarHostState) }) { padding ->
256
+ // content
257
+ }
258
+ LaunchedEffect(Unit) {
259
+ snackbarHostState.showSnackbar("Item deleted", actionLabel = "Undo")
260
+ }
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Anti-Patterns
266
+
267
+ - Hardcoding colors instead of using `MaterialTheme.colorScheme` tokens
268
+ - Nesting multiple `MaterialTheme` composables — causes inconsistent theming
269
+ - Using `androidx.compose.material` (M2) components mixed with M3 — conflicts
270
+ - Not providing a non-dynamic fallback color scheme for API < 31
271
+ - Using `Color.White`/`Color.Black` directly — breaks dark mode
272
+
273
+ ---
274
+
275
+ ## Related Skills
276
+ - `compose` — Compose fundamentals
277
+ - `design-system` — extending M3 with custom design tokens
278
+ - `resources` — color and style resources for XML interop
279
+ - `rtl` — RTL support in M3 components
@@ -0,0 +1,179 @@
1
+ ---
2
+ name: rtl
3
+ description: >
4
+ Right-to-Left (RTL) layout support in Android and Jetpack Compose.
5
+ Load this skill when building layouts that must support RTL languages
6
+ (Arabic, Persian, Hebrew), mirroring icons and directions, handling
7
+ bidirectional text, or ensuring correct layout mirroring behavior.
8
+ ---
9
+
10
+ # RTL
11
+
12
+ ## Overview
13
+ RTL (Right-to-Left) support ensures layouts mirror correctly for languages like Persian, Arabic, and Hebrew. In Compose, this is handled via `LayoutDirection` and logical layout modifiers. Correct RTL support requires using directional-agnostic APIs throughout — never hardcode left/right values.
14
+
15
+ ---
16
+
17
+ ## Core Principles
18
+
19
+ - Always use **logical layout modifiers** — never physical (`start/end`, not `left/right`)
20
+ - Set `android:supportsRtl="true"` in the manifest
21
+ - Use `Arrangement.Start`/`Alignment.Start` — not `Left`/`Right`
22
+ - Mirror directional icons explicitly using `autoMirrored = true`
23
+ - Test in both LTR and RTL using the developer options toggle
24
+
25
+ ---
26
+
27
+ ## Manifest Setup
28
+
29
+ ```xml
30
+ <!-- ✅ Required in AndroidManifest.xml -->
31
+ <application
32
+ android:supportsRtl="true"
33
+ ... >
34
+ ```
35
+
36
+ ---
37
+
38
+ ## Compose Layout Direction
39
+
40
+ ```kotlin
41
+ // ✅ Read current layout direction
42
+ @Composable
43
+ fun DirectionAwareIcon() {
44
+ val layoutDirection = LocalLayoutDirection.current
45
+ val isRtl = layoutDirection == LayoutDirection.Rtl
46
+ }
47
+
48
+ // ✅ Force RTL for a subtree
49
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
50
+ MyLayout()
51
+ }
52
+
53
+ // ✅ Force LTR for specific content (e.g. phone numbers, codes)
54
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
55
+ Text(text = "+98 912 000 0000")
56
+ }
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Logical Modifiers
62
+
63
+ ```kotlin
64
+ // ✅ Use padding start/end — not left/right
65
+ Modifier.padding(start = 16.dp, end = 8.dp)
66
+
67
+ // ✅ Use absolutePadding only when truly position-fixed
68
+ Modifier.absolutePadding(left = 0.dp) // rare — only for non-mirrored content
69
+
70
+ // ✅ Row arrangement
71
+ Row(horizontalArrangement = Arrangement.Start) { ... } // ✅
72
+ Row(horizontalArrangement = Arrangement.End) { ... } // ✅
73
+
74
+ // ❌ Never use physical directions in layout
75
+ Modifier.padding(left = 16.dp) // breaks RTL
76
+ Modifier.padding(right = 8.dp) // breaks RTL
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Icon Mirroring
82
+
83
+ ```kotlin
84
+ // ✅ Use autoMirrored for directional icons (arrows, back, forward)
85
+ Icon(
86
+ painter = painterResource(R.drawable.ic_arrow_forward),
87
+ contentDescription = null,
88
+ modifier = Modifier.scale(
89
+ scaleX = if (LocalLayoutDirection.current == LayoutDirection.Rtl) -1f else 1f,
90
+ scaleY = 1f
91
+ )
92
+ )
93
+
94
+ // ✅ Better — use autoMirrored in vector drawable XML
95
+ // In ic_arrow_forward.xml:
96
+ // android:autoMirrored="true"
97
+
98
+ // ✅ Icons that should NOT be mirrored
99
+ Icon(Icons.Default.PlayArrow, contentDescription = null) // media control — don't mirror
100
+ Icon(Icons.Default.Search, contentDescription = null) // symmetric — don't mirror
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Bidirectional Text
106
+
107
+ ```kotlin
108
+ // ✅ Let the system handle bidi text automatically
109
+ Text(text = "Hello سلام") // system resolves direction per paragraph
110
+
111
+ // ✅ Force text direction when needed
112
+ Text(
113
+ text = userInput,
114
+ textDirection = TextDirection.Content // auto-detect per content
115
+ )
116
+
117
+ // ✅ Force LTR for codes, emails, URLs
118
+ Text(
119
+ text = "user@example.com",
120
+ textDirection = TextDirection.Ltr
121
+ )
122
+
123
+ // ✅ TextField with explicit direction for mixed input
124
+ TextField(
125
+ value = value,
126
+ onValueChange = onValueChange,
127
+ keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
128
+ modifier = Modifier.semantics { textDirection = TextDirection.Content }
129
+ )
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Alignment Helpers
135
+
136
+ ```kotlin
137
+ // ✅ Alignment.Start mirrors automatically
138
+ Box(contentAlignment = Alignment.TopStart) { ... } // top-left in LTR, top-right in RTL
139
+ Box(contentAlignment = Alignment.TopEnd) { ... } // top-right in LTR, top-left in RTL
140
+
141
+ // ✅ Column horizontal alignment
142
+ Column(horizontalAlignment = Alignment.Start) { ... }
143
+ Column(horizontalAlignment = Alignment.End) { ... }
144
+ ```
145
+
146
+ ---
147
+
148
+ ## Previewing RTL
149
+
150
+ ```kotlin
151
+ // ✅ Always add an RTL preview alongside LTR
152
+ @Preview(name = "LTR", locale = "en")
153
+ @Preview(name = "RTL", locale = "fa")
154
+ @Composable
155
+ fun MyComponentPreview() {
156
+ AppTheme {
157
+ MyComponent()
158
+ }
159
+ }
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Anti-Patterns
165
+
166
+ - Using `Modifier.padding(left/right)` — breaks RTL mirroring
167
+ - Using `Arrangement.AbsoluteLeft` or `AbsoluteRight` in normal layouts
168
+ - Hardcoding `LayoutDirection.Ltr` at the root — prevents RTL support
169
+ - Not setting `android:supportsRtl="true"` in manifest
170
+ - Mirroring media/playback icons (play, pause, record) — they are universal
171
+ - Using `Column { Modifier.align(Alignment.AbsoluteLeft) }` — physical alignment
172
+
173
+ ---
174
+
175
+ ## Related Skills
176
+ - `compose` — Compose layout fundamentals
177
+ - `material3` — M3 component RTL behavior
178
+ - `resources` — string direction and locale resources
179
+ - `design-system` — design tokens with directional awareness
package/src/index.ts ADDED
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "fs";
4
+ import path from "path";
5
+ const inquirer = require("inquirer");
6
+
7
+ /**
8
+ * GitHub Remote Skills Repo (ZIP)
9
+ */
10
+ const REMOTE_SKILLS_ZIP =
11
+ "https://github.com/mozhdehnoury-byte/android-agent-skills/archive/refs/heads/main.zip";
12
+
13
+ /**
14
+ * ورود برنامه
15
+ */
16
+ async function main() {
17
+ const args = process.argv.slice(2);
18
+ const command = args[0];
19
+
20
+ if (command === "init") {
21
+ await initRemote();
22
+ return;
23
+ }
24
+
25
+ if (command === "install") {
26
+ const selectedSkills = await wizard(skillsPath());
27
+ await install(selectedSkills, skillsPath());
28
+ return;
29
+ }
30
+
31
+ await wizard(skillsPath());
32
+ }
33
+
34
+ /**
35
+ * مسیر skills (local fallback)
36
+ */
37
+ function skillsPath() {
38
+ return path.join(__dirname, "../skills");
39
+ }
40
+
41
+ /**
42
+ * wizard: انتخاب skill ها
43
+ */
44
+ async function wizard(basePath: string): Promise<Record<string, string[]>> {
45
+
46
+ const selectedSkills: Record<string, string[]> = {};
47
+
48
+ const parentFolders = fs.readdirSync(basePath);
49
+
50
+ for (const parent of parentFolders) {
51
+
52
+ const children = fs.readdirSync(
53
+ path.join(basePath, parent)
54
+ );
55
+
56
+ const answer = await inquirer.prompt([
57
+ {
58
+ type: "checkbox",
59
+ name: "selected",
60
+ message: `Select ${parent} skills`,
61
+ choices: children
62
+ }
63
+ ]);
64
+
65
+ selectedSkills[parent] = answer.selected;
66
+ }
67
+
68
+ console.log("Selected Skills:");
69
+ console.log(selectedSkills);
70
+
71
+ return selectedSkills;
72
+ }
73
+
74
+ /**
75
+ * install: ساخت .agent + کپی skill ها + ساخت config
76
+ */
77
+ async function install(
78
+ selectedSkills: Record<string, string[]>,
79
+ basePath: string
80
+ ) {
81
+
82
+ console.log("🚀 Installing Android SDD skills...");
83
+
84
+ const agentRoot = path.join(process.cwd(), ".agent");
85
+ fs.mkdirSync(agentRoot, { recursive: true });
86
+
87
+ for (const [parent, skills] of Object.entries(selectedSkills)) {
88
+
89
+ for (const skill of skills) {
90
+
91
+ const source = path.join(
92
+ basePath,
93
+ parent,
94
+ skill,
95
+ "SKILL.md"
96
+ );
97
+
98
+ const targetDir = path.join(
99
+ agentRoot,
100
+ parent,
101
+ skill
102
+ );
103
+
104
+ fs.mkdirSync(targetDir, { recursive: true });
105
+
106
+ fs.copyFileSync(
107
+ source,
108
+ path.join(targetDir, "SKILL.md")
109
+ );
110
+
111
+ console.log(`Installed: ${parent}/${skill}`);
112
+ }
113
+ }
114
+
115
+ const config = {
116
+ version: "1.0.0",
117
+ installedAt: new Date().toISOString(),
118
+ skills: selectedSkills
119
+ };
120
+
121
+ fs.writeFileSync(
122
+ path.join(agentRoot, "config.json"),
123
+ JSON.stringify(config, null, 2)
124
+ );
125
+
126
+ console.log("\n🎉 Done! Skills installed in .agent/");
127
+ }
128
+
129
+ /**
130
+ * Remote init (GitHub ZIP → auto-detect folder → wizard)
131
+ */
132
+ async function initRemote() {
133
+
134
+ console.log("🌍 Downloading skills from GitHub...");
135
+
136
+ const fetch = (await import("node-fetch")).default;
137
+ const unzipper = await import("unzipper");
138
+
139
+ const res = await fetch(REMOTE_SKILLS_ZIP);
140
+
141
+ const buffer = Buffer.from(await res.arrayBuffer());
142
+
143
+ const zipPath = path.join(process.cwd(), "skills.zip");
144
+
145
+ fs.writeFileSync(zipPath, buffer);
146
+
147
+ console.log("📦 Extracting skills...");
148
+
149
+ await fs.createReadStream(zipPath)
150
+ .pipe(unzipper.Extract({ path: process.cwd() }))
151
+ .promise();
152
+
153
+ /**
154
+ * 🔥 AUTO DETECT extracted skills path
155
+ * چون GitHub همیشه یک wrapper folder می‌سازه
156
+ */
157
+ const extractedBase = process.cwd();
158
+
159
+ const possiblePaths = [
160
+ path.join(extractedBase, "android-agent-skills-main"),
161
+ ];
162
+
163
+ let extractedPath: string | null = null;
164
+
165
+ for (const p of possiblePaths) {
166
+ if (fs.existsSync(p)) {
167
+ extractedPath = p;
168
+ break;
169
+ }
170
+ }
171
+
172
+ if (!extractedPath) {
173
+ throw new Error("❌ Could not find skills folder after extraction");
174
+ }
175
+
176
+ console.log("🧠 Running wizard...");
177
+
178
+ const selectedSkills = await wizard(extractedPath);
179
+ await install(selectedSkills, extractedPath);
180
+ }
181
+
182
+ main();
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "CommonJS",
5
+ "moduleResolution": "Node",
6
+
7
+ "rootDir": "src",
8
+ "outDir": "dist",
9
+
10
+ "esModuleInterop": true,
11
+ "allowSyntheticDefaultImports": true,
12
+
13
+ "types": ["node"],
14
+
15
+ "strict": false,
16
+ "skipLibCheck": true
17
+ },
18
+ "include": ["src"]
19
+ }