Skip to content

DongLab-DevTools/Composable-Nametag

Repository files navigation

Composable-Nametag

Hits Platform Min SDK Maven Central GitHub stars

한국어 README

Overview

image

Composable-Nametag is a debug tool that overlays the name of every @Composable function as a label on your screen.

Without modifying any existing code, the Kotlin Compiler Plugin (KCP) automatically injects labels at compile time.
See each Composable's name directly on screen, making layout debugging and code review faster.


Screenshots

image

Features

  • Auto injection — The Compiler Plugin injects labels at compile time without touching your existing code.
  • Debug only — The compiler plugin and runtime are applied only to debug builds. Release builds contain zero library code — no IR injection, no runtime dependency.
  • Zero overhead — Works via IR transformation at compile time. In release builds, nothing is injected or included at all.
  • Noise filtering — Only PascalCase Composables get labels; lambdas, remember, property accessors, etc. are ignored.
  • Customizable skip rules — Exclude composables from labeling via package prefix, name regex, or annotation.
  • Build safe — Unsupported Kotlin versions only disable the compiler plugin — the build always succeeds.


Installation

Repository Setup

Choose one of the following depending on where the library is hosted.

Maven Central (default)

Add mavenCentral() to your plugin repositories in settings.gradle.kts:

// settings.gradle.kts
pluginManagement {
    repositories {
        gradlePluginPortal()
        mavenCentral()  // ← required
        google()
    }
}

If using Convention Plugin, also add to build-logic/settings.gradle.kts dependencyResolutionManagement.repositories.

GitHub Packages

The library is also available via GitHub Packages. Add the repository to settings.gradle.kts:

// settings.gradle.kts
pluginManagement {
    repositories {
        gradlePluginPortal()
        google()
        maven {
            url = uri("https://maven.pkg.github.com/{owner}/{repo}")
            credentials {
                username = providers.gradleProperty("gpr.user").orNull ?: System.getenv("GITHUB_ACTOR")
                password = providers.gradleProperty("gpr.token").orNull ?: System.getenv("GITHUB_TOKEN")
            }
        }
    }
}

If using Convention Plugin, also add the same maven { ... } block to build-logic/settings.gradle.kts dependencyResolutionManagement.repositories.

Set credentials in ~/.gradle/gradle.properties:

gpr.user=your-github-username
gpr.token=ghp_xxxxxxxxxxxxxxxxxxxx  # read:packages scope required


Option A. plugins {} block (standard)

Apply the plugin in each Compose module's build.gradle.kts. It must be declared before the Compose plugin.

// feature/home/build.gradle.kts (Compose module)
plugins {
    id("{group-id}") version "{library-version}" // Must be before the Compose plugin
    id("org.jetbrains.kotlin.plugin.compose") version "2.1.21"
    // ...
}

Note

No additional implementation dependency is needed — the plugin adds the runtime library automatically.

The {group-id} is the GROUP configured during publishing (e.g., io.github.dongx0915.composable.nametag for Maven Central).



Option B. Convention Plugin

For projects using a Convention Plugin structure (e.g., build-logic):


Step 1. Add the plugin artifact to your build-logic/convention/build.gradle.kts:

dependencies {
    implementation("{group-id}:composable-nametag-gradle:{library-version}")
}

Step 2. Apply it inside your Compose Convention Plugin, before the Compose plugin:

// e.g., AndroidComposeConventionPlugin.kt
class AndroidComposeConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            pluginManager.apply("{group-id}") // Must be before the Compose plugin
            pluginManager.apply("org.jetbrains.kotlin.plugin.compose")
            // ...
        }
    }
}


Requirements

  • Android API 24 (Android 7.0) or higher
  • Kotlin 2.1.21 ~ 2.3.20 (see Supported Versions)
  • Jetpack Compose (BOM 2025.05.01 or compatible)
  • JDK 17+


Usage

Enable the overlay

// Application class or wherever you want to toggle
ComposeDebugConfig.enabled = true

That's it. All @Composable function names will appear as labels on screen.



How It Works

How Composable-Nametag Works


Filtering Rules

Condition Behavior
PascalCase @Composable Label shown
camelCase (remember, modifier, etc.) Skipped
Lambda / anonymous Skipped
Property accessor Skipped
__ prefix Skipped


Custom Skip Rules

In addition to the built-in filters, you can exclude additional composables from labeling via the composableNametag { } DSL.

Options

Property Type Description
skipPackages List<String> Package FQN prefixes. Functions whose file package matches (exact or sub-package) are skipped.
skipNamePatterns List<String> Java regex patterns. Functions whose simple name fully matches any pattern are skipped.
skipAnnotations List<String> Fully-qualified annotation class names. Functions annotated with any of these are skipped.

All rules are OR-combined with the built-in rules — if any rule matches, the label is not injected.

Per-module

// feature/home/build.gradle.kts
composableNametag {
    skipPackages.addAll(
        "com.myapp.internal",
        "com.myapp.designsystem.foundation",
    )
    skipNamePatterns.addAll(
        ".*Preview$",   // skip `XxxPreview`
        "^Themed.*",    // skip `ThemedXxx`
    )
}

For skipAnnotations, pass the fully-qualified name of any annotation defined in your project (e.g. "com.myapp.debug.MyInternalMarker"). Composables marked with that annotation will be skipped.

Global (Convention Plugin)

Configure once in your convention plugin to apply across all Compose modules:

// AndroidComposeConventionPlugin.kt
import com.donglab.compose.debug.gradle.ComposableNametagExtension

pluginManager.apply("{group-id}")
pluginManager.apply("org.jetbrains.kotlin.plugin.compose")

extensions.configure<ComposableNametagExtension> {
    skipNamePatterns.add(".*Preview$")
}

Individual modules can still add their own rules on top — ListProperty.add/addAll accumulates.

Note

All filtering happens at compile time, so there's zero runtime cost regardless of how many rules you add.



Kotlin Version Compatibility

The compiler plugin uses Kotlin IR internal APIs, so it is published per Kotlin version. The Gradle plugin auto-detects your Kotlin version and resolves the matching compiler artifact.

Kotlin Version Supported
2.1.21
2.2.0
2.2.10
2.2.20
2.2.21
2.3.0
2.3.10
2.3.20
  • Unsupported versions: Logs a warning once and disables only the compiler plugin. The build proceeds normally.
⚠️  compose-debug-overlay: Kotlin X.Y.Z is not supported.
    → Your build and app are NOT affected.


Release Safety

Composable-Nametag is completely excluded from release builds:

Debug Build Release Build
Compiler Plugin (IR injection) Active Not applied
Runtime Library (APK) Included Not included
  • The Gradle plugin uses debugImplementation — the runtime library is not packaged into release APKs.
  • The compiler plugin's isApplicable returns false for non-debug compilations — no code is injected into release builds.
  • Result: Release APK contains zero traces of this library. No performance impact, no binary size increase.


Tech Stack

  • Kotlin 2.1.21 ~ 2.3.20
  • AGP 8.6.1
  • Compose BOM 2025.05.01
  • Gradle 8.7


License

Apache License 2.0

About

A Kotlin compiler plugin that displays composable function names on screen for debugging

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages