Android CLI : The Future of Android Development from Terminal

Android development is no longer limited to Android Studio.

Google has introduced the Android CLI, a modern command-line interface designed for developers, automation systems, and AI agents.

In simple terms:

Android CLI = Build, run, test, and automate Android apps from your terminal — faster and smarter

 

What is Android CLI?

The Android CLI is a unified terminal interface that simplifies Android development workflows such as:

  • Project setup

  • SDK management

  • Emulator control

  • App deployment

  • UI inspection

  • Documentation access

It acts as a standardized entry point to Android tools and best practices.


Why Android CLI 

From Google’s official announcement:

  • 3× faster development using agents + CLI

  • 70% reduction in LLM token usage

  • Designed for AI-driven (agentic) workflows

This is a major shift:

Old ApproachNew Approach
Android Studio-centricCLI + AI agents
Manual setupAutomated setup
IDE-bound workflowsScriptable workflows


Version & Release

  • Version: 0.7

  • Release Date: April 2026

  • Status: First official release


Installation (Official)

Linux

curl -fsSL https://dl.google.com/android/cli/latest/linux_x86_64/install.sh | bash

macOS

curl -fsSL https://dl.google.com/android/cli/latest/darwin_arm64/install.sh | bash

Windows

curl.exe -fsSL https://dl.google.com/android/cli/latest/windows_x86_64/install.cmd -o "%TEMP%\i.cmd" && "%TEMP%\i.cmd"

Verify

which android

Update CLI

android update

Core Capabilities (Simplified)

Project Creation

android create --name MyApp --output ./MyApp

Uses official templates and applies best practices automatically.


SDK Management

android sdk install platforms/android-34
android sdk list
android sdk update

Install only required components for a lean environment.


Emulator Control

android emulator create
android emulator start medium_phone
android emulator list

No need to open Android Studio.


Run App

android run --apks=app-debug.apk

Direct APK deployment.


Project Analysis

android describe

Outputs APK paths, build targets, and project structure.


UI Automation

android screen capture --output=ui.png --annotate
android screen resolve --screenshot=ui.png --string="input tap #3"

Converts UI elements into coordinates for automation.


Layout Inspection

android layout --pretty

Returns UI tree as JSON for testing and accessibility.


Built-in Documentation

android docs search "performance"
android docs fetch kb://android/topic/performance/overview

Access official Android documentation inside the terminal.


Android CLI and AI Agents

Android CLI is designed to work with tools like:

  • Gemini

  • Claude Code

  • Codex

These agents can create projects, run apps, fix issues, and follow best practices automatically.


Android Skills

Android Skills are modular instruction sets for AI agents that help them:

  • Follow best practices

  • Avoid outdated patterns

  • Execute workflows correctly

Examples include:

  • Navigation setup

  • Edge-to-edge UI

  • Compose migration

  • R8 optimization

android skills list
android skills add --all


Android Knowledge Base

The CLI integrates a live knowledge system including:

  • Android Docs

  • Firebase Docs

  • Kotlin Docs

This ensures AI tools always use the latest Android guidance.


Real Workflow (Senior Engineer)

# Create project
android create --name DemoApp --output ./DemoApp

# Install SDK
android sdk install platforms/android-34

# Start emulator
android emulator create
android emulator start medium_phone

# Build app
./gradlew assembleDebug

# Deploy app
android run --apks=app/build/outputs/apk/debug/app-debug.apk

# Inspect UI
android layout --pretty

CI/CD Example

#!/bin/bash

android sdk install platforms/android-34
./gradlew clean assembleRelease
android run --apks=app-release.apk

Architecture

Developer / AI Agent
        ↓
   Android CLI
        ↓
SDK + Emulator + Device
        ↓
 Android App

Android CLI vs Android Studio

FeatureAndroid CLIAndroid Studio
AutomationYesLimited
AI IntegrationNativeGrowing
CI/CDIdealNot suitable
UI DesignNoStrong
DebuggingBasicAdvanced

Known Limitations

  • Windows emulator support is limited

  • Still early version (v0.7)

  • Requires Gradle for builds


Future of Android CLI

Expected improvements include:

  • Fully AI-driven development

  • Instant project scaffolding

  • Automated UI testing without frameworks

  • Cloud-native Android workflows


The Android CLI represents a shift in Android development.

Key takeaway:

Android Studio is for UI and debugging
Android CLI is for automation, scalability, and AI workflows

Android CLI is Google’s new unified terminal interface for Android development. It supports automation, CI/CD, and AI-driven workflows. I use it for project setup, SDK management, deployment, and UI automation using layout and screen commands. It integrates well with AI agents and Android skills.


References


Why Koin Can Be More Powerful Than Hilt in Android Development

Dependency Injection (DI) has become a cornerstone of modern Android development. Two of the most popular DI frameworks today are Koin and Hilt.

