Agent skill

Compose Navigation

by Moustachauve in Moustachauve/WLED-Android

Implement navigation in Jetpack Compose using Navigation Compose.

Apache-2.0Auto-check passedMobile

Install Compose Navigation

skills CLI
$ npx skills add Moustachauve/WLED-Android --skill compose-navigation -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Moustachauve/WLED-Android compose-navigation --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Moustachauve/WLED-Android.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.github/skills/compose-navigation .claude/skills/compose-navigation && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
compose-navigation
GitHub stars
169
Used in
1 other repo
Token cost
~2.7k tokens
SKILL.md length
188 words
Files
1
Skills in repo
17
Repo updated
First seen
Licence
Apache-2.0

At a glance

Implement navigation in Jetpack Compose using Navigation Compose.

  • Works in 3 steps: Define Routes (Type-Safe) → Create NavController → Create NavHost
  • Asked to set up navigation
  • SKILL.md covers Overview, Setup, Core Concepts and Navigation Patterns, plus 7 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Compose Navigation is an agent skill from Moustachauve/WLED-Android. Implement navigation in Jetpack Compose using Navigation Compose. Use when asked to set up navigation, pass arguments between screens, handle deep links, or structure multi-screen apps.

Its SKILL.md is about 2.7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Mobile, covering Android development. It works with Jetpack Compose. The repository describes itself as: Native Android application for WLED. The licence is Apache-2.0.

When your agent uses it

  • Asked to set up navigation
  • Pass arguments between screens
  • Handle deep links
  • Structure multi-screen apps

Example prompts

  • “/compose-navigation”

Workflow steps

3 steps, taken from the step headings in SKILL.md.

  1. Define Routes (Type-Safe)
  2. Create NavController
  3. Create NavHost

What it can do on your machine

Read from SKILL.md and the folder at commit 7e164a8. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are kotlin and xml).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • developer.android.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Compose Navigation loads about 2.7k tokens when it runs. Until then it costs about 51 tokens; SKILL.md has 188 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~51
When it runs · the whole SKILL.md, loaded when a task matches
~2.7k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Moustachauve/WLED-Android at commit 7e164a8, republished under its Apache-2.0 licence (© Moustachauve). 188 words, ~2,694 tokens.

