README.md

Android UI View-Tree Analyzer

A suite of two Claude Code custom agents that statically and semantically analyze Android app projects to extract complete, hierarchical UI information as view trees. Designed for downstream HarmonyOS ArkTS UI generation.

Two specialized agents handle different Android UI paradigms:

Agent Target UI Invocation
android-activity-ui-tree-analyzer Traditional XML layouts (Activity + Layout XML) @android-activity-ui-tree-analyzer <project> [output]
android-compose-ui-tree-analyzer Jetpack Compose UI (Composable screens + NavHost) @android-compose-ui-tree-analyzer <project> [output]

Both agents combine Python scripts for deterministic parsing + Claude for semantic code understanding + optional runtime capture via adb to achieve ~95%+ UI information coverage.


Agent 1: android-activity-ui-tree-analyzer

Analyzes Android apps built with traditional XML layouts. Discovers every Activity with 100% recall, parses layout XML into proper nested trees, analyzes source code for click handlers/menus/dialogs/fragments, merges everything into per-Activity JSON files, and runs automated verification.

Quick Start

@android-activity-ui-tree-analyzer /path/to/android/project [/path/to/output]
  • Project Path: root directory of the Android project (must contain app/src/main/AndroidManifest.xml)
  • Output Directory: where all output files are written (default: <project>/UI_Analysis)