While Hilt is officially backed by Google and widely adopted, many developers argue that Koin can be more powerful in certain scenarios—especially in terms of simplicity, flexibility, and developer productivity.

In this article, we’ll explore why Koin can feel more powerful than Hilt, and when you should consider using it.


Understanding the Core Difference

At a high level:

  • Hilt → Compile-time Dependency Injection

  • Koin → Runtime Dependency Injection

This fundamental difference shapes everything else.


1. Simplicity & Developer Experience

Koin: Minimal Boilerplate

Koin is designed to be idiomatic Kotlin, meaning it feels natural to write and read.

val appModule = module {
    single { UserRepository(get()) }
    viewModel { UserViewModel(get()) }
}

No annotations. No generated code. No complex setup.

Hilt: Annotation-heavy

@HiltViewModel
class UserViewModel @Inject constructor(
    private val repository: UserRepository
) : ViewModel()

Plus modules, components, scopes, and generated code.

Why Koin feels more powerful here:

  • Faster onboarding

  • Less cognitive overhead

  • Cleaner codebase


2. No Compile-Time Overhead

Hilt Problem

Hilt relies on annotation processing (KAPT/KSP), which:

  • Slows down build times

  • Adds complexity to Gradle setup

  • Can cause cryptic compile errors

Koin Advantage

Koin works at runtime:

  • No annotation processing

  • Faster incremental builds

  • Fewer build failures

For large projects, this is a huge productivity win.


3. Dynamic Dependency Injection

Koin allows runtime decisions when injecting dependencies.

single {
    if (BuildConfig.DEBUG) DebugLogger() else ReleaseLogger()
}

Why this matters

  • Feature toggles

  • A/B testing

  • Environment-based configs

  • Dynamic modules

Hilt Limitation

Hilt is static (compile-time graph), so:

  • Less flexible for runtime conditions

  • Requires complex qualifiers or modules

Koin wins in flexibility and dynamic behavior.


4. Easier Testing

Testing with Koin is extremely simple.

val testModule = module {
    single<UserRepository> { FakeUserRepository() }
}

You can override modules easily.

Hilt Testing Challenges

  • Requires @HiltAndroidTest

  • Needs special test runners

  • More setup for mocking dependencies

Koin is more lightweight and test-friendly.


5. No Generated Code (Better Debugging)

Hilt

  • Generates hidden code

  • Stack traces can be confusing

  • Harder to debug DI issues

Koin

  • Everything is explicit

  • Easier to trace dependency issues

  • No magic behind the scenes

This transparency makes Koin feel more controllable.


6. Better for Kotlin Multiplatform (KMP)

If you're exploring Kotlin Multiplatform, Koin has a major edge.

  • Works seamlessly across platforms

  • No Android-specific dependencies

  • Lightweight and portable

Hilt, on the other hand:

  • Is tightly coupled to Android

  • Not suitable for KMP

For future-proof architecture, Koin is often the better choice.


7. Learning Curve

AspectKoin Hilt 
SetupEasyComplex
Learning CurveLowMedium–High
DebuggingSimpleHard
BoilerplateMinimalHigh

Koin empowers developers to focus on business logic instead of DI complexity.


When Hilt is Still Better

To be fair, Hilt has strong advantages:

  • Official Google support

  • Compile-time safety (fewer runtime crashes)

  • Better for very large teams with strict architecture

  • Deep integration with Android components

If you want strict, scalable architecture enforcement, Hilt may be the better choice.


Why Koin Feels More Powerful

Koin is not necessarily “better” in every case—but it feels more powerful because it gives you:

  • Full control at runtime

  • Faster development cycles

  • Simpler codebase

  • Better developer experience

  • Flexibility for modern architectures (KMP, dynamic features)


My Recommendation 

Given your experience level, here’s a practical guideline:

  • Use Koin when:

    • You want speed + flexibility

    • You’re working with Kotlin-first or KMP projects

    • You prefer clean, readable DI

  • Use Hilt when:

    • You need strict architecture enforcement

    • You’re in a large enterprise Android team

    • You want compile-time guarantees


In modern Android development, productivity and maintainability matter just as much as correctness.

Koin empowers developers to move fast without fighting the framework, while Hilt enforces structure and safety.

The real power lies in choosing the right tool for your context.


Migrating from Navigation 2 to Navigation 3 in Android

Modern Android development evolves rapidly, and Google's Jetpack libraries continuously improve developer experience and application architecture. One such evolution is the transition from Navigation 2 (Nav2) to Navigation 3 (Nav3).

If you're building modern apps with Jetpack Compose, Navigation 3 introduces a simpler, type-safe, and scalable navigation system that improves code maintainability and reduces runtime errors.


Why Navigation 3?

Jetpack Navigation 2 works well but has several limitations:

Common issues with Nav2:

  • String-based routes

  • Runtime navigation errors

  • Difficult deep-link handling

  • Hard-to-maintain argument passing

  • Poor type safety

