Skip to content

Commit 40ec356

Browse files
committed
Add official Android agent skills for project-local use
Install the full Android CLI skill pack under project `.claude/skills` and `skills/` (claude-code + openclaw), refreshing the existing adaptive, navigation-3, and XML-to-Compose skills so agents share the same local set.
1 parent 8afaeef commit 40ec356

334 files changed

Lines changed: 115618 additions & 72 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/adaptive/SKILL.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ description: Instructions to make or update an app's UI so that it adapts to dif
1010
license: Complete terms in LICENSE.txt
1111
metadata:
1212
author: Google LLC
13-
last-updated: '2026-05-20'
13+
last-updated: '2026-07-02'
1414
keywords:
1515
- android
1616
- ui
@@ -75,11 +75,11 @@ phone in portrait mode. On larger screen hand-held devices, like tablets and
7575
unfolded foldables, the navigation area must be accessible from the edge of the
7676
screen (navigation rail).
7777

78-
If you need to provide more screen real state for the content, hide the
78+
If you need to provide more screen space for the content, hide the
7979
navigation area. Examples of this include:
8080

8181
- Hiding the navigation bar when the user scrolls down and showing it again when the user scrolls up. The assumption is that when the user is scrolling down, they are consuming content but when scrolling up they are trying to navigate away from that content.
82-
- Hiding the navigation area when its content is distracting. For example, in camera previews or when the content is best displayed in full screen (such as a single photo screen).
82+
- Hiding the navigation area when its content is distracting. For example, in camera previews or when displaying a full-screen photo.
8383

8484
When the detail screen is displayed full-screen on mobile, full-screen mode must
8585
be deactivated on larger screens.
@@ -101,7 +101,7 @@ parameter.
101101

102102
Steps to migrate:
103103

104-
- Identify the scenarios under which the navigation bar is hidden. This is usually done with a boolean variable for the visibility. It could be named something like `isNavBarVisible` or `shouldShowNavBar`.
104+
- Identify the scenarios under which the navigation bar is hidden. This is usually done with a boolean variable for the visibility. Use `isNavBarVisible` or `shouldShowNavBar` as the variable name.
105105
- Create an instance of `NavigationSuiteScaffoldState` using `rememberNavigationSuiteScaffoldState()` and pass it to `NavigationSuiteScaffold`.
106106
- When the navigation area visibility changes, use a `LaunchedEffect` to call `show` or `hide` on the `NavigationSuiteScaffoldState`.
107107

@@ -207,8 +207,8 @@ Look for the following vertical list composables: `LazyColumn`,
207207

208208
Steps to migrate:
209209

210-
- Choose a suitable minimum width in dp for the column. It should be large enough so that item is clearly visible to the user.
211-
- For `LazyColumn`: change to a `LazyVerticalGrid` and follow the instruction below
210+
- Choose a suitable minimum width in dp for the column. The item must be clearly visible to the user at this width.
211+
- For `LazyColumn`: change to a `LazyVerticalGrid` and follow the instruction later
212212
- For `LazyVerticalGrid`: change the `columns` parameter to use `GridCells.Adaptive(<width>.dp)`
213213
- For `LazyVerticalStaggeredGrid`: change the `columns` parameter to use `StaggeredGridCells.Adaptive(<width>.dp)`
214214

.claude/skills/adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/container-behavior.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ There is space, so Child 1 is placed into the line.
9595
There is `80dp` available space in the line. The gap is `8dp`. Child 2 is
9696
`40dp`. The required space is `48dp`. There is space, so the gap and Child 2
9797
are placed into the line.
98-
![First item placed in the FlexBox container.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/flexbox/algorithm-2.png) **Figure 2.** Second item placed in the `FlexBox` container after the first item.
98+
![Second item placed in the FlexBox container after the first item.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/flexbox/algorithm-2.png) **Figure 2.** Second item placed in the `FlexBox` container after the first item.
9999

