Skip to content
Ali Sadeghi edited this page Jan 6, 2026 · 7 revisions

Skills

Skills activate automatically based on context—no manual invocation needed.

creating-kmp-feature

Auto-activates when: User mentions "create feature", "new module", "add feature"

Complete Feature Generation Workflow:

Phase 0: Context Discovery (AUTO)
├── Detect PKG_PREFIX from feature/*/build.gradle.kts
├── Find initKoin.kt path (contains startKoin)
├── Find BaseAppNavHost.kt path (contains NavHost)
└── Detect core module packages

Phase 1: PRD Generation
├── Analyze user prompt
├── Generate Product Requirements Document
├── Save to .claude/docs/{feature}/prd.txt
└── ⏸️ Wait for user approval

Phase 2: Task Generation
├── Break PRD into implementation tasks
├── Assign tasks to agents (data, ui, integration)
├── Save to .claude/docs/{feature}/tasks.md
└── ⏸️ Wait for user approval

Phase 3: Implementation (Parallel)
├── 🔧 data-layer-agent (runs in parallel)
│   ├── Create models with @Serializable
│   ├── Create Ktor Resources (type-safe routes)
│   ├── Implement RemoteDataSource (interface + impl)
│   ├── Implement Repository (interface + impl)
│   └── Validate build
│
├── 🎨 ui-layer-agent (runs in parallel)
│   ├── Create UiModel (presentation models)
│   ├── Implement ViewModel with 4-state pattern
│   ├── Create Composable Screens with X-components
│   ├── Setup Navigation with type-safe routes
│   └── Validate build
│
└── 🔗 integration-agent (runs after data + ui)
    ├── Create DI module with Koin
    ├── Add to settings.gradle.kts
    ├── Add dependency to composeApp
    ├── Register in initKoin.kt
    ├── Wire navigation in BaseAppNavHost.kt
    ├── Generate living specification
    └── Validate full build

Phase 4: Cleanup
├── Verify spec.md exists
├── Remove prd.txt (ephemeral)
├── Remove tasks.md (ephemeral)
└── Remove task-*.md files (ephemeral)

Examples:

Simple Feature (UI-only, no API):

> Create settings feature with toggle switches for notifications and dark mode

Generates: ViewModel, Screen, Navigation (no DataSource/Repository)

Complex Feature (API + multiple screens):

> Create product catalog with list, search, filters, and detail screens

Generates: Models, Ktor Resources, DataSource, Repository, UiModels, ViewModels, Screens, Navigation

Feature with Authentication:

> Create login feature with email/password and OAuth support

Generates: LoginRequest/Response models, AuthRepository, LoginViewModel, LoginScreen, token storage

What Gets Generated:

Data Layer:

// Models
@Serializable
data class Product(
    val id: String,
    val name: String,
    val price: Double,
    val imageUrl: String?
)

// Ktor Resources
@Resource("/products")
class ProductResource {
    @Resource("{id}")
    data class Id(val parent: ProductResource, val id: String)
}

// DataSource
interface ProductRemoteDataSource {
    suspend fun getProducts(): Either<List<Product>>
    suspend fun getProduct(id: String): Either<Product>
}

class ProductRemoteDataSourceImpl(
    private val client: ApiClient
) : ProductRemoteDataSource {
    override suspend fun getProducts(): Either<List<Product>> =
        client.get(ProductResource())
}

// Repository
interface ProductRepository {
    suspend fun getProducts(): Either<List<Product>>
    suspend fun getProduct(id: String): Either<Product>
}

class ProductRepositoryImpl(
    private val dataSource: ProductRemoteDataSource
) : ProductRepository {
    override suspend fun getProducts(): Either<List<Product>> =
        dataSource.getProducts()
}

UI Layer:

// UiModel
data class ProductUiModel(
    val id: String,
    val name: String,
    val price: String, // Formatted: "$99.99"
    val imageUrl: String?
)

// ViewModel
class ProductListViewModel(
    private val repository: ProductRepository
) : ViewModel() {
    private val _state = MutableStateFlow<ProductListUiState>(Uninitialized)
    val state: StateFlow<ProductListUiState> = _state.asStateFlow()

    fun loadProducts() {
        viewModelScope.launch {
            setState { Loading }
            when (val result = repository.getProducts()) {
                is Success -> setState {
                    Success(result.data.map { it.toUiModel() })
                }
                is Failure -> setState { Failed(result.error) }
            }
        }
    }
}

// Screen
@Composable
fun ProductListScreen(
    viewModel: ProductListViewModel = koinViewModel(),
    onProductClick: (String) -> Unit
) {
    val state by viewModel.state.collectAsState()

    XScaffold(
        title = { XText("Products") }
    ) {
        when (val currentState = state) {
            is Uninitialized -> LaunchedEffect(Unit) {
                viewModel.loadProducts()
            }
            is Loading -> XLoadingIndicator()
            is Success -> ProductList(
                products = currentState.products,
                onProductClick = onProductClick
            )
            is Failed -> XErrorView(error = currentState.error)
        }
    }
}

// Navigation
@Serializable
data class ProductListRoute(
    val onProductClick: (String) -> Unit
)

Integration:

// DI Module
class ProductModule : BaseFeature {
    override fun Module.install() {
        single<ProductRepository> { ProductRepositoryImpl(get()) }
        single<ProductRemoteDataSource> { ProductRemoteDataSourceImpl(get()) }
        viewModel { ProductListViewModel(get()) }
    }
}

// initKoin.kt (auto-registered)
modules(ProductModule().module)

// BaseAppNavHost.kt (auto-wired)
composable<ProductListRoute> {
    ProductListScreen(
        onProductClick = { id -> navController.navigate(ProductDetailRoute(id)) }
    )
}

modifying-kmp-feature

Auto-activates when: User mentions "change feature", "modify feature", "update feature", "add to feature"

Spec-First Modification Workflow:

Phase 0: Context Discovery (AUTO)
└── Detect project structure

Phase 1: Load Specification
├── Check for .claude/docs/{feature}/spec/*.md
├── If missing: Generate spec using /generate-spec
└── Load spec into context

Phase 2: Understand Current Implementation
├── Parse spec for architecture patterns
├── Identify data models, API contracts
├── Understand state management
└── Map navigation structure

Phase 3: Plan Changes
├── Determine affected layers (data/ui/integration)
├── Load relevant architecture references
├── Plan implementation approach
└── Identify files to modify

Phase 4: Implement Changes
├── Apply changes following established patterns
├── Maintain consistency with existing code
└── Follow 10 critical rules

Phase 5: Validate
├── Run incremental build
├── Run ktlintFormat
└── Fix any errors

Phase 6: Update Specification
├── Regenerate spec from implementation
├── Add changelog entry at top
└── Preserve previous changelog entries

Examples:

Add Functionality:

> Add sorting by price and date to the product list feature

Changes: ProductListViewModel (add sort state), ProductListScreen (add sort UI)

Refactor:

> Refactor the login screen to use a stepper for multi-step authentication

Changes: LoginUiState (add step state), LoginScreen (add stepper UI)

Fix Issues:

> Fix the loading state not showing in the profile feature

Changes: ProfileViewModel (fix state transition), ProfileScreen (verify loading UI)

Add New Screen:

> Add a forgot password screen to the login feature

Changes: Add ForgotPasswordScreen, update navigation, add ViewModel

Spec Changelog Entry:

## Last Updated

2025-01-05 - Added sorting by price and date
- ProductListUiState: Added sortBy field
- ProductListViewModel: Added setSortOrder function
- ProductListScreen: Added sort dropdown menu

2025-01-03 - Initial implementation
- Created product list with search and filters

using-design-system

Auto-activates when: Working in feature/*/ui/ directories, creating Composables, mentions "UI", "screen", "component"

