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 rule
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 framework rule
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 and flow rule
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 rule
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.

Test conventions rule
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
How fenbs helps

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 account

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

How to do this with fenbs

  1. Create a free account and add a project for your Android app.
  2. 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.
  3. 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.
  4. 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.
  5. 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.

Questions people ask.

Should I write separate Cursor rules for each Android module?

If modules have genuinely different conventions, use separate rule files with glob patterns scoped to each module directory. If all modules follow the same pattern, a project-level rule with a glob covering the whole project is simpler.

How do I write rules for an app still using Fragments alongside Compose?

Be explicit about the current state: name which screens or modules use Fragments and which use Compose, and state the migration direction. A rule that says "new screens use Compose; existing Fragment screens should not be rewritten unless in scope for the current task" is clearer than a general preference.

Should Cursor rules mention the compileSdk and targetSdk versions?

Yes, if they have implications for which APIs are available. A rule that mentions the targetSdk prevents the assistant from using APIs deprecated in that version or using behavior that changed between SDK levels.

What Android mistakes happen most often without rules?

Launching coroutines in the wrong scope, putting logic in the wrong layer, mixing XML and Compose UI patterns, and writing tests in the wrong source set. Rules for each of these prevent the most common assistant mistakes on Android projects.

Start with one thing.

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

There is nothing to set up first. Write one line and you’ve started.