100100
There is `32dp` available space in the line. The gap is `8dp`. Child 3 is
101101
`50dp`. The required space is `58dp`. There is not enough space in the current

.claude/skills/adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/get-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This page describes how to implement basic `FlexBox` layouts.
66
`lib.versions.toml`.
77

88
[versions]
9-
compose = "1.12.0-alpha03"
9+
compose = "1.12.0-beta02"
1010

1111
[libraries]
1212
androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout", version.ref = "compose" }

.claude/skills/adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/container-properties.md

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ You can specify the size of a grid track using one of the following methods:
112112
- **Fixed** (`Dp`): Allocates a specific size (e.g., `column(180.dp)`).
113113
- **Percentage** (`Float`): Allocates a percentage of the total available space from `0.0f` to `1.0f` (e.g., `row(0.5f)` for 50%).
114114
- **Flexible** ([`Fr`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/Fr)): Distributes remaining space proportionally after fixed and percentage tracks are calculated. For example, if two rows are set to `1.fr` and `3.fr`, the latter receives 75% of the remaining height.
115-
- **Intrinsic** : Sizes the track based on the content inside it. For more information, see [Determine grid track size intrinsically](https://developer.android.com/develop/ui/compose/layouts/adaptive/grid/container-properties#intrisic-grid-track-size).
115+
- **Intrinsic** : Sizes the track based on the content inside it. For more information, see [Determine grid track size intrinsically](https://developer.android.com/develop/ui/compose/layouts/adaptive/grid/container-properties#intrinsic-grid-track-size).
116116

117117
The following example uses the different track sizing options
118118
to define the row heights:
@@ -131,12 +131,94 @@ Grid(
131131
modifier = Modifier.height(480.dp)
132132
) {
133133
PastelRedCard("Fixed(100.dp)")
134+
PastelGreenCard("Percentage(0.2f)")
135+
PastelBlueCard("Flex(1.fr)")
136+
PastelYellowCard("Auto")
137+
138+
}
134139
```
135140

136141
<br />
137142

138143
![Row heights defined using the four primary track sizing options.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/grid/track-sizes.png) **Figure 3** . Row heights defined using the four primary track sizing options in `Grid`.
139144

145+
### Set the minimum size for flexible grid tracks
146+
147+
When a grid container has no remaining space,
148+
a standard flexible track can shrink to `0.dp`.
149+
To prevent this and ensure content isn't crushed,
150+
use [`GridTrackSize.MinMax`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/GridTrackSize#MinMax(androidx.compose.ui.unit.Dp,androidx.compose.foundation.layout.Fr))
151+
to enforce an explicit minimum size while keeping the track flexible.
152+
153+
The following example allocates at least `100.dp` to the first row:
154+
155+
156+
```kotlin
157+
Grid(
158+
config = {
159+
column(1f)
160+
// The first row has a minimum height of 100.dp and can expand to
161+
// the half of the remaining space.
162+
row(GridTrackSize.MinMax(100.dp, 1.fr))
163+
// The second row takes the half of the remaining space.
164+
row(1.fr)
165+
// The third row has a fixed height of 200.dp.
166+
row(200.dp)
167+
},
168+
modifier = Modifier.size(360.dp) // Total grid height is 360.dp
169+
) {
170+
PastelRedCard("MinMax(100.dp, 1.fr)")
171+
PastelGreenCard("Flex(1.fr)")
172+
PastelBlueCard("Fixed(200.dp)")
173+
}
174+
```
175+
176+
<br />
177+
178+
![Row heights defined using the four primary track sizing options.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/grid/track-size-minmax.png) **Figure 4** . The first row has at least `100.dp` height.
179+
180+
### Set the minimum grid track size to place lazy lists
181+
182+
Standard flexible tracks automatically query the intrinsic sizes of
183+
their children to establish a base size.
184+
However, Jetpack Compose prohibits querying the intrinsic sizes of
185+
[`SubcomposeLayout`](https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/SubcomposeLayout.composable#SubcomposeLayout(androidx.compose.ui.Modifier,kotlin.Function2)), which backs components,
186+
such as [`LazyColumn`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/LazyColumn.composable) and [`LazyRow`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/LazyRow.composable).
187+
188+
Placing a lazy list inside a standard flexible track causes
189+
an [`IllegalStateException`](https://developer.android.com/reference/java/lang/IllegalStateException) crash.
190+
To safely place lazy lists inside a flexible grid track,
191+
use `MinMax` with an explicit minimum size (such as `0.dp`)
192+
to bypass the intrinsic measurement pass.
193+
194+
195+
```kotlin
196+
Grid(
197+
config = {
198+
column(1f)
199+
// The first row's height is determined by the height of the Text composable.
200+
row(GridTrackSize.Auto)
201+
// The second row occupies the remaining space, allowing the LazyColumn to scroll.
202+
row(GridTrackSize.MinMax(0.dp, 1.fr))
203+
204+
gap(8.dp)
205+
},
206+
modifier = Modifier.size(width = 170.dp, height = 240.dp)
207+
) {
208+
Text("Lazy column in a Grid")
209+
// The LazyColumn is placed in the second row, filling the remaining space.
210+
LazyColumn(verticalArrangement = Arrangement.spacedBy(4.dp)) {
211+
items(100) { number ->
212+
PastelGreenCard("Card $number")
213+
}
214+
}
215+
}
216+
```
217+
218+
<br />
219+
220+
![Row heights defined using the four primary track sizing options.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/grid/lazy-column-in-grid.png) **Figure 5** . `LazyColumn` in a grid cell.
221+
140222
### Determine grid track size intrinsically
141223

142224
You can use [intrinsic sizing](https://developer.android.com/develop/ui/compose/layouts/intrinsic-measurements) for a `Grid`
@@ -163,14 +245,14 @@ Grid(
163245
},
164246
modifier = Modifier.width(480.dp)
165247
) {
166-
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet." )
167-
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet." )
248+
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.")
249+
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.")
168250
}
169251
```
170252

171253
<br />
172254

173-
![Intrinsic sizes specified in the columns.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/grid/intrinsic-size.png) **Figure 4**. Intrinsic sizes specified in the columns.
255+
![Intrinsic sizes specified in the columns.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/grid/intrinsic-size.png) **Figure 5**. Intrinsic sizes specified in the columns.
174256

175257
## Set gaps between rows and columns
176258

@@ -206,7 +288,7 @@ Grid(
206288

207289
<br />
208290

209-
![Gaps between rows and columns.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/grid/gaps.png) **Figure 5**. Gaps between rows and columns.
291+
![Gaps between rows and columns.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/grid/gaps.png) **Figure 6**. Gaps between rows and columns.
210292

211293
You can also use the convenience function [`gap`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/GridConfigurationScope#gap(androidx.compose.ui.unit.Dp))
212294
to define gaps of the same column and row size,

.claude/skills/adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/get-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This page describes how to implement basic [`Grid`](https://developer.android.co
66
`lib.versions.toml`.
77

88
[versions]
9-
compose = "1.12.0-alpha03"
9+
compose = "1.12.0-beta02"
1010

1111
[libraries]
1212
androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout", version.ref = "compose" }

.claude/skills/adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ of which layouts are suitable for each API:
2525

2626
| Component | Purpose |
2727
|---|---|
28-
| `LazyVerticalGrid`, `LazyStaggeredGrid`, `LazyHorizontalGrid` | Visualization of large, homogeneous data sets that requires lazy loading. |
28+
| `LazyVerticalGrid`, `LazyStaggeredGrid`, `LazyHorizontalGrid` | Visualization of large, homogeneous data sets that require lazy loading. |
2929
| `Row`, `Column`, `FlexBox` | One-dimensional layout |
3030
| `Grid` | Two-dimensional layout |
3131

.claude/skills/adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/item-properties.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ A UI element in `Grid`
137137
that has no position specification undergoes auto-placement.
138138
This example shows how you can mix auto-placed elements
139139
and the UI elements with specified grid cells.
140-
Card **#2** and card **#4** are specified grid cells,
140+
Card **#2** and Card **#4** are placed in specified grid cells,
141141
and the other items are auto-placed.
142142

143143

@@ -165,4 +165,4 @@ Grid(
165165

166166
<br />
167167

168-
![Card #3 is placed next to card <b>#1</b>, as it is an auto-placement.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/grid/autoplacement-mixed-with-placement.png) **Figure 4** . Card **#3** is placed next to card **#1**, as it is an auto-placement.
168+
![Card #3 is placed next to Card <b>#1</b>, as it is an auto-placement.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/grid/autoplacement-mixed-with-placement.png) **Figure 4** . Card **#3** is placed next to Card **#1**, as it is an auto-placement.

.claude/skills/adaptive/references/android/develop/ui/compose/tooling/debug.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Inspector](https://developer.android.com/static/develop/ui/compose/images/li-sho
6868

6969
### Compose semantics
7070

71-
In Compose, [Semantics](https://developer.android.com/develop/ui/compose/semantics) describe your UI in an
71+
In Compose, [Semantics](https://developer.android.com/develop/ui/compose/accessibility/semantics) describe your UI in an
7272
alternative manner that is understandable for
7373
[Accessibility](https://developer.android.com/develop/ui/compose/accessibility) services and for the
7474
[Testing](https://developer.android.com/develop/ui/compose/testing) framework. You can use the Layout Inspector
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
name: agp-9-upgrade
3+
description: Upgrades, or migrates, an Android project to use Android Gradle Plugin
4+
(AGP) version 9. Do not use this skill for migrating Kotlin Multiplatform (KMP)
5+
projects.
6+
license: Complete terms in LICENSE.txt
7+
metadata:
8+
author: Google LLC
9+
last-updated: '2026-06-25'
10+
keywords:
11+
- Android Gradle Plugin 9
12+
- AGP 9
13+
- AGP Upgrade
14+
- AGP Migration
15+
- New AGP DSL
16+
- Migrate to built-in Kotlin
17+
---
18+
19+
## Migration guide
20+
21+
See the [AGP 9 migration guide](references/android/build/releases/agp-9-0-0-release-notes.md) for the major changes, many
22+
breaking, in AGP 9 compared to AGP 8.
23+
24+
## Requirements
25+
26+
If the user requests to update or migrate to AGP 9, first check the AGP version
27+
used in the project. If it is lower than 9, stop and ask the user to run the AGP
28+
Upgrade Assistant in Android Studio to update to the latest stable version of
29+
AGP, and confirm when done. The user may also request that this requirement be
30+
skipped; if this is the case, you should update the version of AGP to the latest
31+
stable version as part of the AGP 9 migration. See the
32+
[AGP 9 migration guide](references/android/build/releases/agp-9-0-0-release-notes.md) for how to do this.
33+
34+
Each version of AGP has its own set of compatibilities with other tools, such as
35+
Gradle, JDK, and Kotlin. The release notes for each of these versions will
36+
include a **Compatibility** table indicating the minimum versions for these
37+
tools.
38+
39+
Do not use this skill for KMP projects, as they are unsupported.
40+
41+
## Steps
42+
43+
If AGP is already at 9 or higher, then do the following:
44+
45+
### Step 1: Update dependencies
46+
47+
If KSP (`com.google.devtools.ksp`) is used in the project, ensure it is on
48+
version 2.3.6 or higher.
49+
50+
If Hilt is used in the project, ensure it is on version 2.59.2 or higher.
51+
52+
### Step 2: Migrate to built-in Kotlin
53+
54+
See [the guide](references/android/build/migrate-to-built-in-kotlin.md) for detailed information.
55+
56+
### Step 3. Migrate to the new AGP DSL
57+
58+
See [the guide](references/android/build/releases/agp-9-0-0-release-notes.md) for detailed information.
59+
60+
See also [gradle-recipes](references/recipes.md) for examples on how to migrate old code to code
61+
that is compatible with AGP 9 and the new DSL.
62+
63+
### Step 4. Migrate kapt to KSP or legacy-kapt
64+
65+
If KSP (`com.google.devtools.ksp`) or kapt (`org.jetbrains.kotlin.kapt`) are
66+
used in the project, see [KSP, kapt, and legacy-kapt](references/ksp-kapt.md) for detailed migration
67+
steps.
68+
69+
### Step 5. BuildConfig
70+
71+
If any Android module contains custom BuildConfig fields, see [BuildConfig](references/buildconfig.md)
72+
for detailed information.
73+
74+
### Step 6. Update gradle.properties
75+
76+
After the migration, check gradle.properties. Remove the following flags:
77+
78+
1. android.builtInKotlin
79+
2. android.newDsl
80+
3. android.uniquePackageNames
81+
4. android.enableAppCompileTimeRClass
82+
83+
Additionally, delete all temporary files you've created.
84+
85+
## Guidelines
86+
87+
- Never write or run python scripts.
88+
- Only search the Gradle dependency cache when inspecting external dependencies, and only as a last resort.
89+
- Never add `android.disallowKotlinSourceSets=false` to `gradle.properties`.
90+
- When verifying changes, don't run the `clean` task. This is a waste of time.
91+
92+
## Verification
93+
94+
After migration, verify the following:
95+
96+
1. Gradle IDE sync succeeds.
97+
2. `./gradlew help` succeeds.
98+
3. `./gradlew build --dry-run` succeeds.
99+
100+
## Troubleshooting
101+
102+
Paparazzi v2.0.0-alpha04 and lower versions have issues with AGP 9. See
103+
[references/paparazzi-gradle-9.md](references/paparazzi-gradle-9.md) for details.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
When an Android module contains custom BuildConfig fields, the following steps
2+
are necessary to ensure a correct build.
3+
4+
### Step 1: Enable the buildConfig build feature
5+
6+
In a build script:
7+
8+
android {
9+
buildFeatures {
10+
buildConfig = true
11+
}
12+
}
13+
14+
In custom build-logic for an app module:
15+
16+
extensions.configure<com.android.build.api.dsl.ApplicationExtension> {
17+
buildFeatures {
18+
buildConfig = true
19+
}
20+
}
21+
22+
In custom build-logic for a library module:
23+
24+
extensions.configure<com.android.build.api.dsl.LibraryExtension> {
25+
buildFeatures {
26+
buildConfig = true
27+
}
28+
}
29+
30+
In custom build-logic using `CommonExtension`:
31+
32+
extensions.configure<com.android.build.api.dsl.CommonExtension> {
33+
buildFeatures {
34+
buildConfig = true
35+
}
36+
}
37+
38+
### Step 2: Migrate to the new API
39+
40+
Use the **addCustomBuildConfigFields** recipe from the [gradle-recipes](https://developer.android.com/agents/skills/build/agp/agp-9-upgrade/references/recipes)
41+
repository.
42+
43+
**IMPORTANT:** For `BuildConfigField`s with a type of `String`, the `value` field
44+
*must* include quotation marks as part of the String. For example:
45+
46+
BuildConfigField(
47+
type = "String",
48+
value = "\"Some value\"",
49+
comment = "Optional comment",
50+
)
51+
52+
It is an **error** if the `value` field doesn't include quotation marks as
53+
part of the String. For example, `value = "Some value"` **is an error** . This is
54+
because the `value` is written out literally.

0 commit comments

Comments
 (0)