Design System Enforcement:

Ensures X-components are used instead of Material3, preventing design drift.

Component Mappings:

// ❌ Material3          // ✅ X-Components
ScaffoldXScaffold
ButtonXButton
OutlinedButtonXOutlinedButton
TextButtonXTextButton
TextXText
TextFieldXTextField
OutlinedTextFieldXOutlinedTextField
CardXCard
IconXIcon
IconButtonXIconButton
SwitchXSwitch
CheckboxXCheckbox
RadioButtonXRadioButton
DividerXDivider
CircularProgressIndicatorXLoadingIndicator

Examples:

Creating a Login Form:

> Create a login form with email, password, and submit button

AI generates:

@Composable
fun LoginForm(
    email: String,
    password: String,
    onEmailChange: (String) -> Unit,
    onPasswordChange: (String) -> Unit,
    onSubmit: () -> Unit
) {
    Column {
        XTextField(
            value = email,
            onValueChange = onEmailChange,
            label = { XText("Email") }
        )

        XTextField(
            value = password,
            onValueChange = onPasswordChange,
            label = { XText("Password") },
            visualTransformation = PasswordVisualTransformation()
        )

        XButton(
            onClick = onSubmit,
            text = "Login"
        )
    }
}

Creating a Product Card:

> Create a product card component with image, title, price, and add to cart button

AI generates using XCard, XText, XButton (not Material3 components)

Theme Usage:

// ✅ Correct
XTheme {
    XScaffold { }
}

// ❌ Wrong
MaterialTheme {
    Scaffold { }
}

bridging-swift-kotlin

Auto-activates when: User mentions "Swift bridge", "iOS integration", "native SDK"

Swift-to-Kotlin Integration Patterns:

Uses interface injection to integrate iOS-specific SDKs while maintaining Clean Architecture.

Pattern:

1. Define Kotlin interface (commonMain)
2. Implement in Kotlin (androidMain) - usually stub
3. Implement in Swift (iosMain via expect/actual)
4. Inject via Koin DI

Examples:

Biometric Authentication:

> Integrate iOS Face ID authentication into the login feature

Generates:

// commonMain - Interface
interface BiometricAuthenticator {
    suspend fun authenticate(reason: String): Either<Boolean>
}

// androidMain - Android implementation
actual class BiometricAuthenticatorImpl : BiometricAuthenticator {
    override suspend fun authenticate(reason: String): Either<Boolean> {
        // Android BiometricPrompt implementation
    }
}

// iosMain - expect/actual bridge
expect class BiometricAuthenticatorImpl() : BiometricAuthenticator

// iosMain Swift bridge
@Composable
actual fun rememberBiometricAuthenticator(): BiometricAuthenticator {
    return remember { BiometricAuthenticatorSwiftBridge() }
}
// Swift implementation
class BiometricAuthenticatorSwiftBridge: BiometricAuthenticator {
    func authenticate(reason: String) async -> Either<Bool> {
        let context = LAContext()
        // Face ID implementation
    }
}

Camera Integration:

> Add iOS camera capture to the profile photo feature

Payment Processing:

> Integrate Apple Pay into the checkout feature

Push Notifications:

> Add iOS push notification handling to the messaging feature

Clone this wiki locally