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.
A skill your agent uses to drive Jetpack Compose UI from tests with the high-level action APIs that do not go through a gesture builder — performClick, performScrollTo, performScrollToIndex…
$ npx skills add skydoves/android-testing-skills --skill clicking-and-scrolling -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install skydoves/android-testing-skills clicking-and-scrolling --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/compose/actions/clicking-and-scrolling .claude/skills/clicking-and-scrolling && rm -rf skills-srcUse ~/.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/
Install the "clicking-and-scrolling" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/actions/clicking-and-scrolling into .claude/skills/clicking-and-scrolling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clicking-and-scrolling", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/skydoves/android-testing-skills/tree/main/compose/actions/clicking-and-scrollingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add skydoves/android-testing-skills --skill clicking-and-scrolling -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install skydoves/android-testing-skills clicking-and-scrolling --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/compose/actions/clicking-and-scrolling .agents/skills/clicking-and-scrolling && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "clicking-and-scrolling" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/actions/clicking-and-scrolling into .agents/skills/clicking-and-scrolling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clicking-and-scrolling", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add skydoves/android-testing-skills --skill clicking-and-scrolling -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install skydoves/android-testing-skills clicking-and-scrolling --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/compose/actions/clicking-and-scrolling .cursor/skills/clicking-and-scrolling && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "clicking-and-scrolling" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/actions/clicking-and-scrolling into .cursor/skills/clicking-and-scrolling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clicking-and-scrolling", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/skydoves/android-testing-skills.git --path compose/actions/clicking-and-scrolling--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add skydoves/android-testing-skills --skill clicking-and-scrolling -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install skydoves/android-testing-skills clicking-and-scrolling --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/compose/actions/clicking-and-scrolling .gemini/skills/clicking-and-scrolling && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "clicking-and-scrolling" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/actions/clicking-and-scrolling into .gemini/skills/clicking-and-scrolling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clicking-and-scrolling", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install skydoves/android-testing-skills clicking-and-scrollingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add skydoves/android-testing-skills --skill clicking-and-scrolling -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/compose/actions/clicking-and-scrolling .github/skills/clicking-and-scrolling && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "clicking-and-scrolling" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/actions/clicking-and-scrolling into .github/skills/clicking-and-scrolling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clicking-and-scrolling", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add skydoves/android-testing-skills --skill clicking-and-scrolling -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install skydoves/android-testing-skills clicking-and-scrolling --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/compose/actions/clicking-and-scrolling .opencode/skills/clicking-and-scrolling && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "clicking-and-scrolling" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/actions/clicking-and-scrolling into .opencode/skills/clicking-and-scrolling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clicking-and-scrolling", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
clicking-and-scrollingA skill your agent uses to drive Jetpack Compose UI from tests with the high-level action APIs that do not go through a gesture builder — performClick, performScrollTo, performScrollToIndex…
Clicking And Scrolling is an agent skill from skydoves/android-testing-skills. Use this skill to drive Jetpack Compose UI from tests with the high-level action APIs that do not go through a gesture builder — performClick, performScrollTo, performScrollToIndex, performScrollToKey, performScrollToNode, requestFocus, performSemanticsAction, and performFirstLinkClick. Covers picking the correct receiver node (the scrollable container vs an item), the matchers used to find a scroll parent (hasScrollAction, hasScrollToIndexAction, hasScrollToKeyAction, hasScrollToNodeAction), and how the lazy vs…
Its SKILL.md is about 3.6k 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: ⚡️ A set of skills for Android testing: Compose UI, AndroidX Test, JVM unit tests, and ADB. The licence is Apache-2.0.
9 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 8665ed5. It shows what the files ask for, not the result of running them.
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.
No scripts in the folder and no shell commands in SKILL.md (its code samples are kotlin).
From the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
developer.android.comgithub.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Clicking And Scrolling loads about 3.6k tokens when it runs. Until then it costs about 217 tokens; SKILL.md has 1,039 words of instructions outside code blocks.
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.
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.
The full file from skydoves/android-testing-skills at commit 8665ed5, republished under its Apache-2.0 licence (© skydoves). 1,039 words, ~3,604 tokens.
.claude/skills/clicking-and-scrolling/SKILL.md (or your agent's skills folder).Compose's high-level actions resolve to platform-appropriate primitives or to semantics actions that the composable already exposes. Use them whenever the test does not need pixel-level control over the gesture. Reach for performTouchInput { … } (see ../injecting-touch-gestures/SKILL.md) only when the high-level action cannot express the intent.
LazyColumn / LazyRow to a specific index, key, or matched item.AccessibilityAction<T> declared via Modifier.semantics { … }.LinkAnnotation inside a Text.../injecting-touch-gestures/SKILL.md.../injecting-mouse-and-keyboard/SKILL.md.../entering-text/SKILL.md.../../finders/finding-nodes-by-tag-text-content/SKILL.md and ../../debug/printing-the-semantics-tree/SKILL.md.androidx.compose.ui:ui-test-junit4 (or androidx.compose.ui:ui-test for runComposeUiTest) configured per ../../setup/configuring-test-dependencies/SKILL.md.Modifier.testTag("…") from production source — skydoves hot take #1.performScrollToIndex / performScrollToKey: the container must implement the relevant semantics actions. LazyColumn / LazyRow do; a plain Modifier.verticalScroll does not.performFirstLinkClick: the Text must use an AnnotatedString carrying a LinkAnnotation.Pick the right receiver node. This is the most common failure mode. performClick / performScrollTo / performFirstLinkClick run on a content node; performScrollToIndex / performScrollToKey / performScrollToNode run on the scrollable container. Confirm with ../../debug/printing-the-semantics-tree/SKILL.md if unsure.
Click a node — performClick(). On Android (both device tests and Robolectric host tests) it delegates to performTouchInput { click() } via the Android actual (Actions.android.kt:22-24). The mouse-click path lives in JetBrains' Compose Multiplatform desktop fork. Common API at Actions.kt:49-62.
rule.onNodeWithTag(SubmitButtonTag).performClick()performScrollTo(). Walks up the tree to the closest parent carrying SemanticsActions.ScrollBy and scrolls by the smallest delta needed to put the node fully in the viewport (Actions.kt:78-87). Throws AssertionError if no scroll parent exists.rule.onNodeWithTag(LastItemTag).performScrollTo().assertIsDisplayed()performScrollToIndex(index). Requires SemanticsActions.ScrollToIndex on the receiver node (Actions.kt:159-172). The receiver MUST be the container (the LazyColumn itself), not an item.rule.onNode(hasScrollToIndexAction()).performScrollToIndex(42)performScrollToKey(key). Requires both IndexForKey and ScrollToIndex (Actions.kt:188-203). Matches the key = { … } parameter of LazyColumn / LazyRow items.rule.onNode(hasScrollToKeyAction()).performScrollToKey("user-7")performScrollToNode(matcher). Walks the lazy container viewport-by-viewport from start to end. For non-lazy scrollables, falls back to performScrollTo once the node materializes (Actions.kt:233-268). Throws when end-of-content is reached without a match.rule.onNode(hasScrollToNodeAction()).performScrollToNode(hasText("End of feed"))requestFocus(). Sugar for performSemanticsAction(SemanticsActions.RequestFocus) (Actions.kt:600-601). Required before performIndirectPointerInput, and useful for BasicTextField setups that bypass performTextInput's auto-focus path.rule.onNodeWithTag(InputTag).requestFocus()AccessibilityAction<T> — performSemanticsAction(key, invocation) for parameterized actions, performSemanticsAction(key) for nullary ones (Actions.kt:631-672). The action MUST be declared on the node via Modifier.semantics { … }; otherwise an AssertionError is thrown.val MyAction = SemanticsPropertyKey<AccessibilityAction<(Int) -> Boolean>>("MyAction")
// production:
Modifier.semantics { this[MyAction] = AccessibilityAction("Bump") { delta -> bump(delta); true } }
// test:
rule.onNodeWithTag(Tag).performSemanticsAction(MyAction) { it(3) }LinkAnnotation inside Text — performFirstLinkClick(predicate) (Actions.kt:777-804). The default predicate { true } clicks the first link. Throws when the receiver has no text or when no link satisfies the predicate.rule.onNodeWithTag(BodyTag).performFirstLinkClick { it.item is LinkAnnotation.Url }// WRONG
rule.onNodeWithTag("item-7").performScrollToIndex(7)
// WRONG because: performScrollToIndex requires the ScrollToIndex semantics action,
// which lives on the LazyColumn container, not on its items. AssertionError:
// "Failed to scroll to index 7, the node is missing [ScrollToIndex]".// RIGHT
rule.onNode(hasScrollToIndexAction()).performScrollToIndex(7)
rule.onNodeWithTag("item-7").assertIsDisplayed()The matcher hasScrollToIndexAction() is defined in Filters.kt and identifies any container exposing SemanticsActions.ScrollToIndex. Tag the container too if multiple lazy lists exist on screen.
// WRONG
rule.onNodeWithTag(BottomBannerTag).assertIsDisplayed()
// WRONG because: a Column inside Modifier.verticalScroll renders all children, but
// children outside the viewport are clipped — assertIsDisplayed fails because
// the visible bounds intersect the viewport at zero pixels.// RIGHT
rule.onNodeWithTag(BottomBannerTag).performScrollTo().assertIsDisplayed()performScrollTo scans up to the closest hasScrollAction() parent and scrolls by the smallest delta needed (Actions.kt:95-141). For lazy lists, prefer performScrollToNode since the target item may not yet be composed.
// RIGHT
rule.onNode(hasScrollToNodeAction()).performScrollToNode(
hasText("Privacy Policy", substring = true)
)The matcher hasScrollToNodeAction() accepts both lazy and non-lazy scrollables (Filters.kt). For lazy containers, performScrollToNode rewinds to index 0 first and walks viewport-sized steps until the matcher hits.
Production:
val Bump = SemanticsPropertyKey<AccessibilityAction<(Int) -> Boolean>>("Bump")
@Composable
fun Counter(value: Int, onBump: (Int) -> Unit) {
Box(
Modifier
.testTag("counter")
.semantics {
this[Bump] = AccessibilityAction("Bump") { delta ->
onBump(delta); true
}
}
) { Text(value.toString()) }
}Test:
@Test fun bumpAction_increments() {
var value by mutableIntStateOf(0)
rule.setContent { Counter(value) { value += it } }
rule.onNodeWithTag("counter").performSemanticsAction(Bump) { it(5) }
rule.runOnIdle { assertEquals(5, value) }
}This is the cleanest way to test logic that does not have a built-in action like OnClick — no need to fabricate touch coordinates or to depend on the layout being clickable.
// RIGHT
@Test fun privacyLink_navigates() {
var clicked = false
rule.setContent {
Text(
buildAnnotatedString {
append("Read our ")
withLink(LinkAnnotation.Url("https://example.com/privacy") {
clicked = true
}) { append("Privacy Policy") }
},
modifier = Modifier.testTag(BodyTag),
)
}
rule.onNodeWithTag(BodyTag).performFirstLinkClick { it.item is LinkAnnotation.Url }
rule.runOnIdle { assertTrue(clicked) }
}performFirstLinkClick first asserts the node has text, collects every LinkAnnotation in the AnnotatedString, picks the first that satisfies the predicate, then dispatches OnClick on the corresponding link child (Actions.kt:777-804).
// RIGHT
rule.onNodeWithTag(SurfaceTag).requestFocus()
rule.performIndirectPointerInput( // extension on SemanticsNodeInteractionsProvider, not on a node
indirectPointerEventPrimaryDirectionalMotionAxis = Vertical,
inputDeviceSize = IntSize(1000, 1000),
) {
// events go to the focused tree
}The public performIndirectPointerInput extension hangs off SemanticsNodeInteractionsProvider (Actions.kt:862) — i.e. the rule (or ComposeUiTest) itself. The same-name overload on SemanticsNodeInteraction is internal (Actions.kt:942), so rule.onRoot().performIndirectPointerInput(...) does NOT compile from consumer code.
Indirect pointer input dispatches through the focus path, so an explicit requestFocus is mandatory (Actions.kt:807-875). For ordinary touch tests, focus is not required.
performScrollToIndex, performScrollToKey, and performScrollToNode on the scrollable container, not on an item — the semantics actions live on the container. Otherwise AssertionError: the node is missing [ScrollToIndex].performScrollTo on a content node, not on the container — performScrollTo walks up to find the scroll parent.Modifier.testTag("…") whose value is a constant defined in production source — skydoves hot take #1. Text and content-description finders are i18n-fragile.runOnIdle { … } (skydoves hot take #5). Reading state directly from the test thread races with the recomposer.performScrollTo on a LazyColumn item — the item probably is not even composed. Use performScrollToIndex / performScrollToKey / performScrollToNode on the container.performClick for hover, right-click, or wheel scroll. Use the modality-specific scope from ../injecting-mouse-and-keyboard/SKILL.md.hasScrollAction() / hasScrollToIndexAction() / hasScrollToKeyAction() / hasScrollToNodeAction() (Filters.kt) when there is a single such container on screen, instead of adding a redundant test tag to it.performScrollToIndex / performScrollToKey / performScrollToNode call targets the container — not an item — and a tag or hasScrollToIndexAction() matcher selects it.performClick is used to simulate hover, right-click, or scroll wheel.performSemanticsAction call references a SemanticsPropertyKey that the production code installs via Modifier.semantics { … }.rule.runOnIdle { … }../gradlew :app:connectedDebugAndroidTest (or :app:testDebugUnitTest for Robolectric) passes for the test under change.compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Actions.kt — performClick (Actions.kt:58), performScrollTo (Actions.kt:78), performScrollToIndex (Actions.kt:159), performScrollToKey (Actions.kt:188), performScrollToNode (Actions.kt:233), requestFocus (Actions.kt:600), performSemanticsAction (Actions.kt:631 / Actions.kt:668), performFirstLinkClick (Actions.kt:777).compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Filters.kt — hasScrollAction, hasScrollToIndexAction, hasScrollToKeyAction, hasScrollToNodeAction.compose/foundation/foundation/integration-tests/lazy-tests/.../LazyListTest.kt — canonical performScrollToIndex / performScrollToKey patterns.compose/foundation/foundation/src/androidDeviceTest/.../CombinedClickableTest.kt — performClick, performTouchInput { longClick() }.© skydoves, 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
Just SKILL.md in compose/actions/clicking-and-scrolling of skydoves/android-testing-skills.
Open the folder on GitHubat commit 8665ed5
Clicking And Scrolling 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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Clicking And Scrolling this skillskydoves/android-testing-skills | 334 | — | ~3.6k | Automated safety check: Pass | Apache-2.0 | |
| Compose Multiplatform Patternsmonta-app/ocpp-emulator | 180 | 5 repos | ~2k | Automated safety check: Pass | Apache-2.0 | |
| Deferring State ReadsrosuH/EasyWatermark | 1.9k | 1 repos | ~3.8k | Automated safety check: Pass | Apache-2.0 | |
| Android Developmentdpconde/claude-android-skill | 336 | — | ~1.7k | Automated safety check: Pass | MIT | |
| Diagnosing Compose StabilityrosuH/EasyWatermark | 1.9k | 1 repos | ~3.3k | Automated safety check: Pass | Apache-2.0 | |
| Stylesarindamxd/camerax-android | 132 | 4 repos | ~2.3k | Automated safety check: Pass | Apache-2.0 |
monta-app/ocpp-emulator
Compose Multiplatform and Jetpack Compose patterns for KMP projects — state management, navigation, theming, performance, and platform-specific UI.
rosuH/EasyWatermark
A skill your agent uses to push frequently-changing Jetpack Compose state reads (scroll position, animation values, drag offsets) out of the Composition phase and down into Layout or Draw using…
dpconde/claude-android-skill
Create production-quality Android applications following Google's official architecture guidance and NowInAndroid best practices.
rosuH/EasyWatermark
A skill your agent uses to diagnose Jetpack Compose stability problems by enabling and reading the Compose Compiler Reports (classes.txt, composables.txt, composables.csv, module.json).
arindamxd/camerax-android
A skill your agent uses to integrate the Jetpack Compose Styles API into an Android project.
androidx/androidx
Benchmarking and improving the performance of Jetpack Compose.
skydoves/android-testing-skills
A skill your agent uses to verify Compose layout measurements from a UI test using assertWidthIsEqualTo, assertHeightIsEqualTo, assertWidthIsAtLeast, assertHeightIsAtLeast…
skydoves/android-testing-skills
A skill your agent uses to verify a Compose semantics node's properties from a UI test using assertExists, assertDoesNotExist, assertIsDisplayed, assertIsNotDisplayed, assertIsDeactivated…
skydoves/android-testing-skills
A skill your agent uses to render every Jetpack Compose @Preview as a screenshot on a real Android device or emulator and publish a browsable HTML catalog from CI.
skydoves/android-testing-skills
A skill your agent uses to capture visual artefacts from a device for test failures, golden image generation, QA repro, and demo videos.
skydoves/android-testing-skills
A skill your agent uses to pick the correct Compose UI test entry point.
skydoves/android-testing-skills
A skill your agent uses to pick which behaviors to cover in an Android test suite using Google's five-category state vocabulary plus the explicit "what NOT to test" list from…
Works with
Categories
A skill your agent uses to drive Jetpack Compose UI from tests with the high-level action APIs that do not go through a gesture builder — performClick, performScrollTo, performScrollToIndex…. Clicking And Scrolling is an agent skill from skydoves/android-testing-skills. Use this skill to drive Jetpack Compose UI from tests with the high-level action APIs that do not go through a gesture builder — performClick, performScrollTo, performScrollToIndex, performScrollToKey, performScrollToNode, requestFocus, performSemanticsAction, and performFirstLinkClick.
Clicking And Scrolling fits situations like: drive Jetpack Compose UI from tests with the high-level action APIs that do not go through a gesture builder — performClick; performScrollTo; performScrollToIndex; performScrollToKey.
Run `npx skills add skydoves/android-testing-skills --skill clicking-and-scrolling -a claude-code`. Or copy the skill folder (compose/actions/clicking-and-scrolling in skydoves/android-testing-skills) into .claude/skills/clicking-and-scrolling in your project. Claude Code loads it when a task matches its description.
Run `npx skills add skydoves/android-testing-skills --skill clicking-and-scrolling -a codex`. Or copy the skill folder (compose/actions/clicking-and-scrolling in skydoves/android-testing-skills) into .agents/skills/clicking-and-scrolling in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add skydoves/android-testing-skills --skill clicking-and-scrolling -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/clicking-and-scrolling, .gemini/skills/clicking-and-scrolling, .github/skills/clicking-and-scrolling and .opencode/skills/clicking-and-scrolling in your project.
SKILL.md names no scripts, command-line tools or credentials: Clicking And Scrolling is instructions for the agent only.
SKILL.md names 2 domains. As links in the text: developer.android.com and github.com. This is read from the text; nothing was executed.
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.
Clicking And Scrolling is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.6k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Clicking And Scrolling: Compose Multiplatform Patterns (monta-app/ocpp-emulator, 180 stars), Deferring State Reads (rosuH/EasyWatermark, 1.9k stars), Android Development (dpconde/claude-android-skill, 336 stars) and Diagnosing Compose Stability (rosuH/EasyWatermark, 1.9k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
skydoves (a GitHub user) maintains it in skydoves/android-testing-skills, which has 334 GitHub stars. The repository holds 50 skills in this directory. The repository was last updated on May 25, 2026.
Source: skydoves/android-testing-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.