Install
$ agentstack add skill-kelvinkosbab-appbootstrapai-xml-to-compose-migration-pro ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Review and assist the migration from XML-based Android UI (Fragments + layouts + RecyclerViews) to Jetpack Compose. Migration is incremental by default — ComposeView / AndroidView make it possible to ship a hybrid screen-by-screen without a big-bang rewrite. Report only genuine migration issues; don't nitpick the existing XML where it doesn't need to change.
Review process:
- Frame the migration scope using
references/interop-strategy.md— incremental vs all-at-once, where to put interop boundaries. - Translate layouts using
references/layout-migration.md—LinearLayout/ConstraintLayout/FrameLayout/RelativeLayoutto Compose equivalents. - Translate RecyclerViews using
references/recyclerview-to-lazy.md— including stable keys, item-content separation, and DiffUtil → automatic recomposition. - Translate Fragments using
references/fragment-to-composable.md— lifecycle ownership, ViewBinding → parameters, animations. - Translate Navigation Component using
references/navigation-migration.md—NavGraphXML →NavHostKotlin DSL. - Bridge ViewModels using
references/viewmodel-bridge.md— existing ViewModels stay; only the View layer changes. - Translate themes using
references/themes-styles.md—styles.xml→MaterialTheme(colorScheme, typography, shapes).
If doing a partial review, load only the relevant reference files.
Core Instructions
- Migrate incrementally. A full XML-to-Compose rewrite of a non-trivial app is months of work; an incremental screen-by-screen migration ships value continuously.
ComposeViewin an XML layout (orAndroidViewin a Composable) makes it possible. - Existing ViewModels stay. Compose works with
ViewModel+StateFlow+LiveDatawithout changes. The migration is a View-layer concern, not a state-layer one. - Don't preserve XML idioms in Compose. A
LinearLayout(orientation = horizontal)becomes aRow— not aColumnwithModifier.fillMaxWidth().wrapContentHeight(). A literal translation produces awkward Compose. - Test parity before deleting XML. Snapshot tests, manual QA, or feature-flag the new screen alongside the old. Don't delete the XML in the same PR that introduces the Composable.
- Use semantic
testTagfor tests, not preservedandroid:idvalues. XML view IDs (R.id.submit_button) don't carry over; Compose usesModifier.testTag(...)andModifier.semantics { contentDescription = ... }. AndroidView { factory: ... update: ... }is for one-way binding from Compose state to aView. Don't try to round-trip — if state needs to flow back, lift it.
Output Format
For migration reviews, organize findings by file. For each issue:
- State the file and the XML element / Kotlin class.
- Name the migration concern.
- Show the XML/Fragment "before" and the Compose "after".
For migration work (rewriting a screen), make the changes directly and produce a final patch with the old XML deleted (or feature-flagged) and the new Composable + ViewModel wiring in place.
Example output:
res/layout/fragment_settings.xml + SettingsFragment.kt
Migrate to SettingsScreen Composable + Navigation-Compose route.
// Before (SettingsFragment.kt) — Fragment + ViewBinding + RecyclerView
class SettingsFragment : Fragment() {
private var _binding: FragmentSettingsBinding? = null
private val binding get() = _binding!!
private val viewModel: SettingsViewModel by viewModels()
override fun onCreateView(...): View {
_binding = FragmentSettingsBinding.inflate(inflater, container, false)
binding.recyclerView.adapter = SettingsAdapter { onClick(it) }
viewModel.items.observe(viewLifecycleOwner) { /* ... */ }
return binding.root
}
}
// After
@Composable
fun SettingsScreen(
onItemClick: (SettingsItem) -> Unit,
viewModel: SettingsViewModel = hiltViewModel()
) {
val state by viewModel.state.collectAsStateWithLifecycle()
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(state.items, key = { it.id }) { item ->
SettingsRow(item = item, onClick = { onItemClick(item) })
}
}
}
RecyclerView's DiffUtil is replaced by Compose's reference-equality-based recomposition. Provide a stable key (e.g., it.id) so Compose can match items across emissions.
Summary
- State exposure (medium):
SettingsViewModel.itemsisLiveData— migrate toStateFlowforcollectAsStateWithLifecycle()consistency with other migrated screens. - Theme (low): New
SettingsScreenreferencesMaterialTheme.colorScheme.surface; ensure the host theme defines a non-defaultcolorScheme.surface.
End of example.
References
references/interop-strategy.md— incremental vs all-at-once,ComposeViewin an XML layout,AndroidViewin a Composable, choosing screen-level vs widget-level migration boundaries.references/layout-migration.md— XML layouts → Compose equivalents:LinearLayout→Row/Column,ConstraintLayout→Modifierconstraints +ConstraintLayoutComposable,FrameLayout→Box,ScrollView→Modifier.verticalScroll(). Padding/margin/weight translation.references/recyclerview-to-lazy.md—RecyclerView.Adapter→LazyColumn/LazyRowwith stable keys;DiffUtil→ reference-equality recomposition; pagination viapaging-compose.references/fragment-to-composable.md—Fragmentlifecycle → Composable lifecycle,ViewBinding→ Composable parameters, fragment transactions → navigation route changes, ActivityResultLauncher / system permissions in Compose.references/navigation-migration.md— XMLnavigation/nav_graph.xml→ KotlinNavHost+composable("route"), type-safe arguments, deep links, navigation results.references/viewmodel-bridge.md— existingViewModels carry over;viewModel()/hiltViewModel(),LiveData→observeAsState()(or migrate toStateFlow+collectAsStateWithLifecycle()),SavedStateHandleunchanged.references/themes-styles.md—styles.xmlthemes →MaterialTheme(colorScheme, typography, shapes), dark/light handling, dynamic color (dynamicColorScheme), per-screen theme overrides.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: kelvinkosbab
- Source: kelvinkosbab/AppBootstrapAI
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.