You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apk Analyzer is an Android multi-module application that lets users inspect installed apps and APK files on their device. It shows app details (permissions, activities, services, certificates), device-wide statistics, and permission usage across all installed apps.
Language - Kotlin 2.4 (kotlin 2.4.10, ksp 2.3.10).
UI - Jetpack Compose only. No XML layouts.
Dependency Injection - Hilt 2.60.1. No Dagger/Koin.
Libraries - Use libraries from gradle/libs.versions.toml. Do not introduce new libraries unless required.
Concurrency - Kotlin coroutines and flows exclusively.
Build System - Gradle with convention plugins in build-logic/.
Every module listed below has its own AGENTS.md (dense, agent-oriented reference: purpose,
package, annotated structure, key interfaces, dependencies, known gotchas — not user
documentation) plus a one-line CLAUDE.md pointer. Read the specific module's AGENTS.md before
working inside it instead of re-deriving its structure from scratch.
Modules
Module
Gradle ID
Purpose
app
:app
Main Application class, ApkAnalyzerActivity, top-level Hilt wiring, navigation host
Top-level navigation uses NavigationState + Navigator from :core:navigation.
In app module, ApkAnalyzerApp.kt wires all entry providers via entryProvider { } block.
Entry transition metadata: use bottomEntryMetadata(), slideFromEndEntryMetadata() from core:uilibrary:animation.
Top-level destinations defined in app/ui/navigation/TopLevelDestinations.kt using NavigationBarItem.
Hilt Dependency Injection
ViewModels: annotate with @HiltViewModel, inject via @Inject constructor.
Assisted injection: use @HiltViewModel(assistedFactory = VM.Factory::class) + @AssistedFactory interface + @AssistedInject constructor (see AppDetailViewModel).
Hilt modules: use @Module @InstallIn(SingletonComponent::class). Prefer interface with @Binds for interfaces. Use class with @Provides for platform types.
Use @Singleton for repository/manager bindings.
Constructor injection with @Inject constructor() is preferred over module @Provides.
MVVM Architecture
ViewModel Pattern
Extend ViewModel() directly. No base class.
Expose val state: StateFlow<FeatureState> built with .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), initialValue) or a simple MutableStateFlow with backing field.
Events (one-shot): use Channel<Event>(Channel.BUFFERED) exposed as eventChannel.receiveAsFlow().
Actions: single fun onAction(action: FeatureAction) method with when dispatch.
In Composable: collect state with collectAsStateWithLifecycle(), collect events via LaunchedEffect.
State, Event, Action Pattern
State - sealed interface or @Immutable data class + StateFlow. No lambdas in State.
Define private const val TAG = "ClassName" at file level for ViewModel/Manager tags.
Serialization
Kotlin Serialization for navigation keys (@Serializable).
Parcelize for legacy Android-specific data (intents/bundles). Newer models use @Serializable.
Style & Conventions
Official Kotlin coding conventions.
data object instead of plain object for sealed interface members (e.g., data object Loading : State).
No wildcard imports.
Never write comments or KDoc in generated code — not even when the WHY seems non-obvious. Prefer self-documenting names/structure instead. Only exception: the user explicitly asks for a comment to be added in that specific instance.
Prefer private visibility; internal for module-visible.
public only for actual public API.
Spotless: ./gradlew spotlessApply before committing.
Ktlint config: multiline signatures at 3+ params, compose rules enabled.
Git commits: always authored as the human user only. Never add Co-Authored-By: Claude, Claude-Session:, or any AI co-author trailer. See .claude/skills/git-commit-author/SKILL.md.