This is how I built an Android app through conversation alone in a fresh Claude Code session, all the way to the edge of a Play Store release.
Instead of writing code myself, I focused on deciding what to build, checking the results, and steering the direction.
- Example app: 금연관리 / Quit Smoking (Kotlin, Jetpack Compose, local storage only, AdMob ads)
- Timeline: October 9, 2026 to November 2026 (one conversation, resumed many times)
- What I did: ideas, mockups and artwork, decisions, checking screens, anything involving accounts, passwords and keys
- What Claude did: design, code, tests, builds, emulator checks, source research, docs, Git
0. What you need
| Item | In this example | Notes |
|---|---|---|
| Claude Code | Desktop app (Code tab) | Turn on Remote Control to follow along from your phone |
| JDK 17 | D:\dev\java\temurin_jdk17 | Run Gradle with JDK 17 (the JBR bundled with Android Studio may be too new) |
| Android Studio + SDK | SDK in %LOCALAPPDATA%\Android\Sdk | Create one emulator (AVD) |
| Git + GitHub account | Source in a private repo, privacy policy on public GitHub Pages | |
| Image generator | ChatGPT | Avatars, mascots, icon, a short video |
Tip: When your PC sleeps, the remote connection and the emulator drop. Set "never sleep when plugged in" to save yourself trouble.
1. Turn the idea into two documents
Before the first prompt, write down what you want to build. These two files become the reference for every session after.
spec.md: features and formulas
- Screens, features, and formulas (e.g.
money saved = cigarettes not smoked × price per cigarette) - A list of open questions (
- [ ] How far should the avatar drop after a relapse?), checked off as you decide
CLAUDE.md: rules Claude reads every time
Claude Code reads this file automatically at the start of each session, so whatever you put here gets followed every time.
- Stack/structure: Kotlin, Compose, MVVM, DataStore, Room, WorkManager, and so on
- Core rules (the ones that mattered most for this app)
- All calculations live in a pure function
QuitCalculator, always unit-tested - Health figures are "estimates for reference", never medical claims
- Never invent recovery percentages or timelines without a source
- No blaming language after a relapse
- Only 3 required inputs
- Build order: 1) project, theme, tabs 2) calculator and tests 3) welcome, home, settings 4) missions, SOS, relapse, badges 5) notifications, avatar, ads
- Design tokens: colors, font, touch target sizes
CLAUDE.md is not write-once. Whenever a decision changes, ask Claude to "update CLAUDE.md too" so the next session knows.
Mockups
- I made HTML mockups of the screens and put them in
mockup/, with one file per screen inmockup/screens/. - In the first conversation I said "the attachment is the mockup for this app", and Claude followed its design tokens and layout.
2. First session: build in order
A first prompt can be as simple as:
Read CLAUDE.md and spec.md and start with step 1 of the build order.
The mockups are in mockup/. JDK and Android Studio are installed under D:\dev.
At each step Claude:
- Writes the code
- Builds, runs unit tests and lint
./gradlew assembleDebug testDebugUnitTest lintDebug
- Installs on the emulator and checks the screen with a screenshot
- Summarizes and proposes the next step
You only need to look at the screenshot or the APK and say "good" or "this looks off".
Where this project first got stuck: backslashes in the SDK path, Gradle not running on the newest JBR, and the emulator's AVD path. Claude read the error messages and fixed them.
3. Refining through conversation
Most features came out of this loop:
You: an idea or a pain point → Claude: options + a recommendation + reasons
You: a decision ("yes", "B") → Claude: implement → test → check the screen → APK
You: try it on your phone, give feedback → (repeat)
Real examples from this app
| What I said | What came out |
|---|---|
| "How about watching ads during the 3-minute challenge?" | An "ad" mode in the 3-minute challenge with a reward: collect 38 cheer angels, get a badge when complete, then start over |
| "Isn't anything other than breathing or ads pointless?" | Modes cut down to breathing and ads; the rest became a "try these too" checklist |
| "What happens to the health missions if I smoke one cigarette?" | After a relapse only short-term missions restart; long-term ones are kept (no evidence one cigarette resets long-term risk) |
| "Can you show recovery % for skin and lungs?" | Researched the sources and concluded no. No percentages, only sourced explanations |
| "Can '12 hours to a few days' be an exact number of days?" | Instead of a made-up number: the time the mission completes plus the range other sources give |
| "The icon is too small to tell it's an angel" | Compared variants, then made a dedicated icon in ChatGPT and generated adaptive and themed icons automatically |
| "What about tracking time saved?" → "Drop the book comparison, it differs per person" | Added time saved, then removed the comparison again |
Key point: don't hand decisions to Claude. Ask for options and choose yourself. If you don't like the result, roll it back.
4. Art, video and other assets
Assets that code can't make came from an image generator, and cropping and conversion were kept as scripts so they can be rerun.
| Asset | Source | Processing script |
|---|---|---|
| Avatars (4 looks × 2 genders × 5 stages) | ChatGPT sheet images | mockup/avatars/crop_sheets.py |
| Craving devil and cheer angel badges, 38 collectible items | ChatGPT character sheets | mockup/mascot/crop_mascot.py, crop_items.py |
| App icon | ChatGPT "broken cigarette + sprout" | mockup/icon/make_icon.py (adaptive, monochrome, Play 512px) |
| 30-second story video (Korean/English) | ChatGPT video | ffmpeg re-encode (mockup/story/README.md) |
Tip: Attach the image to the chat and say "crop this sheet into the 5 avatar stages". For large art, always preview how it looks at small size (48px).
5. Check facts against sources first
A health app is full of lines like "20 minutes after quitting, your heart rate drops". For these:
- Have Claude read the official sources directly (CDC, WHO, ACS, NHS).
- Summarize them in a table in
docs/health-sources.md(use / on hold / do not use). - Add a rule to CLAUDE.md: only items marked "use" in that table may appear in the app.
Figures without a source, such as "lung function improves 10% in 3 to 9 months" or hair regrowth rates, never made it into the app.
6. Habits that keep quality up
- Pure functions + unit tests for all calculations. About 50 tests ran on every change.
- Check on the emulator yourself. It catches the "the code changed but my phone shows the old screen" mistake. Make sure the new APK was actually installed.
- Test on a real device. Install the debug APK Claude sends, use it, and give feedback with screenshots.
- Lint. Before release, run
lintReleaseand confirm zero errors. - Claude is sometimes wrong (for example, it said the home screen had a banner ad when only the missions screen did). Confirm results on screen.
7. Getting ready to release
| Step | What | Who |
|---|---|---|
| App name and ID | Quit Smoking, com.example.quitsmoking style ID (can't change after the first upload) | You decide |
| Languages | English (default) + Korean, with an in-app language picker | Claude |
| Upload key | Created with keytool; you type the password yourself; keystore.properties stays out of Git | You |
| targetSdk | Raised to match Play policy (API 36+ required from August 31, 2026) | Claude, after checking the policy |
| AdMob | You create the app and ad units → Claude wires the IDs (real IDs in release only, test IDs in debug) | Together |
| Privacy policy | Claude drafts it → published on GitHub Pages | Together |
| app-ads.txt | Published at the root of the same Pages site | Claude |
| EU consent (UMP) message | Set up in the AdMob console → publish | Together |
| AAB build | ./gradlew bundleRelease, then verify it's signed with the upload key | Claude |
| Play Console | Register the app, data safety, content rating, closed testing (new personal accounts need 12 testers for 14 days) | You |
Claude doesn't type passwords, payment details or sign-ins for you. Do those yourself, say "done", and it continues from there.
8. Git / GitHub
git init -b main
git add -A
git commit -m "Initial commit"
git remote add origin https://github.com/<user>/<repo>.git
git push -u origin main
- Put keys, passwords and build output (
*.jks,keystore.properties,local.properties,dist/,build/) in.gitignorefirst, and check withgit ls-filesbefore committing. - Claude commits and pushes after each feature.
- If you're editing in VS Code at the same time, tell Claude which files you're touching so it stays away from them.
9. Picking up in a new session
When a session gets long, the early part is summarized, and a new session remembers nothing. So:
- Record decisions in CLAUDE.md / spec.md / docs/. A new session reads them automatically.
- A first message might be:
Read CLAUDE.md, spec.md and docs/ and summarize where things stand.
Then let's continue preparing the Play Console closed test.
git log --onelinealso shows the progress.
10. Requests I used often
| Situation | Request |
|---|---|
| New feature idea | "What if we added X? Give me options and a recommendation" |
| Decision | "Go with B" / "Default 7 minutes, add it everywhere" |
| Check | "Check it on the emulator with a screenshot" |
| Delivery | "Let me download the latest APK" / "Build the AAB" |
| Fact check | "Find the sources and check. Don't use numbers without a source" |
| Docs | "Update CLAUDE.md and spec.md too" |
| Roll back | "Drop the book comparison and just show the time" |
| Backup | "Commit and push to GitHub" |
11. Looking back
- Writing good rules in CLAUDE.md up front paid off the most. Principles like "no numbers without a source" and "no blaming language" kept the app's tone consistent as features piled up.
- Build in small steps, try each one on your phone, and say what you think right away. That's the fastest loop.
- For hard-to-undo things like accounts, keys, payments and publish buttons, either do them yourself or have Claude ask before it acts.








