Cursor Rules for Android and Kotlin Projects
A practical rule set for Android and Kotlin development in Cursor, covering lifecycle behavior, architecture patterns, and verification steps. Adapt each template to your project and keep accepted project decisions in fenbs.
Updated 6 min read
Cursor rules for an Android project tell the assistant how your app handles the Activity and Fragment lifecycle, which architecture pattern the project follows, how coroutines and flows are used, and how to run tests and checks. Android development has evolved through several architectural approaches, and many projects carry code from more than one era. Without rules, the assistant may write ViewBinding code in a project that uses Jetpack Compose, or introduce a handler pattern in a codebase that uses coroutines. fenbs helps teams record the decisions that make their Android conventions specific, so every connected assistant starts from the same approved foundation.
The templates below are starting points. Replace module names, class names, and package paths with your actual project values. Test each rule against a real file in your project before committing it.
Architecture and layer rules
Android projects using Clean Architecture or a similar layered approach need a rule that names the layers and the dependency direction between them. An assistant that puts repository code in a ViewModel or calls a use case from a data class creates technical debt that is hard to untangle.
Architecture: MVVM with Clean Architecture layers Layers (dependency direction: data <- domain <- presentation): - data/: repositories, data sources, remote/local models - domain/: use cases, domain models, repository interfaces - presentation/: ViewModels, UI state, Compose screens ViewModels import from domain only. Data layer implements domain interfaces. Do not import Android framework classes (Context, Activity) from domain.
Lifecycle and UI framework rules
Whether your project uses Jetpack Compose, the traditional View system, or both is the first thing a UI rule should establish. An assistant that generates XML layouts for a Compose project creates confusion, and vice versa. If the project is migrating, name the current state and the intended direction.
UI: Jetpack Compose throughout. Do not introduce XML layouts. Screen composables go in presentation/screens/. Reusable UI components go in presentation/components/. Collect StateFlow/SharedFlow in composables using collectAsStateWithLifecycle(). Do not use collectAsState() — use the Lifecycle-aware version. Minimum SDK: 24. Target SDK: 35.
Coroutines and flow rules
Kotlin coroutines replaced callback patterns in Android, but the right scope and dispatcher for each task varies by context. A ViewModel should launch coroutines in viewModelScope; a repository should be dispatcher-agnostic and let callers choose the context. A rule about dispatcher usage prevents the common mistake of running network calls on the main thread or UI updates on a background dispatcher.
Coroutines: - ViewModels: launch coroutines in viewModelScope - Repositories: suspend functions should be main-safe (use withContext(Dispatchers.IO) internally) - Do not use GlobalScope - Do not use runBlocking on the main thread Flow: - Expose StateFlow or SharedFlow from ViewModels, not Flow directly - Use catch() to handle errors in flows before they reach the UI layer
Dependency injection rules
If your project uses Hilt, Koin, or a custom DI approach, a rule naming the framework and how to add new dependencies prevents the assistant from creating manual instantiation in a project that expects everything to be injected.
Dependency injection: Hilt Annotate ViewModels with @HiltViewModel. Repositories are bound via @Binds in a Hilt module in data/di/. Do not instantiate repositories or use cases directly in a ViewModel. New dependencies: add them to the appropriate Hilt module, not directly to a constructor.
Test and verification rules
Android testing spans unit tests, integration tests, and UI tests with different tools and different setup requirements. A rule that names your test setup, which testing library you use, and how to run each type keeps new tests consistent with the existing suite.
Unit tests: - Location: src/test/ - Framework: JUnit 4 + MockK for mocking - ViewModel tests use TestCoroutineScheduler and UnconfinedTestDispatcher Instrumentation tests: - Location: src/androidTest/ - Framework: Espresso for UI, Hilt for injection in tests Run unit tests: ./gradlew test Run all checks: ./gradlew check
Store Android rules with the decisions behind them
Add your approved Android rules to fenbs Skills and prompts alongside the choices that shaped them: which architecture pattern was selected and why, which DI framework is in use, what the minimum SDK is and why. When the project updates its target SDK or migrates a layer to Compose, update the entry in fenbs so the next assistant starts from the current state.
Create a free accountFree for one person · No credit card · Works with Claude, ChatGPT, Cursor and more
How to do this with fenbs
- Create a free account and add a project for your Android app.
- Add a skill or prompt for each rule area: architecture, UI framework, coroutines, dependency injection, and tests. Keep each rule focused on decisions that prevent real mistakes.
- Record the key decisions in Decisions and rules: why the project uses Hilt over Koin, what the minimum SDK is and any constraints on changing it, which modules are not ready for Compose migration.
- When someone proposes changing the architecture or adding a new dependency pattern, record the proposal as an open decision in fenbs and wait for sign-off before updating the rules.
- Connect your AI tools from Integrations so they read the current rules before starting work on the app.
What a rule file cannot do
A Cursor rule describes coding conventions but does not prevent the assistant from making changes that break the build until you run ./gradlew build. Run the build and tests after any significant change, especially if the assistant modified module structure, Hilt annotations, or the DI setup. Rules guide the assistant toward correct patterns; your build system catches the errors.
Feature requirements, product context, and in-progress task state belong in your project notes in fenbs, not in rule files. See cursor rules for AI projects for how to structure both together.
Android development spans many years of API levels, and the gap between compileSdk and minSdk determines which APIs are safe to use unconditionally. A rule that mentions both values helps the assistant decide whether to wrap an API call in a version check. If the project targets devices running Android 8 (API 26) as the minimum, certain notification APIs and background execution rules differ significantly from newer versions. Naming the minSdk in the rule prevents the assistant from suggesting APIs that would fail on older devices.
When the project upgrades the Android Gradle Plugin or a major dependency like Jetpack Compose, review your rules for instructions that referenced an older API surface. Compose in particular evolves between minor versions. A rule about which APIs to use for animations or state hoisting may become outdated faster than a rule about architecture. Update the rule file after each significant dependency upgrade, not just after major version changes.
If the project uses Kotlin Multiplatform, a rule that names the module boundaries — what belongs in the shared module versus the Android-specific module — prevents the assistant from placing Android dependencies in code that must compile for other targets. The shared module typically has no Android or iOS dependencies. Keeping that boundary visible in the rules saves debugging time when a build fails because a platform import ended up in the wrong module.