Architecture

                    Android Project Source
                           |
          +----------------+----------------+
          v                v                v
   AndroidManifest.xml  res/layout/*.xml  *.kt / *.java
          |                |                |
    Phase 1:          Phase 2:         Phase 3:
    Activity          XML -> Tree      Source Code
    Discovery         Parser           Analyzer
          |                |                |
          |                |          Phase 3b:
          |                |          Claude Deep
          |                |          Semantic       <-- MANDATORY
          |                |          Analysis
          |                |                |
          |          Phase 3.5:             |
          |          Runtime UI       (optional)
          |          Dump
          |                |                |
          +--------+-------+--------+------+
                   v                
             Phase 4: Merge         
                   v                
             Phase 5: Verify        
                   v
          Final per-Activity JSON
          + UI_Design.md
          + verification_report.md

Pipeline Phases

Phase Script Output Description
1 discover_activities.py discovery.json Parse AndroidManifest.xml, scan source dirs (incl. build flavors, includeBuild libraries), cross-reference manifest vs. source
2 parse_layout_xml.py layout_trees/*.json, resolved_resources.json Parse layout XML into hierarchical trees; resolve <include>/<merge>, resource references (@string/, @color/, @dimen/)
3 analyze_source.py source_analyses/*.json, component_maps.json Regex-based extraction: layout binding, click handlers, menus, dialogs, fragments, dynamic views; global adapter/fragment/dialog scanning
3b Claude deep analysis Updated source_analyses/*.json MANDATORY. Trace inheritance chains, extension functions, adapter callbacks, menu handlers, dialog triggers to reach ~95%+ coverage
3.5 runtime_dump.py runtime_dumps/*.xml Optional. Capture runtime view hierarchy via adb shell uiautomator dump
4 merge_ui_tree.py pages/*.json, UI_Design.md Merge all sources; inline adapter item layouts, fragment layouts, dialog layouts, runtime data
5 verify_output.py verification_report.md Automated quality checks: Activity recall, view completeness, resource resolution, tree integrity

Phase 3b — Deep Semantic Analysis Detail

Claude reads source code across the full inheritance chain for every Activity:

Step What Why
Trace inheritance chain Read Activity -> SimpleActivity -> BaseSimpleActivity Catch inherited click handlers and menu handlers
Scan extension functions Search for fun SimpleActivity.launchXxx() Catch navigation methods defined in extension files
Trace adapter callbacks Follow DirectoryAdapter(itemClick = { ... }) to final startActivity() Catch indirect item click navigation
Trace menu handlers Follow R.id.settings -> launchSettings() -> startActivity() Catch menu-triggered navigation
Trace dialog triggers Find which view click opens which dialog, and what dialog buttons do Map dialog lifecycle to UI components

Output Format

Each Activity produces a JSON file in pages/:

{
  "page_name": "MainActivity",
  "activity_class": "com.example.app.activities.MainActivity",
  "source_file": "app/src/main/kotlin/.../MainActivity.kt",
  "layout_file": "activity_main.xml",
  "description": "...",
  "window": { "theme": "...", "screen_orientation": "...", "exported": true },
  "view_tree": {
    "type": "CoordinatorLayout",
    "id": "main_coordinator",
    "third_party": false,
    "attributes": { "android:layout_width": "match_parent" },
    "children": [
      {
        "type": "RecyclerView",
        "id": "items_grid",
        "children": [],
        "actions": [
          { "event": "onItemClick", "navigates_to": "MediaActivity" }
        ],
        "adapter_items": [
          {
            "adapter": "DirectoryAdapter",
            "layout_file": "directory_item_grid.xml",
            "view_tree": { "type": "RelativeLayout", "children": [ "..." ] }
          }
        ]
      }
    ]
  },
  "menus": [ { "menu_file": "menu_main", "items": [ "..." ] } ],
  "dialogs": [ { "dialog_class": "ChangeSortingDialog", "view_tree": { "..." : "..." } } ],
  "fragments": [ { "fragment_class": "PhotoFragment", "view_tree": { "..." : "..." } } ],
  "dynamic_elements": []
}

Key properties:

  • view_tree — single root node with nested children[], preserving exact XML hierarchy
  • adapter_items — on RecyclerView nodes, contains parsed item layout trees
  • fragments[].view_tree / dialogs[].view_tree — inlined full hierarchies
  • actions[] — click handlers with navigation targets, attached to the correct tree node
  • runtime_bounds, _runtime_only — present when runtime capture is available

Verification Criteria

Check Pass Criteria
Activity Recall 100% — every manifest activity has a JSON
View Completeness ID coverage >= 95% per Activity
Resource Resolution >= 95% references resolved
Tree Integrity No structural issues
Layout Binding Activities correctly mapped to layouts

Iron Rules

  1. 100% Activity Recall — Every <activity> in AndroidManifest.xml must have a corresponding JSON output
  2. True Hierarchical Treeview_tree preserves exact parent-child nesting from layout XML
  3. Complete Attribute Capture — Every XML attribute on every view must appear
  4. Resolved Resource Values@string/app_name -> "Simple Gallery", @color/primary -> "#F57C00"
  5. Include Resolution<include> replaced with actual layout tree; <merge> children lifted
  6. Third-Party Flagging — Non-Android/AndroidX views marked "third_party": true
  7. Deep Semantic Analysis is MANDATORY — Phase 3b must execute for EVERY Activity
  8. No Fabrication — Only output what exists in source code
Activity Recall:           100%  (20/20 manifest + 6 extras)
View Tree Nodes:           347   (static XML)
Adapter Item Nodes:        115   (6 adapters, 13 item layouts)
Fragment Layout Nodes:      30   (PhotoFragment + VideoFragment)
Dialog Layout Nodes:       536   (56 dialog classes)
Runtime Enrichments:        50   (3 Activities captured)
Click Handler Coverage:    ~95%  (with Phase 3b deep analysis)
-----------------------------------------------
Total UI Nodes:           1078   (3x improvement over static-only)

Agent 2: android-compose-ui-tree-analyzer

Analyzes Android apps built with Jetpack Compose. Discovers every Activity and Compose navigation screen with 100% recall, parses @Composable functions into nested component trees, analyzes source code for navigation/state/events, merges everything into per-screen JSON files, and runs automated verification.

Quick Start

@android-compose-ui-tree-analyzer /path/to/android/project [/path/to/output]
  • Project Path: root directory of the Android project (must contain app/src/main/AndroidManifest.xml)
  • Output Directory: where all output files are written (default: <project>/Compose_UI_Analysis)

Prerequisites

pip3 install tree-sitter tree-sitter-kotlin

Architecture

                    Android Project Source (Compose)
                           |
     +----------+----------+----------+-----------+
     v          v          v          v           v
  Manifest  ScreenRoute  ComposeNav  *.kt        res/values/
     |          |          |          |           |
  Phase 1:  Discover all screens, routes, registrations,
            shell components (dynamic detection)
     |
  Phase 1.5: ViewModel analysis + Theme token extraction
     |
  Phase 2: tree-sitter AST -> compose_trees/*.json
            (Modifier parsing, content_params, custom expansion)
     |
  Phase 2b: Legacy XML layouts (xml-based Activities only)
     |
  Phase 3a: Automated source analysis (regex: ViewModel, nav, dialogs)
     |
  Phase 3b: Claude deep semantic analysis (MANDATORY)
     |
  Phase 3.5: Runtime UI capture (optional)
     |
  Phase 4: Merge -> pages/*.json + navigation_graph.json + UI_Design.md
     |
  Phase 5: Verify -> verification_report.md (11 checks)

Pipeline Phases

Phase Script Output Description
1 discover_all_screens.py discovery.json Activities from manifest, route constants from ScreenRoute.kt, composable registrations from ComposeNavigation.kt, shell components from setContent {}
1.5 analyze_viewmodels.py viewmodels/*.json StateFlow/LiveData properties, sealed UiState definitions, public method signatures
1.5b extract_theme_tokens.py theme_tokens.json SaltTheme color/textStyle/dimension token catalog
2 parse_compose_tree_v2.py compose_trees/*.json tree-sitter AST parsing: structured Modifier, content_params, conditional blocks, custom composable one-level expansion, R.string resolution
2b parse_layout_xml.py layout_trees/*.json Legacy XML layouts only (for Activities with ui_type: "xml")
3a analyze_compose_source.py source_analyses/*.json Automated: ViewModel bindings, state collection, navigation targets, dialog state, LaunchedEffect, sealed UiState variants
3b Claude deep analysis Updated source_analyses/*.json MANDATORY. Complex navigation in nested lambdas, custom composable resolution, ViewModel method effects, cross-file navigation chains
3.5 Runtime capture runtime_dumps/ Optional. Compose semantics tree dump, Layout Inspector, or UIAutomator
4 merge_compose_output.py pages/*.json, navigation_graph.json, UI_Design.md Merge all sources into final per-page JSON with navigation graph
5 verify_compose_output.py verification_report.md 11 automated checks including semantic validation

Phase 2 — tree-sitter AST Parsing Detail

Uses tree-sitter-kotlin for proper AST parsing (not regex+brace-depth). Handles:

  • Chained call patternFoo(params) { content } correctly parsed
  • Structured Modifier parsing.fillMaxSize().padding(16.dp) -> structured array
  • Content parameter lambdastitleContent = { ... }, sheetContent = { ... } parsed into content_params
  • Transparent containersCompositionLocalProvider { ... } penetrated for content
  • Control flow preservationif/when/else as ConditionalBlock/WhenBlock nodes
  • R.string resolutionstringResource(R.string.xxx) resolved from res/values/strings.xml
  • Custom composable expansion — one-level auto-expansion with expanded_children[]

Phase 3b — Deep Semantic Analysis Detail

Claude fills remaining ~15% gaps that automated Phase 3a cannot capture:

Step What
Read screen source Identify wrapper, ViewModel access, state collection, CompositionLocal usage
Trace navigation Every navController.navigate() and startActivity() traced to trigger component
Resolve custom composables Find @Composable definition, build sub-tree, record children
Analyze event handlers Trace onClick lambdas to final effect (ViewModel method, dialog, state toggle)

Output Format

Compose Screens (NavHost routes)

{
  "page_name": "SettingsScreen",
  "page_type": "compose_screen",
  "route": "SETTINGS",
  "route_pattern": "settings",
  "route_arguments": [],
  "parent_activity": "MainActivity",
  "source_file": "app/src/main/.../SettingsScreen.kt",
  "view_model": "SettingsViewModel",
  "compose_tree": [
    {
      "type": "BasicScreenColumn",
      "salt_semantic": "screen_wrapper_scrollable",
      "library": "salt_ui",
      "arkts_hint": "Navigation + Scroll + Column",
      "children": [
        {
          "type": "Item",
          "salt_semantic": "list_item",
          "clickable": true,
          "arkts_hint": "ListItem with onClick",
          "params": { "text": "Salt Player Pro" },
          "actions": [
            { "event": "onClick", "navigates_to": "SALT_PLAYER_PRO" }
          ]
        }
      ]
    }
  ],
  "navigation_targets": ["SALT_PLAYER_PRO", "USER_INTERFACE"],
  "dialogs": [],
  "state_description": "Settings hub with grouped navigation items"
}

Activities

{
  "page_name": "MainActivity",
  "page_type": "activity",
  "is_activity": true,
  "activity_class": "com.salt.music.ui.MainActivity",
  "ui_type": "compose",
  "window": { "theme": "...", "exported": true, "launch_mode": "singleTask" },
  "compose_entry": "MainActivityUI",
  "compose_tree": [ "..." ]
}

Shell Components

{
  "page_name": "PlayerScreen",
  "page_type": "shell_component",
  "shell_role": "full_player_overlay",
  "source_file": "app/src/main/.../PlayerScreen.kt",
  "compose_tree": [ "..." ]
}

Key properties:

  • compose_tree — list of root nodes with nested children[], a true hierarchical tree
  • salt_semantic — maps Salt UI components to semantic UI types
  • arkts_hint — suggests equivalent HarmonyOS ArkUI component
  • custom: true — flags app-specific composables
  • ConditionalBlock/WhenBlock — conditional UI rendering preserved
  • content_params — named content lambdas (e.g., sheetContent, titleContent)

Salt UI Component Mapping

Salt UI Semantic Type ArkTS Hint
BasicScreenColumn screen_wrapper_scrollable Navigation + Scroll + Column
BasicScreenBox screen_wrapper_box Navigation + Stack
RoundedColumn grouped_container Column with borderRadius
Item list_item (clickable) ListItem with onClick
ItemSwitcher toggle_item ListItem with Toggle
ItemCheck checkbox_item ListItem with Checkbox
ItemSlider slider_item ListItem with Slider
ItemTitle section_title Text with section styling
YesDialog confirm_dialog AlertDialog (confirm)
YesNoDialog confirm_cancel_dialog AlertDialog (confirm/cancel)
BottomSheetScaffold bottom_sheet_scaffold Sheet + Stack

Verification Criteria

Check Type Pass Criteria
Activity Recall Critical 100% — every manifest activity has output
Route Constant Recall Critical 100% — every ScreenRoute constant in discovery
Composable Registration Coverage Critical 100% — every composable() has output
Tree Integrity Critical No structural issues
Shell Completeness Critical All shell components have output
Navigation Target Validity Advisory Some dynamic routes acceptable
Custom Composable Resolution Advisory Simple wrappers acceptable unresolved
Clickable Action Completeness Advisory Every clickable should have handler info
ViewModel Source Analysis Advisory Screens with ViewModel should have state info
String Resource Resolution Advisory Tracks R.string resolution rate
Phase 3a Coverage Advisory Summary of automated analysis coverage

Iron Rules

  1. 100% Activity Recall — Every <activity> in AndroidManifest.xml must have output
  2. 100% Route Recall — Every const val in ScreenRoute.kt must be in discovery
  3. 100% Composable Registration Coverage — Every composable() in ComposeNavigation.kt must have output
  4. True Hierarchical Treecompose_tree preserves Compose component nesting
  5. Salt UI Semantic Mapping — All Salt UI components must have salt_semantic and arkts_hint
  6. Custom Composable Flagging — Non-standard composables marked "custom": true
  7. Conditional UI Preservationif/when blocks preserved as ConditionalBlock/WhenBlock nodes
  8. Deep Semantic Analysis is MANDATORY — Phase 3a (automated) + Phase 3b (Claude) for every screen
  9. No Fabrication — Only output what exists in source code

Shared Infrastructure

Scripts

scripts/
├── discover_activities.py        # Phase 1 (Activity agent): Activity discovery
├── discover_all_screens.py       # Phase 1 (Compose agent): Activity + route + registration discovery
├── parse_layout_xml.py           # Phase 2: XML -> hierarchical tree (shared)
├── parse_compose_tree.py         # Phase 2 (Compose, v1): regex+brace-depth parser (legacy)
├── parse_compose_tree_v2.py      # Phase 2 (Compose, v2): tree-sitter AST parser
├── salt_ui_mapping.py            # Salt UI -> semantic type + ArkTS hint mapping
├── analyze_source.py             # Phase 3 (Activity agent): regex-based source analysis
├── analyze_compose_source.py     # Phase 3a (Compose agent): automated source analysis
├── analyze_viewmodels.py         # Phase 1.5 (Compose agent): ViewModel property extraction
├── extract_theme_tokens.py       # Phase 1.5b (Compose agent): SaltTheme token catalog
├── merge_ui_tree.py              # Phase 4 (Activity agent): merge all sources
├── merge_compose_output.py       # Phase 4 (Compose agent): merge all sources
├── verify_output.py              # Phase 5 (Activity agent): automated verification
└── verify_compose_output.py      # Phase 5 (Compose agent): automated verification (11 checks)

Requirements

  • Python 3.6+ — for running analysis scripts
  • tree-sitter + tree-sitter-kotlin — required for Compose agent Phase 2
  • Android project source — with app/src/main/AndroidManifest.xml
  • Claude Code — for Phase 3b deep semantic analysis
  • adb + device/emulator (optional) — for runtime capture

Choosing the Right Agent

Your Android Project Uses Use This Agent
XML layouts (res/layout/*.xml) with Activities/Fragments android-activity-ui-tree-analyzer
Jetpack Compose with NavHost routing android-compose-ui-tree-analyzer
Mixed (some Activities use XML, some use Compose) Run both agents; Compose agent handles XML Activities via Phase 2b

Coverage Summary

Dimension Activity Agent Compose Agent
Activity discovery 100% 100%
Route/registration discovery N/A 100%
XML layout hierarchy 100% Legacy only
Compose component tree N/A 100% (tree-sitter)
Resource resolution 99.8% R.string resolved
RecyclerView/adapter items 100% N/A (Compose uses LazyColumn)
Fragment layouts 100% N/A
Dialog layouts ~53% Via source analysis
Click handlers / navigation ~95%+ ~95%+
ViewModel state N/A Full (sealed UiState)
Salt UI semantic mapping N/A Full
Runtime capture Optional (uiautomator) Optional (semantics/uiautomator)

Known Limitations

  1. Theme/Style attribute expansion@style/MyStyle not expanded (Activity agent)
  2. Conditional UI visibility — Static analysis captures all views but cannot determine runtime visibility state
  3. Custom View internals — Only available via runtime capture (Activity agent)
  4. Purely programmatic views — Views created entirely in code have limited accuracy
  5. Dynamic Compose content — Content generated from runtime data (API responses) captured structurally but not with actual values