Navigation 3 introduces:

✔  Type-safe destinations
✔  Compile-time safety
✔  Cleaner navigation APIs
✔  Better Compose integration
✔  Reduced boilerplate


Nav2 vs Nav3: Key Differences

FeatureNavigation 2Navigation 3
Route definitionString basedType-safe
ArgumentsManual parsingStrongly typed
SafetyRuntime errors possibleCompile-time safety
Compose integrationGoodExcellent
MaintainabilityModerateHigh

Dependency Setup

First, ensure your project is using the latest navigation library.

dependencies {
    implementation("androidx.navigation:navigation-compose:2.8.0")
}

Navigation 3 features are enabled via typed routes.


Navigation 2 Example (Before Migration)

Typical Nav2 implementation uses string routes.

Define Routes

object Routes {
    const val HOME = "home"
    const val DETAILS = "details/{id}"
}

NavHost Setup

NavHost(
    navController = navController,
    startDestination = Routes.HOME
) {

    composable(Routes.HOME) {
        HomeScreen {
            navController.navigate("details/10")
        }
    }

    composable(
        route = Routes.DETAILS,
        arguments = listOf(navArgument("id") { type = NavType.IntType })
    ) { backStackEntry ->

        val id = backStackEntry.arguments?.getInt("id")

        DetailScreen(id)
    }
}

Problems:

  • Hardcoded strings

  • Argument errors occur at runtime

  • Difficult refactoring


Navigation 3 Approach (Recommended)

Navigation 3 introduces type-safe destinations using Kotlin serialization or sealed classes.


Step 1: Define Type-safe Routes

Use sealed classes or data classes.

sealed class Screen {

    data object Home : Screen()

    data class Detail(val id: Int) : Screen()
}

This gives:

  • Compile-time safety

  • Strongly typed navigation


Step 2: Navigation Setup

NavHost(
    navController = navController,
    startDestination = Screen.Home
) {

    composable<Screen.Home> {

        HomeScreen {
            navController.navigate(Screen.Detail(10))
        }
    }

    composable<Screen.Detail> { entry ->

        val detail = entry.toRoute<Screen.Detail>()

        DetailScreen(detail.id)
    }
}

Now navigation is:

✔ type-safe
✔ compile-time validated
✔ easier to maintain


Step 3: Passing Arguments Safely

Old approach:

navController.navigate("details/10")

New Nav3 approach:

navController.navigate(Screen.Detail(10))

No more:

  • string concatenation

  • route parsing

  • argument mismatch errors


Migration Strategy for Production Apps

Large applications cannot migrate everything at once.

Recommended migration strategy:

Step 1 — Introduce Typed Routes

Convert existing routes to sealed classes gradually.

Step 2 — Replace String Navigation

Replace:

navController.navigate("details/$id")

With:

navController.navigate(Screen.Detail(id))

Step 3 — Remove navArgument()

Typed navigation removes the need for manual argument definitions.

Step 4 — Refactor Navigation Graph

Update composables to use typed navigation.


Best Practices for Navigation 3

1. Use Sealed Classes for Screens

sealed interface AppScreen

Keeps navigation organized.


2. Use Feature-Based Navigation

Structure navigation by feature modules.

Example:

navigation
 ├── auth
 ├── home
 ├── profile

Each feature owns its navigation graph.


3. Avoid Passing Large Objects

Pass IDs instead of full models.

Good:

Screen.Detail(productId)

Bad:

Screen.Detail(product)

4. Keep Navigation in One Layer

Recommended architecture:

UI Layer
   ↓
Navigation Layer
   ↓
ViewModel
   ↓
Repository

Example Project Structure

A clean navigation architecture might look like this:

app
 ├── navigation
 │     AppNavHost.kt
 │     Screen.kt
 │
 ├── features
 │     ├── home
 │     ├── detail
 │     ├── profile
 │
 ├── ui
 ├── data
 ├── domain

Performance Benefits

Navigation 3 also improves performance because:

  • Fewer runtime checks

  • Cleaner back stack management

  • Reduced route parsing


Common Migration Pitfalls

Avoid these mistakes:

❌ Mixing typed routes with string routes
❌ Passing complex objects between screens
❌ Creating huge navigation graphs

Instead:

✔ Keep navigation modular
✔ Use feature-based graphs
✔ Pass only necessary arguments


When Should You Migrate?

Migration is recommended if:

  • Your app uses Jetpack Compose

  • You maintain a large codebase

  • You want compile-time navigation safety

If your project still uses Fragments, Nav2 may still be sufficient.


My Thoughts

Navigation 3 represents a major improvement in Android navigation architecture, especially for Compose-first applications.

By adopting:

  • Type-safe routes

  • Cleaner APIs

  • Compile-time safety

Android engineers can build more maintainable, scalable, and safer navigation systems.

If you are starting a new Jetpack Compose project today, Navigation 3 should be your default choice.