Greenfish cpm skill
A Claude skill designed for working with Compose Multiplatform, based on my own experience using the Claude Code and CMP combination.From the repository description
npx -y skills add DumbGreenFish/greenfish-cpm-skillAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.4 KB, 773 tokens by cl100k_base, as published. Nobody here has run it
Compose Multiplatform — Working Conventions
Architecture: MVI
Every screen follows this structure under ui/<feature>/:
*State— immutable data class; initializes with empty/default values, never hardcoded sample data*Intent— sealed class for user actions*ViewModel— holdsStateFlow<*State>, processes intents; annotated@KoinViewModel*View— Composable that observes state and dispatches intents
One function (or class) per file. No exceptions.
Dependency Injection (Koin)
Use annotation-based Koin: @Module, @KoinViewModel, component scanning on the root package. No manual module { } blocks or factory/single wiring unless annotations are unavailable. KSP generates type-safe builders at compile time.
Theme and Content Color
Never wrap a theme root in Surface just to set content color. Use CompositionLocalProvider:
CompositionLocalProvider(LocalContentColor provides colorScheme.onSurface) {
content()
}
Surface adds an implicit background layer. Use it only when you explicitly want a background drawn. CompositionLocalProvider is the right primitive for propagating color context.
Naming by Context
Do not repeat what the surrounding package or class already says. In package navigation.animation, a function called navAnimationColors() is redundant — animationColors() is enough. Before naming a symbol, check what the enclosing scope already implies; only add a qualifier if the name would be genuinely ambiguous without it.
Design Tokens
All animation constants (durations, spring stiffness, press scales) go in a single *Animation object. All extended color tokens go in a single *Colors object. Never inline magic numbers in UI code — if a value is used once, it still belongs in the token object.
M3 state layer opacity: 8% hover, 12% press. Active nav items: lerp(containerColor, onContainerColor, stateAlpha). Inactive: onSurface.copy(alpha = stateAlpha).
No Mock Data in Production
State classes and ViewModels initialize with empty collections and default values. Hardcoded sample or demo data belongs in test helpers or @Preview parameters only — never inline in production State or ViewModel files. The app is a working product, not a prototype.
No Magic Numbers in UI
Every numeric constant used in layout, animation, or color logic must be named. No Modifier.padding(12.dp) without a token; no alpha = 0.08f without a constant. Name it where it lives conceptually (animation object, color object, shape object).
Adaptive Layout
- Compact (width < 600 dp): bottom navigation
- Wide (width ≥ 600 dp): sidebar navigation + vertical divider + content in a
Row - Both branches use
Scaffoldso window insets are handled automatically currentWindowAdaptiveInfo()has nocommonMainalternative yet; suppress deprecation where needed
Android Specifics
Lock phones (smallestScreenWidthDp < 600) to portrait in Activity.onCreate(). Tablets and foldables rotate freely.
Antipatterns
- Do not use
Surfaceas a theme wrapper for content color propagation - Do not put mock/sample data inline in
StateorViewModel - Do not repeat package/class context in symbol names
- Do not use magic numbers anywhere in UI code — no inline dp, alpha, duration values
- Do not wire Koin manually when annotations are available
- Do not write multiple functions or classes in a single file
What ships with it: 2 files
36.5 KB alongside SKILL.md