Download SKILL.mdSave it as .claude/skills/compose-navigation/SKILL.md (or your agent's skills folder).
name
compose-navigation
description
Implement navigation in Jetpack Compose using Navigation Compose. Use when asked to set up navigation, pass arguments between screens, handle deep links, or structure multi-screen apps.

Compose Navigation

Overview

Implement type-safe navigation in Jetpack Compose applications using the Navigation Compose library. This skill covers NavHost setup, argument passing, deep links, nested graphs, adaptive navigation, and testing.

Setup

Add the Navigation Compose dependency:

kotlin
// build.gradle.kts
dependencies {
    implementation("androidx.navigation:navigation-compose:2.8.5")
    
    // For type-safe navigation (recommended)
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
}

// Enable serialization plugin
plugins {
    kotlin("plugin.serialization") version "2.0.21"
}

Core Concepts

1. Define Routes (Type-Safe)

Use @Serializable data classes/objects for type-safe routes:

kotlin
import kotlinx.serialization.Serializable

// Simple screen (no arguments)
@Serializable
object Home

// Screen with required argument
@Serializable
data class Profile(val userId: String)

// Screen with optional argument
@Serializable
data class Settings(val section: String? = null)

// Screen with multiple arguments
@Serializable
data class ProductDetail(val productId: String, val showReviews: Boolean = false)
2. Create NavController
kotlin
@Composable
fun MyApp() {
    val navController = rememberNavController()
    
    AppNavHost(navController = navController)
}
3. Create NavHost
kotlin
@Composable
fun AppNavHost(
    navController: NavHostController,
    modifier: Modifier = Modifier
) {
    NavHost(
        navController = navController,
        startDestination = Home,
        modifier = modifier
    ) {
        composable<Home> {
            HomeScreen(
                onNavigateToProfile = { userId ->
                    navController.navigate(Profile(userId))
                }
            )
        }
        
        composable<Profile> { backStackEntry ->
            val profile: Profile = backStackEntry.toRoute()
            ProfileScreen(userId = profile.userId)
        }
        
        composable<Settings> { backStackEntry ->
            val settings: Settings = backStackEntry.toRoute()
            SettingsScreen(section = settings.section)
        }
    }
}

Navigation Patterns

Basic Navigation
kotlin
// Navigate forward
navController.navigate(Profile(userId = "user123"))

// Navigate and pop current screen
navController.navigate(Home) {
    popUpTo<Home> { inclusive = true }
}

// Navigate back
navController.popBackStack()

// Navigate back to specific destination
navController.popBackStack<Home>(inclusive = false)
Navigate with Options
kotlin
navController.navigate(Profile(userId = "user123")) {
    // Pop up to destination (clear back stack)
    popUpTo<Home> {
        inclusive = false  // Keep Home in stack
        saveState = true   // Save state of popped screens
    }
    
    // Avoid multiple copies of same destination
    launchSingleTop = true
    
    // Restore state when navigating to this destination
    restoreState = true
}
Bottom Navigation Pattern
kotlin
@Composable
fun MainScreen() {
    val navController = rememberNavController()
    
    Scaffold(
        bottomBar = {
            NavigationBar {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentDestination = navBackStackEntry?.destination
                
                NavigationBarItem(
                    icon = { Icon(Icons.Default.Home, contentDescription = "Home") },
                    label = { Text("Home") },
                    selected = currentDestination?.hasRoute<Home>() == true,
                    onClick = {
                        navController.navigate(Home) {
                            popUpTo(navController.graph.findStartDestination().id) {
                                saveState = true
                            }
                            launchSingleTop = true
                            restoreState = true
                        }
                    }
                )
                // Add more items...
            }
        }
    ) { innerPadding ->
        AppNavHost(
            navController = navController,
            modifier = Modifier.padding(innerPadding)
        )
    }
}

Argument Handling

Retrieve Arguments in Composable
kotlin
composable<Profile> { backStackEntry ->
    val profile: Profile = backStackEntry.toRoute()
    ProfileScreen(userId = profile.userId)
}
Retrieve Arguments in ViewModel
kotlin
@HiltViewModel
class ProfileViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val userRepository: UserRepository
) : ViewModel() {
    
    private val profile: Profile = savedStateHandle.toRoute<Profile>()
    
    val user: StateFlow<User?> = userRepository
        .getUser(profile.userId)
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)
}
Complex Data: Pass IDs, Not Objects
kotlin
// CORRECT: Pass only the ID
navController.navigate(Profile(userId = "user123"))

// In ViewModel, fetch from repository
class ProfileViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
    private val profile = savedStateHandle.toRoute<Profile>()
    val user = userRepository.getUser(profile.userId)
}

// INCORRECT: Don't pass complex objects
// navController.navigate(Profile(user = complexUserObject)) // BAD!

kotlin
@Serializable
data class Profile(val userId: String)

composable<Profile>(
    deepLinks = listOf(
        navDeepLink<Profile>(basePath = "https://example.com/profile")
    )
) { backStackEntry ->
    val profile: Profile = backStackEntry.toRoute()
    ProfileScreen(userId = profile.userId)
}
Manifest Configuration
xml
<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="https" android:host="example.com" />
    </intent-filter>
</activity>
Create PendingIntent for Notifications
kotlin
val context = LocalContext.current
val deepLinkIntent = Intent(
    Intent.ACTION_VIEW,
    "https://example.com/profile/user123".toUri(),
    context,
    MainActivity::class.java
)

val pendingIntent = TaskStackBuilder.create(context).run {
    addNextIntentWithParentStack(deepLinkIntent)
    getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}

Nested Navigation

Create Nested Graph
kotlin
NavHost(navController = navController, startDestination = Home) {
    composable<Home> { HomeScreen() }
    
    // Nested graph for authentication flow
    navigation<AuthGraph>(startDestination = Login) {
        composable<Login> {
            LoginScreen(
                onLoginSuccess = {
                    navController.navigate(Home) {
                        popUpTo<AuthGraph> { inclusive = true }
                    }
                }
            )
        }
        composable<Register> { RegisterScreen() }
        composable<ForgotPassword> { ForgotPasswordScreen() }
    }
}

// Route definitions
@Serializable object AuthGraph
@Serializable object Login
@Serializable object Register
@Serializable object ForgotPassword

Adaptive Navigation

Use NavigationSuiteScaffold for responsive navigation (bottom bar on phones, rail on tablets):

