greenfish-cpm-skill
NewA Claude skill designed for working with Compose Multiplatform, based on my own experience using the Claude Code and CMP combination.
Summary
This skill provides conventions and best practices for building Compose Multiplatform apps with MVI architecture, Koin DI, and proper theming.
- It helps developers avoid common pitfalls and maintain consistency across screens and modules.
Overview
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
Install & Usage
mkdir -p .claude/skillsmkdir -p .claude/skills && curl -o .claude/skills/greenfish-cpm-skill.md https://raw.githubusercontent.com/DumbGreenFish/greenfish-cpm-skill/main/SKILL.md/greenfish-cpm-skillUse Cases
Usage Examples
/greenfish-cpm-skill Create a new login screen with MVI architecture under ui/login/
How should I set up Koin DI for my ViewModel in a CMP project?
Show me the correct way to apply theme content color without using Surface.
Security Audits
Frequently Asked Questions
What is greenfish-cpm-skill?
This skill provides conventions and best practices for building Compose Multiplatform apps with MVI architecture, Koin DI, and proper theming. It helps developers avoid common pitfalls and maintain consistency across screens and modules.
How to install greenfish-cpm-skill?
To install greenfish-cpm-skill: create the skills directory (mkdir -p .claude/skills), then run: mkdir -p .claude/skills && curl -o .claude/skills/greenfish-cpm-skill.md https://raw.githubusercontent.com/DumbGreenFish/greenfish-cpm-skill/main/SKILL.md. Finally, /greenfish-cpm-skill in Claude Code.
What is greenfish-cpm-skill best for?
greenfish-cpm-skill is a skill categorized under General. It is designed for: design. Created by DumbGreenFish.
What can I use greenfish-cpm-skill for?
greenfish-cpm-skill is useful for: Set up a new screen following MVI pattern with State, Intent, ViewModel, and View files.; Configure Koin dependency injection using annotations and KSP for type-safe module generation.; Apply theme colors correctly without unnecessary Surface wrappers using CompositionLocalProvider.; Name functions and classes contextually to avoid redundancy and improve code readability.; Refactor existing Compose Multiplatform code to align with recommended architecture and conventions..