Code Review And Quality
CommunityGuillemRoca
Use when reviewing Android code (own or others'). Five-axis review framework: Correctness, Readability, Architecture, Security, Performance. Categorized findings with Kotlin/Compose-specific checks.
Overview
- Repository
- GuillemRoca/agent-skills-android
- Publisher
- GuillemRoca
- Stars
- 6
- Forks
- 3
- Bundled files
- 0
- License
- MIT
- Updated
- Oct 3, 2026
Installation
tmp=$(mktemp -d)
git clone --depth 1 https://github.com/GuillemRoca/agent-skills-android.git "$tmp"
mkdir -p ~/.claude/skills
cp -R "$tmp/skills/code-review-and-quality" ~/.claude/skills/code-review-and-quality
rm -rf "$tmp"tmp=$(mktemp -d)
git clone --depth 1 https://github.com/GuillemRoca/agent-skills-android.git "$tmp"
mkdir -p ~/.codex/skills
cp -R "$tmp/skills/code-review-and-quality" ~/.codex/skills/code-review-and-quality
rm -rf "$tmp"Install the Code Review And Quality agent skill from https://github.com/GuillemRoca/agent-skills-android/tree/main/skills/code-review-and-quality into this project's skills folder.Instructions
Code Review and Quality
Overview
Review code across five axes: Correctness, Readability, Architecture, Security, and Performance. The approval standard: "Approve when it definitely improves overall code health of the system." Every finding is categorized and actionable.
When to Use
- Reviewing a pull request (own or teammate's)
- Self-review before creating a PR
- Requested code quality check on a specific file or module
- After completing a feature (final quality gate)
Skip when: Not reviewing code (this is a review skill, not a writing skill).
Core Process
Step 1: Understand Context
- Read the PR description — what problem does it solve?
- Read the spec or ticket — does the PR match the stated goal?
- Check the diff size — target ~100 lines, flag >1000 lines for splitting
Step 2: Review Tests First
Start with test files — they reveal the intended behavior
Check for:
- Are critical paths tested?
- Are edge cases covered (null, empty, error, boundary values)?
- Do test names describe behavior?
- Are tests independent (no shared mutable state)?
- Would a test fail if the new behavior regressed?
Answer the last question by experiment, not by reading: invert one condition the change adds (drop a
!, swap&&for||, flip a>=), run that module's tests (./gradlew :module:testDebugUnitTest), then restore the file. A mutation that stays green is a finding — name the missing test case. For a project-wide mutation score, seeconstraint-driven-development.
Step 3: Five-Axis Review
Axis 1: Correctness
- Verify behavior matches intent:
- Does the code handle all states? (loading, success, error, empty)
- Are nulls handled safely? (no
!!, proper?.chains) - Are coroutines structured correctly? (proper scope, cancellation)
- Are lifecycle-aware collections used? (
collectAsStateWithLifecycle) - Do Room queries match the schema?
- Are migrations correct and tested?
Axis 2: Readability
- Kotlin-specific readability:
// GOOD: idiomatic Kotlin
val activeTask = tasks.firstOrNull { !it.completed }
?: return TaskListUiState.Empty
// BAD: Java-style
var activeTask: Task? = null
for (task in tasks) {
if (!task.completed) {
activeTask = task
break
}
}
if (activeTask == null) return TaskListUiState.Empty- Check for:
- Clear naming (functions describe actions, variables describe content)
- Appropriate use of
whenexpressions,let/also/apply, extension functions - Functions under ~40 lines
- Sealed classes/interfaces for exhaustive state handling
- No nested callbacks (use coroutines)
Axis 3: Architecture
Verify layer boundaries:
- UI layer only calls ViewModel (never Repository/DAO directly)
- Domain layer has no Android dependencies
- Data layer implements domain interfaces
- Feature modules don't depend on each other
- No business logic in Composables
Check for:
- Proper use of
@Inject constructor(not field injection) StateFlowexposed from ViewModel (notMutableStateFlow)- Repository pattern for data access
- Single source of truth (local DB for offline-first)
- Proper use of
Axis 4: Security
- Check for:
- No hardcoded secrets, API keys, or passwords
- Input validation for user-provided data
- Proper intent validation (exported components)
- No logging of sensitive data (
Log.dwith tokens, passwords) - Secure storage (EncryptedSharedPreferences for sensitive data)
- See
security-and-hardeningfor comprehensive checklist
Axis 5: Performance
- Check for:
- N+1 query patterns in Room
- Unbounded data loading (should use Paging3 for large datasets)
- Unnecessary recompositions in Compose (unstable parameters, lambda allocations)
- Heavy work on main thread (use
withContext(Dispatchers.IO)) - Memory leaks (Activity/Context references in singletons)
- See
performance-optimizationfor comprehensive checklist
Dependency Upgrades
An upgrade is a behavior change you didn't write. The riskiest ones are bulk "bump deps" PRs. Review them with the same discipline:
- Read the changelog, not just the version. A "patch" can change behavior; a major bump (Kotlin, AGP, Compose BOM, Room) needs its migration notes read and the breakage found.
- One dependency per change (or one tightly related group, e.g. a BOM and its artifacts). When a bulk bump breaks the build, you've lost which one did it.
- Let the tests decide. Green suite before and after. If coverage around the dependency's behavior is thin, that gap is the finding — add a test first.
- Mind the transitive graph. Review the resolved diff, not just
gradle/libs.versions.toml:./gradlew :app:dependencies --configuration releaseRuntimeClasspathbefore and after. One direct bump can move dozens of transitive versions — and can raise your effectiveminSdkorcompileSdk. - Keep verification honest. If the project uses dependency locking or
gradle/verification-metadata.xml, regenerate them with Gradle (never hand-edit) and review their diff. For supply-chain risk, followsecurity-and-hardening.
Step 4: Categorize Findings
- Use severity categories:
| Category | Description | Action Required |
|---|---|---|
| Critical | Security vulnerability, data loss, crash | Must fix before merge |
| Important | Missing tests, architecture violation, bug risk | Should fix before merge |
| Suggestion | Better Kotlin idiom, readability improvement | Optional, author's discretion |
| Nit | Formatting, naming preference | Optional |
| FYI | Context or explanation, no action needed | Informational |
- Format findings:
**[Critical]** `TaskRepository.kt:45` — API key hardcoded in source.
Move to `local.properties` and access via `BuildConfig`.
**[Important]** `TaskListViewModel.kt:23` — Uses `GlobalScope.launch`.
Use `viewModelScope.launch` for proper lifecycle management.
**[Suggestion]** `TaskMapper.kt:12` — Could use `copy()` instead
of manual field mapping for partial updates.
Step 5: Verify Build and Tests
- Before approving:
./gradlew testpasses./gradlew assembleDebugbuilds./gradlew linthas no new warnings./gradlew detektpasses (if configured)
Common Rationalizations
| Shortcut | Why It Fails |
|---|---|
| "LGTM" without reading the code | Rubber-stamp reviews miss bugs. They also train teammates to skip reviews. |
| "I'll clean it up later" | Later never comes. Fix it now or create a tracked issue. |
| "It works, so it's fine" | Working code with poor architecture becomes non-working code during the next change. |
| "The author knows best" | Fresh eyes catch blind spots. That's the point of review. |
| "It's just a small change" | Small changes in the wrong layer create architectural debt. |
| "It's just a version bump" | A bump is a behavior change you didn't write. Read the changelog; semver doesn't guarantee no breakage. |
| "The tests cover it" | Prove it — mutate the new condition and see if anything goes red. |
Red Flags
- PR over 1000 lines without justification
- No tests in the PR
- Tests that only cover happy path
!!(non-null assertion) without justificationGlobalScopeusage- Mutable state exposed from ViewModel
- Business logic in Composables
- Feature module depending on another feature module
- Secrets or API keys in source code
@Suppressannotations without explanatory comments- A bulk "bump dependencies" PR with no changelog review and no per-dependency isolation
verification-metadata.xmlor lockfiles hand-edited or merged without reviewing their diff
Verification
- All five axes reviewed (Correctness, Readability, Architecture, Security, Performance)
- Tests reviewed first (coverage, edge cases, naming) — at least one new condition mutated to confirm a test catches its regression
- Dependency upgrades reviewed against changelogs, isolated per dependency, with the resolved-dependency diff checked
- Findings categorized (Critical, Important, Suggestion, Nit, FYI)
- Critical findings resolved before approval
-
./gradlew testpasses -
./gradlew assembleDebugbuilds -
./gradlew lintclean - PR size reasonable (~100 lines, flagged if >1000)
FAQ
What does Code Review And Quality do?
Use when reviewing Android code (own or others'). Five-axis review framework: Correctness, Readability, Architecture, Security, Performance. Categorized findings with Kotlin/Compose-specific checks.
Who made Code Review And Quality?
GuillemRoca (a community member) publishes it in the GuillemRoca/agent-skills-android repository on GitHub.
Is Code Review And Quality free?
Yes. Code Review And Quality is open source, published by GuillemRoca under the MIT license.
What comes with Code Review And Quality?
Just its instructions. Everything the agent needs is in one SKILL.md file.
Which agents can use Code Review And Quality?
Any coding agent that reads SKILL.md files, including Claude Code, Codex, Cursor, GitHub Copilot and Gemini CLI. The agent loads the skill when a task matches its description.
What are agent skills?
An agent skill is a folder with a SKILL.md file: instructions that teach a coding agent how to do one kind of task, and optionally files it can read while it works. The agent keeps only the skill's name and description in mind and reads the rest when a task calls for it.
How are agent skills different from MCP servers?
An MCP server gives an agent new tools to call, code that runs somewhere and returns results. A skill gives it knowledge: how to approach a task with the tools it already has. Many agents use both.
How can my agent test my Android app?
Robomori lets coding agents create, start and control Android emulators and devices from one command, so they can install your app, take screenshots and check dark mode, font sizes and languages.