kotlin
@Composable
fun AdaptiveApp() {
    val navController = rememberNavController()
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentDestination = navBackStackEntry?.destination
    
    NavigationSuiteScaffold(
        navigationSuiteItems = {
            item(
                icon = { Icon(Icons.Default.Home, contentDescription = "Home") },
                label = { Text("Home") },
                selected = currentDestination?.hasRoute<Home>() == true,
                onClick = { navController.navigate(Home) }
            )
            item(
                icon = { Icon(Icons.Default.Settings, contentDescription = "Settings") },
                label = { Text("Settings") },
                selected = currentDestination?.hasRoute<Settings>() == true,
                onClick = { navController.navigate(Settings()) }
            )
        }
    ) {
        AppNavHost(navController = navController)
    }
}

Testing

Setup
kotlin
// build.gradle.kts
androidTestImplementation("androidx.navigation:navigation-testing:2.8.5")
Test Navigation
kotlin
class NavigationTest {
    @get:Rule
    val composeTestRule = createComposeRule()
    
    private lateinit var navController: TestNavHostController
    
    @Before
    fun setup() {
        composeTestRule.setContent {
            navController = TestNavHostController(LocalContext.current)
            navController.navigatorProvider.addNavigator(ComposeNavigator())
            AppNavHost(navController = navController)
        }
    }
    
    @Test
    fun verifyStartDestination() {
        composeTestRule
            .onNodeWithText("Welcome")
            .assertIsDisplayed()
    }
    
    @Test
    fun navigateToProfile_displaysProfileScreen() {
        composeTestRule
            .onNodeWithText("View Profile")
            .performClick()
        
        assertTrue(
            navController.currentBackStackEntry?.destination?.hasRoute<Profile>() == true
        )
    }
}

Critical Rules

DO
  • Use @Serializable routes for type safety
  • Pass only IDs/primitives as arguments
  • Use popUpTo with launchSingleTop for bottom navigation
  • Extract NavHost to a separate composable for testability
  • Use SavedStateHandle.toRoute<T>() in ViewModels
DON'T
  • Pass complex objects as navigation arguments
  • Create NavController inside NavHost
  • Navigate in LaunchedEffect without proper keys
  • Forget FLAG_IMMUTABLE for PendingIntents (Android 12+)
  • Use string-based routes (legacy pattern)

References

© Moustachauve, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .github/skills/compose-navigation of Moustachauve/WLED-Android.

Open the folder on GitHubat commit 7e164a8

Used in 1 other repository

We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in Moustachauve/WLED-Android, which our catalogue first saw on October 7, 2026.

Compare with similar skills

Compose Navigation next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Compose Navigation compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Compose Navigation this skillMoustachauve/WLED-Android1691 repos~2.7kAutomated safety check: PassApache-2.0
Compose Multiplatform Patternsmonta-app/ocpp-emulator1805 repos~2kAutomated safety check: PassApache-2.0
Stylesarindamxd/camerax-android1324 repos~2.3kAutomated safety check: PassApache-2.0
Compose Animationschrisbanes/skills1.1k—~1.1kAutomated safety check: PassApache-2.0
Edge To Edgearindamxd/camerax-android1325 repos~3.6kAutomated safety check: PassApache-2.0
Compose UI Testing Patternschrisbanes/skills1.1k—~1.8kAutomated safety check: PassApache-2.0

Similar skills

  • Compose Multiplatform Patterns

    monta-app/ocpp-emulator

    Compose Multiplatform and Jetpack Compose patterns for KMP projects — state management, navigation, theming, performance, and platform-specific UI.

    180 GitHub starsUsed in 5 repos~2k tokens
    MobileAuto-check passed
  • Styles

    arindamxd/camerax-android

    A skill your agent uses to integrate the Jetpack Compose Styles API into an Android project.

    132 GitHub starsUsed in 4 repos~2.3k tokens
    MobileAuto-check passed
  • Compose Animations

    chrisbanes/skills

    A skill your agent uses when writing or reviewing Jetpack Compose motion: visibility enter/exit, animating one property toward a target, color or size transitions, multiple properties from one…

    1.1k GitHub stars~1.1k tokensUpdated 4 days ago
    MobileAuto-check passed
  • Edge To Edge

    arindamxd/camerax-android

    A skill your agent uses to migrate your Jetpack Compose app to add adaptive edge-to-edge support and troubleshoot common issues.

    132 GitHub starsUsed in 5 repos~3.6k tokens
    MobileAuto-check passed
  • A skill your agent uses when writing or reviewing Jetpack Compose UI tests, screenshot tests or baseline-recording evidence, previews, semantics assertions, fake image loading, keyboard input, focus…

    1.1k GitHub stars~1.8k tokensUpdated 4 days ago
    MobileAuto-check passed
  • Navigation3

    new-silvermoon/awesome-android-agent-skills

    Implement navigation in Jetpack Compose using Navigation 3. An agent skill from new-silvermoon/awesome-android-agent-skills.

    972 GitHub stars~1.9k tokensUpdated 2 mo ago
    MobileAuto-check passed

