React Native Best Practices
vercel-labs/openreview
A prioritized rule set for React Native and Expo apps covering list performance, animation, navigation, UI patterns, state, rendering, monorepos and configuration.
A skill your agent uses to locate Compose semantics nodes from a UI test using onNodeWithTag, onNodeWithText, onNodeWithContentDescription, onAllNodes, and onRoot.
$ npx skills add skydoves/android-testing-skills --skill finding-nodes-by-tag-text-content -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install skydoves/android-testing-skills finding-nodes-by-tag-text-content --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/finders/finding-nodes-by-tag-text-content .claude/skills/finding-nodes-by-tag-text-content && 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 "finding-nodes-by-tag-text-content" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/finders/finding-nodes-by-tag-text-content into .claude/skills/finding-nodes-by-tag-text-content/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "finding-nodes-by-tag-text-content", 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/finders/finding-nodes-by-tag-text-contentType 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 finding-nodes-by-tag-text-content -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install skydoves/android-testing-skills finding-nodes-by-tag-text-content --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/finders/finding-nodes-by-tag-text-content .agents/skills/finding-nodes-by-tag-text-content && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "finding-nodes-by-tag-text-content" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/finders/finding-nodes-by-tag-text-content into .agents/skills/finding-nodes-by-tag-text-content/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "finding-nodes-by-tag-text-content", 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 finding-nodes-by-tag-text-content -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install skydoves/android-testing-skills finding-nodes-by-tag-text-content --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/finders/finding-nodes-by-tag-text-content .cursor/skills/finding-nodes-by-tag-text-content && 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 "finding-nodes-by-tag-text-content" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/finders/finding-nodes-by-tag-text-content into .cursor/skills/finding-nodes-by-tag-text-content/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "finding-nodes-by-tag-text-content", 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/finders/finding-nodes-by-tag-text-content--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 finding-nodes-by-tag-text-content -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install skydoves/android-testing-skills finding-nodes-by-tag-text-content --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/finders/finding-nodes-by-tag-text-content .gemini/skills/finding-nodes-by-tag-text-content && 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 "finding-nodes-by-tag-text-content" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/finders/finding-nodes-by-tag-text-content into .gemini/skills/finding-nodes-by-tag-text-content/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "finding-nodes-by-tag-text-content", 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 finding-nodes-by-tag-text-contentInstalls 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 finding-nodes-by-tag-text-content -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/finders/finding-nodes-by-tag-text-content .github/skills/finding-nodes-by-tag-text-content && 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 "finding-nodes-by-tag-text-content" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/finders/finding-nodes-by-tag-text-content into .github/skills/finding-nodes-by-tag-text-content/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "finding-nodes-by-tag-text-content", 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 finding-nodes-by-tag-text-content -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 finding-nodes-by-tag-text-content --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/finders/finding-nodes-by-tag-text-content .opencode/skills/finding-nodes-by-tag-text-content && 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 "finding-nodes-by-tag-text-content" agent skill from https://github.com/skydoves/android-testing-skills/tree/main/compose/finders/finding-nodes-by-tag-text-content into .opencode/skills/finding-nodes-by-tag-text-content/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "finding-nodes-by-tag-text-content", 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.
finding-nodes-by-tag-text-contentA skill your agent uses to locate Compose semantics nodes from a UI test using onNodeWithTag, onNodeWithText, onNodeWithContentDescription, onAllNodes, and onRoot.
Finding Nodes By Tag Text Content is an agent skill from skydoves/android-testing-skills. Use this skill to locate Compose semantics nodes from a UI test using onNodeWithTag, onNodeWithText, onNodeWithContentDescription, onAllNodes, and onRoot. Covers the count contract (single-node finders fail on 0 or 1 matches; collection finders never throw on 0), the merged-vs-unmerged tree distinction, and why tagging in production beats text-matching from tests. Use when the developer reports "no node matched", "multiple nodes matched", "tag not found", "useUnmergedTree", "Modifier.testTag", or asks how to find…
Its SKILL.md is about 3.2k 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. 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.
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.comjetbrains.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.
Finding Nodes By Tag Text Content loads about 3.2k tokens when it runs. Until then it costs about 191 tokens; SKILL.md has 903 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). 903 words, ~3,196 tokens.
.claude/skills/finding-nodes-by-tag-text-content/SKILL.md (or your agent's skills folder).Every Compose UI test starts by locating a semantics node. This skill picks the right finder, reasons about the count contract, and decides when to flip useUnmergedTree. Use it whenever the developer is staring at a "Reason: Expected exactly '1' node but could not find any node that satisfies …" error.
SemanticsNodeInteraction.Button, Text, Icon, IconButton, Switch, or any other composable inside a test.onNodeWithTag, onNodeWithText, onNodeWithContentDescription, onAllNodesWith*, or onRoot.useUnmergedTree, the merged tree, or "why does my inner Text not exist".../../assertions/asserting-node-state-and-text/SKILL.md (state) or ../../assertions/asserting-bounds-and-dimensions/SKILL.md (geometry).../composing-semantics-matchers/SKILL.md.../traversing-the-semantics-tree/SKILL.md.../../debug/printing-the-semantics-tree/SKILL.md.androidx.compose.ui:ui-test-junit4 (or v2) wired up. See ../../setup/configuring-test-dependencies/SKILL.md if createComposeRule is unresolved.ComposeTestRule or ComposeUiTest is in scope. See ../../setup/choosing-test-rule-vs-runtest/SKILL.md.setContent { … } before the finder runs. Finders are lazy and re-evaluate on every operation. 1. Default to onNodeWithTag(SomeTag). Add a Modifier.testTag(SomeTag) in the production source under a const val SomeTag = "Some". Tests find by tag, not by text. Skydoves hot take #1: in androidx/material3 itself, onNodeWithTag outnumbers onNodeWithText roughly 4:1 (1825 vs 424) and onNodeWithContentDescription 40:1 (1825 vs 46). Text finders churn with copy edits and break on locale rotation.
2. Pick the finder by signal type. Mapping (all from commonMain/.../Finders.kt):
| Need to match by … | Finder | File:line |
|---|---|---|
Modifier.testTag("…") | onNodeWithTag(testTag, useUnmergedTree=false) | Finders.kt:31-35 |
| Visible/editable/input text | onNodeWithText(text, substring=false, ignoreCase=false, useUnmergedTree=false) | Finders.kt:110-116 |
| Accessibility content description | onNodeWithContentDescription(label, substring=false, ignoreCase=false, useUnmergedTree=false) | Finders.kt:66-73 |
| Custom predicate | onNode(matcher, useUnmergedTree=false) from SemanticsNodeInteractionsProvider | SemanticsNodeInteractionsProvider.kt |
| Whole tree | onRoot(useUnmergedTree=false) | Finders.kt:150-153 |
Each onNodeWith* is a thin @CheckResult wrapper over onNode(hasTestTag(...))/onNode(hasText(...))/onNode(hasContentDescription(...)). The behavior is identical to the matcher form.
3. Respect the count contract. SemanticsNodeInteraction (single) throws AssertionError when fetched against 0 or >1 matching nodes (SemanticsNodeInteraction.kt:150-191). SemanticsNodeInteractionCollection (plural) never throws on 0 — it returns an empty collection that assertCountEquals(0) will accept (Assertions.kt:276-292). Pick the variant that matches the expected cardinality.
4. Flip useUnmergedTree = true only for inner elements. The merged tree collapses descendants whose semantics roll up into the parent — Text and Icon inside a Button appear as one node. To target the inner Text, pass useUnmergedTree = true. The flag is sticky: once a finder is created with useUnmergedTree = true, every subsequent onChild/onParent/filter keeps it on (SemanticsNodeInteraction.kt:42-49). Skydoves hot take #2: default to merged; flip only when targeting composition detail.
5. Read the auto-suggested unmerged hint on count mismatch. When a finder targets the merged tree and finds zero, the framework re-runs the same query against the unmerged tree and embeds the matches in the error message (SemanticsNodeInteraction.kt:184-205, getNodesInUnmergedTree). If the error shows nodes that "would have matched" with useUnmergedTree = true, flip the flag.
6. For substring or case-insensitive text matches, pass the boolean flags explicitly. onNodeWithText("Sub", substring = true) matches "Submit" and "Subscribe". Combine with onAllNodesWithText plus assertCountEquals to express intent (see Pattern: ambiguous text below).
// WRONG
@Test
fun submit_isEnabled_afterFormFilled() {
rule.setContent { CheckoutScreen() }
rule.onNodeWithText("Place order").assertIsEnabled()
}
// WRONG because: the button label changes with copy edits, and the test breaks the moment QA
// asks for "Buy now". Also fails under any locale that is not the test default.// RIGHT
// production: ui/checkout/CheckoutScreen.kt
const val PlaceOrderButtonTag = "CheckoutScreen.PlaceOrderButton"
@Composable
fun CheckoutScreen() {
Button(modifier = Modifier.testTag(PlaceOrderButtonTag), onClick = { /* … */ }) {
Text(stringResource(R.string.place_order))
}
}
// test:
@Test
fun submit_isEnabled_afterFormFilled() {
rule.setContent { CheckoutScreen() }
rule.onNodeWithTag(PlaceOrderButtonTag).assertIsEnabled()
}// WRONG
@Test
fun greeting_appearsTwice() {
rule.setContent { GreetingList(listOf("Hello", "Hello")) }
// Returns the first match silently; never proves "twice".
rule.onNodeWithText("Hello").assertIsDisplayed()
}
// WRONG because: onNode* throws on >1 matches; if the duplicate count drifts to 1 the test
// passes for the wrong reason, and if it drifts to 3 the test fails with an opaque count error.// RIGHT
@Test
fun greeting_appearsTwice() {
rule.setContent { GreetingList(listOf("Hello", "Hello")) }
rule.onAllNodesWithText("Hello").assertCountEquals(2)
}// WRONG
@Test
fun button_text_isShown() {
rule.setContent {
Button(onClick = {}, modifier = Modifier.testTag("submit")) {
Text("Submit", modifier = Modifier.testTag("submitLabel"))
}
}
rule.onNodeWithTag("submitLabel").assertIsDisplayed()
}
// WRONG because: in the merged tree the Text is rolled into the Button. The finder sees zero
// nodes and the auto-attached unmerged hint will surface in the error message — flip the flag.// RIGHT
@Test
fun button_text_isShown() {
rule.setContent { /* same content */ }
rule.onNodeWithTag("submitLabel", useUnmergedTree = true).assertIsDisplayed()
}// WRONG
rule.onNodeWithText("hello").assertIsDisplayed()
// WRONG because: matches only the exact string. UI showing "Hello, world" or "HELLO" produces
// a "no node matched" error.// RIGHT — when intent really is "contains 'Hello'":
rule.onNodeWithText("Hello", substring = true, ignoreCase = true).assertIsDisplayed()
// RIGHTER — prefer a tag and assert the text once:
rule.onNodeWithTag(GreetingTag).assertTextContains("Hello", substring = true, ignoreCase = true)// production:
IconButton(onClick = onShare, modifier = Modifier.testTag(ShareButtonTag)) {
Icon(Icons.Default.Share, contentDescription = stringResource(R.string.share))
}
// test:
rule.onNodeWithTag(ShareButtonTag).assertIsDisplayed() // PREFERRED
rule.onNodeWithContentDescription("Share").assertIsDisplayed() // acceptable for accessibility-focused testsonNodeWithContentDescription defaults to merged-tree exact match, so the merged Icon's
content description rolls up to the parent IconButton. To match a specific Icon's description
in a button that contains many icons, flip useUnmergedTree = true.
onRoot() as the screenshot/print starting pointrule.onRoot().printToLog("tree") // dump merged
rule.onRoot(useUnmergedTree = true).printToLog("unmerged")See ../../debug/printing-the-semantics-tree/SKILL.md for printToLog / printToString depth controls.
onNodeWithTag over onNodeWithText and onNodeWithContentDescription. Skydoves hot take #1.Modifier.testTag(...) in production code under a constant. MUST NOT redefine the same string literal in both the production source and the test.useUnmergedTree = false. Flip to true only when targeting an inner element collapsed by merge or verifying composition detail. Skydoves hot take #2.onAllNodesWith* + assertCountEquals when the count itself is part of the test contract. MUST NOT rely on onNodeWith* to imply "exactly one" by side effect.onNode(...).onChild().onChildAt(2).onChild()). Add a tag instead — see ../traversing-the-semantics-tree/SKILL.md.useUnmergedTree = true rather than rewriting the matcher.onNodeWithTag unless the assertion is explicitly about user-visible text or accessibility content description.const val in the production source, not inlined in the test.useUnmergedTree = true appears only at sites that target an inner element of a merged composable (Button, IconButton, ListItem, etc.)../gradlew :app:connectedDebugAndroidTest (device) or :app:testDebugUnitTest (Robolectric host) passes locally.compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Finders.kt — onNodeWithTag/Text/ContentDescription/onRoot and their onAllNodesWith* siblings.compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/SemanticsNodeInteractionsProvider.kt — base onNode(matcher, useUnmergedTree) / onAllNodes(matcher, useUnmergedTree).compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction.kt — count contract (fetchOneOrThrow) and the auto-attached unmerged-tree hint (getNodesInUnmergedTree).compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Filters.kt — hasTestTag, hasText, hasContentDescription underlying matchers.© 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/finders/finding-nodes-by-tag-text-content of skydoves/android-testing-skills.
Open the folder on GitHubat commit 8665ed5
Finding Nodes By Tag Text Content 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 |
|---|---|---|---|---|---|---|
| Finding Nodes By Tag Text Content this skillskydoves/android-testing-skills | 333 | — | ~3.2k | Automated safety check: Pass | Apache-2.0 | |
| React Native Best Practicesvercel-labs/openreview | 1.7k | 17 repos | ~1.1k | Automated safety check: Pass | MIT | |
| Swiftui Protwostraws/SwiftUI-Agent-Skill | 5.2k | 2 repos | ~1.5k | Automated safety check: Pass | MIT | |
| Kortix Brandkortix-ai/suna | 20k | — | ~4k | Automated safety check: Pass | Custom licence | |
| Ip As LogoKartikLabhshetwar/better-shot | 2.4k | 1 repos | ~4.3k | Automated safety check: Pass | MIT | |
| Compose Multiplatform Patternsmonta-app/ocpp-emulator | 180 | 5 repos | ~2k | Automated safety check: Pass | Apache-2.0 |
vercel-labs/openreview
A prioritized rule set for React Native and Expo apps covering list performance, animation, navigation, UI patterns, state, rendering, monorepos and configuration.
twostraws/SwiftUI-Agent-Skill
Comprehensively reviews SwiftUI code for best practices on modern APIs, maintainability, and performance.
kortix-ai/suna
Load FIRST for anything that carries the Kortix look or voice: product or mobile UI, copy of any kind, decks, social, images, email, CLI output, anything with the logo, and reviews of these.
KartikLabhshetwar/better-shot
Generate extremely simple, cute, personified square character images with rounded heavy forms, two purposeful character colors, one solid background color, and a dominant lower-corner composition.
monta-app/ocpp-emulator
Compose Multiplatform and Jetpack Compose patterns for KMP projects — state management, navigation, theming, performance, and platform-specific UI.
adamlyttleapps/claude-skill-aso-appstore-screenshots
Generate high-converting App Store screenshots by analyzing your app's codebase, discovering core benefits, and creating ASO-optimized screenshot images using Nano Banana Pro.
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…
Categories
A skill your agent uses to locate Compose semantics nodes from a UI test using onNodeWithTag, onNodeWithText, onNodeWithContentDescription, onAllNodes, and onRoot. Finding Nodes By Tag Text Content is an agent skill from skydoves/android-testing-skills. Use this skill to locate Compose semantics nodes from a UI test using onNodeWithTag, onNodeWithText, onNodeWithContentDescription, onAllNodes, and onRoot.
Finding Nodes By Tag Text Content fits situations like: locate Compose semantics nodes from a UI test using onNodeWithTag; onNodeWithContentDescription; the developer reports no node matched; multiple nodes matched.
Run `npx skills add skydoves/android-testing-skills --skill finding-nodes-by-tag-text-content -a claude-code`. Or copy the skill folder (compose/finders/finding-nodes-by-tag-text-content in skydoves/android-testing-skills) into .claude/skills/finding-nodes-by-tag-text-content in your project. Claude Code loads it when a task matches its description.
Run `npx skills add skydoves/android-testing-skills --skill finding-nodes-by-tag-text-content -a codex`. Or copy the skill folder (compose/finders/finding-nodes-by-tag-text-content in skydoves/android-testing-skills) into .agents/skills/finding-nodes-by-tag-text-content 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 finding-nodes-by-tag-text-content -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/finding-nodes-by-tag-text-content, .gemini/skills/finding-nodes-by-tag-text-content, .github/skills/finding-nodes-by-tag-text-content and .opencode/skills/finding-nodes-by-tag-text-content in your project.
SKILL.md names no scripts, command-line tools or credentials: Finding Nodes By Tag Text Content is instructions for the agent only.
SKILL.md names 2 domains. As links in the text: developer.android.com and jetbrains.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.
Finding Nodes By Tag Text Content 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.2k tokens (SKILL.md is roughly 13k 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 Finding Nodes By Tag Text Content: React Native Best Practices (vercel-labs/openreview, 1.7k stars), Swiftui Pro (twostraws/SwiftUI-Agent-Skill, 5.2k stars), Kortix Brand (kortix-ai/suna, 20k stars) and Ip As Logo (KartikLabhshetwar/better-shot, 2.4k 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 333 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.