Whether you use Claude Code, GitHub Copilot, Gemini, or Codex — most Android developers are burning tokens and getting inconsistent results. I fixed that with 28 files.
I've been building Apps Manager — a production Play Store app with 163 Java files, Firebase, AdMob, Google Billing, WorkManager, widgets, and a gamification system. Yes, it's Java — not Kotlin, not Compose. A migration is on the roadmap, but if you've maintained a legacy app, you know that's a "when we have bandwidth" task. The codebase works, ships, and earns revenue.
I use Claude Code, Codex, and Gemini in Android Studio daily. They've helped me fix data races, modernize deprecated APIs, and ship features faster. But here's the part nobody talks about: these tools don't actually know your project.
You open a session, ask the AI to add a feature, and it suggests converting your Java to Kotlin. Or proposes Compose when your UI is XML. Or autocompletes a Hilt injection when you have zero DI. My project has 3 Retrofit clients — the AI picks the wrong one every time. I have a theme system where ThemeUtil.applyTheme() must be called before super.onCreate() — the AI puts it after.
I was spending the first 3-4 messages of every session just correcting the AI. And when a teammate started using these tools? Same problem. Every developer having the same "no, this is Java" conversation independently. Claude Code, Copilot, Gemini — didn't matter. The problem was the same: no project-level context.
Then I discovered 5 features in Claude Code that most developers never set up — and the principles apply to every AI coding tool.
The 5 Features Nobody Talks About
Claude Code isn't just a chat window. It has a proper configuration system:
1. CLAUDE.md — A file at your project root that Claude reads automatically every session. Think of it as your project's identity card. Your architecture, conventions, tech stack, build commands, things to never do — all in one place.
2. Skills — On-demand expertise files that Claude loads only when relevant. Unlike CLAUDE.md (always loaded), Skills activate contextually. A "Firebase patterns" skill loads when you're working with Firebase. An "AdMob patterns" skill loads when you touch ad code. This keeps your context window clean.
3. Sub-agents — Isolated Claude instances for focused tasks. Need a code review? Spawn a sub-agent. It reviews the code, returns results, and doesn't pollute your main conversation.
4. Hooks — Automated guardrails that fire on specific events. Edit a file? Run lint automatically. Try to commit to main? Block it. Create a model class? Remind about ProGuard rules. No manual intervention needed.
5. MCP Servers — Connections to external services. Claude can create GitHub PRs, check Firebase data, and interact with your actual development tools — not just your codebase.
When you combine all five, Claude Code transforms from a chatbot into a configured development partner.
A note for Copilot/Gemini/Codex users: While I'm demonstrating this with Claude Code (because it has the most mature configuration system right now), every AI coding tool is moving in this direction. GitHub Copilot has custom instructions and .github/copilot-instructions.md. Gemini in Android Studio reads project context. Codex supports system prompts. The concept of giving your AI tool project-level memory is universal — the implementation details differ, but the mindset is the same. What you learn here applies everywhere.
What I Actually Built
Here's the full setup I created for my Android project — every file tailored to my real codebase, not a demo project.
CLAUDE.md — The Foundation
This is the single most impactful file. Here's what mine includes:
# Project: Apps Manager by MyInnos
## Architecture
- Single-module Android app (app/ only)
- Pattern: MVC (Activity-based)
- Language: Java only (no Kotlin files in project)
- UI: XML layouts with ViewBinding + DataBinding (no Jetpack Compose)
- Gradle: Groovy DSL (build.gradle, not .kts)
## Important Rules
- NEVER suggest Kotlin — this is a Java-only project
- NEVER suggest Jetpack Compose — this uses XML layouts
- NEVER suggest Hilt/Dagger — no DI framework in use
- NEVER suggest Room — data is in SharedPreferences + Firebase
- BaseActivity is 63.5KB — don't add more to it
- Always handle ad-free state (isAdFree()) when touching ad code
That last section is the game-changer. Without it, Claude would suggest Kotlin every other response. With it, Claude stays in Java mode and follows my actual patterns.
My full CLAUDE.md includes the package structure, all 3 Retrofit client URLs, SharedPreferences key constants, build commands, git conventions, and testing notes. It's about 200 lines — comprehensive but not bloated.
8 Skills — Context-Aware Expertise
Instead of generic skills, I built ones that match my exact codebase:
| Skill | What It Knows |
|---|---|
| retrofit-api-patterns | My 3 separate Retrofit clients, endpoint patterns, Gson model conventions |
| firebase-patterns | My Analytics events, RemoteConfig flags, Realtime DB write structure |
| activity-ui-patterns | ViewBinding setup, ThemeUtil.applyTheme() before super.onCreate(), edge-to-edge |
| admob-patterns | Banner lifecycle, interstitial dual-frequency control, rewarded ads memory guard |
| billing-subscription | BillingClient singleton, purchase acknowledgement, points-based theme unlocking |
| leaderboard-gamification | 7-day streak cycle, badge unlocks, referral system, coupon redemption |
| widget-receiver-patterns | goAsync(), AtomicInteger task tracking, PendingIntent flags |
| workmanager-patterns | Weekly report worker, snapshot comparison, notification channels |
Each skill is a SKILL.md file inside .claude/skills/{name}/. When I ask Claude to "add a new API endpoint," it auto-loads the retrofit-api-patterns skill and knows to use @SerializedName, check which of my 3 Retrofit clients to use, null-check response.body(), and log failures to Crashlytics.
Here's a snippet from my AdMob skill:
## Interstitial Ad — Dual Frequency Control
Two gates must pass before showing:
1. Time gap — ad_interstitial_timegap seconds since last show (from RemoteConfig)
2. Interaction gap — ad_interstitial_interaction_gap interactions since last show
## Rules
- NEVER show ads without checking isAdFree() first
- NEVER show ads without consent (canRequestAds())
- NEVER load rewarded ads on low-memory devices
This means Claude will never accidentally break my ad logic. Every ad-related change respects the consent flow, subscription state, and memory constraints.
5 Sub-agents — Isolated Specialists
These are my favorite. Each agent has a focused job:
| Agent | Role |
|---|---|
| code-reviewer | Reviews Java/XML for memory leaks, lifecycle issues, thread safety, null safety |
| architecture-analyst | Finds God classes, circular dependencies, code duplication |
| security-auditor | Checks cleartext traffic, unencrypted storage, WebView risks, permission issues |
| performance-analyzer | Spots main-thread blocking, RecyclerView inefficiency, widget refresh cost |
| api-contract-validator | Verifies Retrofit endpoints match model classes, checks ProGuard coverage |
When I ask "review the leaderboard package for security issues," Claude spawns the security-auditor in isolation. It scans the files, returns findings categorized as HIGH/MEDIUM/LOW severity, and doesn't clutter my main conversation.
My code-reviewer agent is specifically tuned for Java (not Kotlin), checks for Android-specific issues like isFinishing() guards, and knows about my ad system's isAdFree() requirement.
6 Hooks — Automatic Guardrails
These run without me doing anything:
| Hook | Trigger | Action |
|---|---|---|
| prevent-main-commit |
git commit on main/develop |
Blocks with error message |
| commit-message-format | Any git commit
|
Enforces type(scope): description format |
| manifest-validation | Edit AndroidManifest.xml | Validates XML structure |
| proguard-reminder | Edit any model class | Checks if ProGuard rules cover it |
| post-edit-lint | Edit any Java/XML file | Runs lint check |
| test-reminder | Claude stops working | Reminds that zero tests exist |
The commit message hook is surprisingly useful. My project uses conventional commits (feat(leaderboard): add streak badges), and now Claude can't commit with a lazy "updated files" message.
The ProGuard reminder has already saved me. I added a new API model class, and the hook immediately flagged that it wasn't in proguard-rules.pro. Without this, the release build would crash with Gson deserialization errors.
MCP Servers — External Connections
I connected 3 external services:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
},
"firebase": {
"command": "npx",
"args": ["-y", "firebase-tools@latest", "mcp"]
},
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"]
}
}
}
Now I can say "create a GitHub issue for the streak reset bug" and Claude actually creates it on my real repo. No copy-pasting, no switching tabs.
6 Slash Commands — Repeatable Workflows
For tasks I do often:
-
/create-activity UserInsightsActivity— scaffolds Activity + XML + manifest entry -
/create-model AppRatingModel— creates Gson model + ProGuard rules -
/create-adapter WeeklyStatsAdapter— RecyclerView adapter with ClickerInterface -
/create-api-endpoint get-user-stats— endpoint + model + error handling -
/review-module leaderBoard— triggers code review sub-agent -
/version-bump patch— increments versionCode/versionName
Each command follows my exact project conventions. /create-activity knows to call ThemeUtil.applyTheme() before super.onCreate(), use CoordinatorLayout as root, and register in the manifest. Every time. Consistently.
The Token Savings Are Real
Before this setup, a typical session started with 3-4 messages just establishing context. "This is Java." "We use ViewBinding." "Don't suggest Kotlin." "Here's how our API clients work." Each message costs tokens — both in what you send and what Claude processes.
Now? First message, first task. Claude already knows everything. For a team of developers, multiply that saving across every session, every day.
But the bigger win is consistency. When my teammate uses Claude Code on this project, they get the same conventions, same patterns, same guardrails. No more "Claude suggested Kotlin to me but Java to you." The CLAUDE.md is committed to git — it's shared across the team.
How to Set This Up for Your Project
The complete folder structure:
your-android-project/
├── CLAUDE.md # Always-loaded project rules
├── .mcp.json # MCP server connections
├── .claude/
│ ├── settings.json # Hooks configuration
│ ├── settings.local.json # Personal overrides (gitignored)
│ ├── commands/ # Slash commands
│ │ ├── create-activity.md
│ │ ├── create-adapter.md
│ │ └── ...
│ ├── skills/ # On-demand expertise
│ │ ├── retrofit-api-patterns/
│ │ │ └── SKILL.md
│ │ ├── firebase-patterns/
│ │ │ └── SKILL.md
│ │ └── ...
│ ├── agents/ # Sub-agents
│ │ ├── code-reviewer.md
│ │ ├── security-auditor.md
│ │ └── ...
│ └── hooks/ # Automated guardrails
│ ├── prevent-main-commit.sh
│ ├── proguard-reminder.sh
│ └── ...
└── app/
Start with CLAUDE.md — it gives you the biggest immediate improvement. Write your actual project rules, not aspirational ones. If your project is Java, say Java. If it's a monolith, say monolith.
Then add Skills for the patterns you repeat most. Look at your last 10 Claude conversations — what did you explain more than once? That's a skill.
Hooks come next — start with the commit protection ones. They prevent mistakes with zero effort.
Sub-agents and MCP servers are the advanced layer. Add them when you're comfortable with the basics.
The Decision Matrix
| Situation | Feature |
|---|---|
| Always applies to every task? | CLAUDE.md |
| Needed sometimes, context-specific? | Skill |
| Need isolated, focused work? | Sub-agent |
| Want automatic enforcement? | Hook |
| Need external data/services? | MCP Server |
| Repeatable multi-step workflow? | Slash Command |
What This Means for Android Teams
Most Android developers are using AI coding tools like a chat window — type a question, get an answer, repeat. Whether it's Claude Code, Copilot, Gemini, or Codex — they're leaving 80% of the tool's capability on the table.
The problem isn't the AI. It's the setup. Or rather, the lack of it.
Setting up project-level context takes about an hour. The payoff is immediate: fewer wasted tokens, consistent code patterns, automatic guardrails, and a shared knowledge base that every team member benefits from. Commit the configuration files to git, and every developer on the team gets the same AI experience from day one.
My Apps Manager project went from "the AI sometimes suggests Kotlin on a Java project" to "it knows every convention, catches ProGuard mistakes automatically, and creates GitHub PRs without me switching tabs."
28 files. One hour of setup. Every session after that is faster, cheaper, and more consistent.
The Bigger Picture
We're at an interesting moment in Android development. AI coding tools are becoming essential, but most developers treat them like Stack Overflow with autocomplete. They ask questions, get answers, and move on.
The developers who will get ahead are the ones who configure their AI tools — who invest an hour upfront to save hundreds of hours over the lifetime of a project. This isn't about which AI tool you use. Claude Code, Copilot, Gemini, Codex — they all benefit from project-level context. The specific features I showed (CLAUDE.md, Skills, Hooks, Sub-agents, MCP) are Claude Code's implementation, but every tool has its equivalent:
| Concept | Claude Code | GitHub Copilot | Gemini | Codex |
|---|---|---|---|---|
| Project context | CLAUDE.md | .github/copilot-instructions.md | Project context | System prompts |
| On-demand rules | Skills | — | — | — |
| Automated checks | Hooks | Pre-commit hooks | — | — |
| External tools | MCP Servers | Extensions | Extensions | Plugins |
The tool-specific features will converge over time. The mindset of "configure your AI before you use it" is what matters.
If you're using any AI coding tool for Android development without project-level setup — you're doing it wrong. Start with one file. Write your project's rules. Watch everything change.
The setup I showed is tailored for a Java/XML codebase, but the same approach works for any Android project — Kotlin, Compose, multi-module, whatever your stack is. Adapt the files to your project's conventions and you're good to go.
Check out Apps Manager: appsmanager.app
If you found this useful, share it with your Android team. This is the kind of setup that saves everyone tokens and headaches.
Follow me for more Android development + AI tooling content.
Tags: #AndroidDev #ClaudeCode #AI #Automation #AndroidStudio #GitHubCopilot #Gemini #Codex #Productivity #DeveloperTools
Top comments (2)
Nice writeup - getting the AI tool "set up right" is usually 80% of the outcome.
One thing we’ve found helpful is to treat the agent like a junior dev: lock down the build/test loop (gradle tasks, formatting, lint), and make it easy to run a single failing test or module so the model gets tight feedback. On Android, keeping a clear boundary around platform code vs shared domain logic also reduces the weird refactors.
Curious if you tried any guardrails around generated code (like disallowing edits to certain packages, or requiring changes to go through small PR-sized diffs)?
Thanks Mahima! Great points.
Yes — that "treat the agent like a junior dev" mindset is exactly what drove this setup. The Hooks system is where the guardrails live. For example, I have a hook that blocks commits directly to main/develop, another that enforces conventional commit message format, and one that automatically reminds about ProGuard rules when model classes are edited.
On the "disallowing edits to certain packages" front — the CLAUDE.md itself acts as the first guardrail. Mine explicitly says "BaseActivity is 63.5KB — don't add more to it." Claude respects this and creates new Activities instead of bloating the God class further. You could go deeper with hooks that reject edits to specific files, but I've found the CLAUDE.md rules are usually enough.
For PR-sized diffs — I haven't enforced that through hooks yet, but that's a great idea. Right now the Sub-agents handle review: after a feature is built, I spawn a code-reviewer agent that scans the changes in isolation. But adding a hook that flags large diffs before committing would be a solid addition.
The platform code vs domain logic boundary you mentioned is something I want to explore more — especially as we plan the Kotlin + Compose migration. Would love to hear how your team handles that.