More from Moustachauve/WLED-Android

All 17 skills in this repo
  • Compose Performance Audit

    Moustachauve/WLED-Android

    Audit and improve Jetpack Compose runtime performance from code review and architecture.

    169 GitHub starsUsed in 3 repos~1.7k tokens
    Auto-check passed
  • Compose UI

    Moustachauve/WLED-Android

    Best practices for building UI with Jetpack Compose, focusing on state hoisting, detailed performance optimizations, and theming.

    169 GitHub starsUsed in 3 repos~676 tokens
    Auto-check passed
  • Gradle Build Performance

    Moustachauve/WLED-Android

    Debug and optimize Android/Gradle build performance. An agent skill from Moustachauve/WLED-Android.

    169 GitHub starsUsed in 3 repos~2k tokens
    Auto-check passed
  • Kotlin Concurrency Expert

    Moustachauve/WLED-Android

    Kotlin Coroutines review and remediation for Android. An agent skill from Moustachauve/WLED-Android.

    169 GitHub starsUsed in 3 repos~1.4k tokens
    Auto-check passed
  • Coil Compose

    Moustachauve/WLED-Android

    Expert guidance on using Coil for image loading in Jetpack Compose.

    169 GitHub starsUsed in 2 repos~789 tokens
    Auto-check passed
  • XML To Compose Migration

    Moustachauve/WLED-Android

    Convert Android XML layouts to Jetpack Compose. An agent skill from Moustachauve/WLED-Android.

    169 GitHub starsUsed in 2 repos~2.6k tokens
    Auto-check passed

Works with

Categories

Questions about Compose Navigation

What does Compose Navigation do?

Implement navigation in Jetpack Compose using Navigation Compose. Compose Navigation is an agent skill from Moustachauve/WLED-Android. Implement navigation in Jetpack Compose using Navigation Compose.

When should I use Compose Navigation?

Compose Navigation fits situations like: asked to set up navigation; pass arguments between screens; handle deep links; structure multi-screen apps.

How do I install Compose Navigation in Claude Code?

Run `npx skills add Moustachauve/WLED-Android --skill compose-navigation -a claude-code`. Or copy the skill folder (.github/skills/compose-navigation in Moustachauve/WLED-Android) into .claude/skills/compose-navigation in your project. Claude Code loads it when a task matches its description.

How do I install Compose Navigation in Codex?

Run `npx skills add Moustachauve/WLED-Android --skill compose-navigation -a codex`. Or copy the skill folder (.github/skills/compose-navigation in Moustachauve/WLED-Android) into .agents/skills/compose-navigation in your project. Codex loads it when a task matches its description.

Can I use Compose Navigation in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Moustachauve/WLED-Android --skill compose-navigation -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/compose-navigation, .gemini/skills/compose-navigation, .github/skills/compose-navigation and .opencode/skills/compose-navigation in your project.

What does Compose Navigation need to run?

SKILL.md names no scripts, command-line tools or credentials: Compose Navigation is instructions for the agent only.

Does Compose Navigation access the network?

SKILL.md names 1 domain. As links in the text: developer.android.com. This is read from the text; nothing was executed.

Is Compose Navigation safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Compose Navigation use?

Compose Navigation is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Compose Navigation use?

About 2.7k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Compose Navigation?

Skills that share tags, products or a category with Compose Navigation: Compose Multiplatform Patterns (monta-app/ocpp-emulator, 180 stars), Styles (arindamxd/camerax-android, 132 stars), Compose Animations (chrisbanes/skills, 1.1k stars) and Edge To Edge (arindamxd/camerax-android, 132 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Compose Navigation?

Moustachauve (a GitHub user) maintains it in Moustachauve/WLED-Android, which has 169 GitHub stars. The repository holds 17 skills in this directory. The repository was last updated on October 7, 2026.

Source: Moustachauve/WLED-Android on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.