Claude Code Skills for Android: Automate the Boilerplate You Write Every Day

What Skills Are in Claude Code

Once you’ve used Claude Code for a while you’ll notice you repeat the same prompts. “Create a new feature screen with a ViewModel and UiState.” “Add a Room entity and DAO for this model.” “Write a Hilt module that provides this repository.” These are perfect candidates for skills — reusable prompt templates that Claude Code loads on demand, so you get consistent, project-aware output with a single slash command instead of typing the same paragraph every time.

A skill is just a Markdown file with a structured prompt inside it, stored in .claude/skills/ at your project root. Claude Code discovers them automatically and makes them available as /skill-name in any session.

Code on a dark monitor
Skills turn your most-repeated prompts into single slash commands — consistent output every time.

Creating Your First Skill: New Feature Screen

The most useful Android skill to build first is one that scaffolds a complete feature: Compose screen, ViewModel with UiState, and a UseCase. Create the file .claude/skills/new-screen/SKILL.md:

# New Feature Screen

Create a complete Android feature screen with the following files:

1. `{FeatureName}Screen.kt` in `:feature:{feature-name}/ui/`
   - Jetpack Compose screen function annotated with @Composable
   - Collects uiState from ViewModel via collectAsStateWithLifecycle()
   - Passes only primitive/data values down to sub-composables (never the ViewModel)

2. `{FeatureName}ViewModel.kt` in `:feature:{feature-name}/ui/`
   - @HiltViewModel, constructor-injected dependencies
   - Exposes a single `uiState: StateFlow<{FeatureName}UiState>`
   - UiState is a data class with an isLoading: Boolean and an error: String?
   - All data loading launched in viewModelScope

3. `{FeatureName}UseCase.kt` in `:feature:{feature-name}/domain/`
   - Single operator fun invoke() method, returns Flow or suspend result
   - Constructor-injected repository interface

Ask the user for the feature name and its primary data type before generating.

Now whenever you type /new-screen in a Claude Code session, it reads this skill, asks you for the feature name, and generates all three files following your exact conventions — Hilt annotations, StateFlow, collectAsStateWithLifecycle, and all.

A Room Entity + DAO Skill

Database boilerplate is another time sink. Create .claude/skills/new-entity/SKILL.md:

# New Room Entity

Given a data model description from the user, generate:

1. A Room @Entity data class in `:core:database/entity/`
   - Use @PrimaryKey(autoGenerate = true) unless the user specifies a natural key
   - All nullable fields use Kotlin nullable types (not @Nullable annotation)
   - Include a companion object with a TABLE_NAME constant

2. A @Dao interface in `:core:database/dao/`
   - All methods are suspend functions (no RxJava, no LiveData)
   - Include: upsert(@Insert(onConflict = REPLACE)), getById(id), getAll() as Flow, deleteById(id)
   - Use @Transaction on any query that joins tables

3. A mapper extension function file `{Entity}Mapper.kt` in `:core:database/mapper/`
   - fun {Entity}.toDomain(): {Model}
   - fun {Model}.toEntity(): {Entity}

Ask the user for the entity name and its fields (name + type) before generating.

A Hilt Module Skill

Wiring up a new repository in Hilt always follows the same pattern. Create .claude/skills/hilt-module/SKILL.md:

# Hilt Binding Module

Generate a Hilt @Module that binds an interface to its implementation.

- Use @InstallIn(SingletonComponent::class) and @Singleton scope by default
- Use @Binds (not @Provides) since we're binding interface to implementation
- Place in `:core:di/` if it crosses module boundaries, otherwise in the feature module's di/ package
- Name the module {Interface}Module

Ask the user for: interface name, implementation class name, and which component to install in.

Tips for Writing Good Skills

A few things make the difference between a skill you use every day and one you ignore:

  • Tell the skill to ask first. End your skill with an instruction to ask the user for the specific inputs it needs — feature name, field list, etc. — before generating. This avoids generic placeholder output that you have to edit anyway.
  • Reference your real module paths. Use your actual module names (:feature:home, :core:database) rather than abstract placeholders. The generated code will land in the right place.
  • Specify what NOT to use. Listing anti-patterns is just as useful as listing patterns: “no LiveData”, “no field injection”, “no !! operator”. It’s a fast way to enforce team conventions without a linting rule for everything.
  • Keep each skill focused. One skill per concern is better than a monolithic scaffold skill. You can always invoke two skills in one session.

Sharing Skills Across Your Team

Because skills live inside .claude/skills/ in your project root, they’re committed to Git like any other file. Your whole team gets the same consistent scaffolding the moment they pull. New developers get your architecture conventions baked into their first generated files rather than learning them through code review feedback.

You can also put team-wide skills in a global ~/.claude/skills/ directory for things that apply across all your Android projects — a personal code style skill, a preferred test structure, or a commit message formatter.

Summary

Claude Code skills are the highest-leverage thing you can build after writing a solid CLAUDE.md. Start with the three patterns you scaffold most often — a new screen, a new database entity, and a new Hilt module — and you’ll save meaningful time every feature cycle. The skill files are plain text, live in Git, and become shared team knowledge the moment you commit them.

Again, this works with other coding LLM agents, maybe the naming differs. What skills do you use? What else would you suggest to add/remove/edit? :)


This post was written by a human with the help of Claude, an AI assistant by Anthropic.

Scroll to Top