Agent skill

Testing State Restoration

by skydoves in skydoves/android-testing-skills

A skill your agent uses to test rememberSaveable round-trips with StateRestorationTester, the only supported tool for proving Compose state survives process death and configuration change.

Apache-2.0Auto-check passedMobile

Install Testing State Restoration

skills CLI
$ npx skills add skydoves/android-testing-skills --skill testing-state-restoration -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install skydoves/android-testing-skills testing-state-restoration --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/compose/patterns/testing-state-restoration .claude/skills/testing-state-restoration && rm -rf skills-src

Use ~/.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/

Facts

Skill name
testing-state-restoration
GitHub stars
333
Token cost
~3.5k tokens
SKILL.md length
817 words
Files
1
Skills in repo
50
Repo updated
First seen
Licence
Apache-2.0

At a glance

A skill your agent uses to test rememberSaveable round-trips with StateRestorationTester, the only supported tool for proving Compose state survives process death and configuration change.

  • Test rememberSaveable round-trips with StateRestorationTester
  • SKILL.md covers When to use this skill, When NOT to use this skill, Prerequisites and Workflow, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • The only supported tool for proving Compose state survives process death and configuration change

What it does

Testing State Restoration is an agent skill from skydoves/android-testing-skills. Use this skill to test rememberSaveable round-trips with StateRestorationTester, the only supported tool for proving Compose state survives process death and configuration change. Covers the constructor (StateRestorationTester(rule: ComposeContentTestRule)), why restorationTester.setContent { } MUST replace rule.setContent { }, the state = null between phases trick that proves restoration actually happened, the 1 MB Bundle cap, and what is NOT exercised (Activity lifecycle, configuration changes, plain remember)…

Its SKILL.md is about 3.5k 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.

When your agent uses it

  • Test rememberSaveable round-trips with StateRestorationTester
  • The only supported tool for proving Compose state survives process death and configuration change
  • The developer asks how do I test rememberSaveable
  • Test state survives rotation

Example prompts

  • “how do I test rememberSaveable”
  • “test state survives rotation”
  • “state is lost after restore”
  • “/testing-state-restoration”

What it can do on your machine

Read from SKILL.md and the folder at commit 8665ed5. It shows what the files ask for, not the result of running them.

  • Tool permissions

    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.

  • Runs code

    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.

  • Network

    Links to these hosts (documentation or services it may open):

    • developer.android.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Testing State Restoration loads about 3.5k tokens when it runs. Until then it costs about 212 tokens; SKILL.md has 817 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~212
When it runs · the whole SKILL.md, loaded when a task matches
~3.5k

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.

Safety

Auto-check passed

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.

SKILL.md

The full file from skydoves/android-testing-skills at commit 8665ed5, republished under its Apache-2.0 licence (© skydoves). 817 words, ~3,533 tokens.

Download SKILL.mdSave it as .claude/skills/testing-state-restoration/SKILL.md (or your agent's skills folder).
name
testing-state-restoration
description
Use this skill to test `rememberSaveable` round-trips with `StateRestorationTester`, the only supported tool for proving Compose state survives process death and configuration change. Covers the constructor (`StateRestorationTester(rule: ComposeContentTestRule)`), why `restorationTester.setContent { }` MUST replace `rule.setContent { }`, the `state = null` between phases trick that proves restoration actually happened, the 1 MB Bundle cap, and what is NOT exercised (Activity lifecycle, configuration changes, plain `remember`). Use when the developer asks "how do I test rememberSaveable", "test state survives rotation", "state is lost after restore", "Bundle exceeds maximum size", or shows a test that re-reads the same state reference after `emulateSavedInstanceStateRestore` and is confused why nothing changed.
license
Apache-2.0. See LICENSE for complete terms.
metadata.author
Jaewoong Eum (skydoves)
metadata.keywords
jetpack-compose, ui-testing, state-restoration-tester, rememberSaveable, SaveableStateRegistry, emulateSavedInstanceStateRestore, process-death…

Testing State Restoration — StateRestorationTester Round-Trips Only rememberSaveable

StateRestorationTester is the only first-party way to verify that a Composable's state survives a save/restore cycle. It is narrow — it injects a LocalSaveableStateRegistry, snapshots whatever registered through it, throws away the composition, and re-composes with the snapshot restored. It does not restart the Activity, it does not trigger Application.onCreate, and it has a hard 1 MB cap on the serialized Bundle. Misunderstanding the scope produces tests that look passing but prove nothing.

When to use this skill

  • The developer is verifying that rememberSaveable survives — for a LazyListState, a TextField value, a screen toggle, etc.
  • The developer asks "how do I test rememberSaveable in a unit test?"
  • A test calls emulateSavedInstanceStateRestore() and the state appears unchanged or null.
  • The developer hits IllegalStateException: Bundle exceeds maximum size (1 MB).
  • A reviewer asks for a regression test for a save/restore bug fix.

When NOT to use this skill

  • The bug under test is an Activity recreation issue (rotation re-creates the Activity, callbacks fire, ViewModels rebind). StateRestorationTester does not exercise that path; use Espresso ActivityScenario.recreate() plus this skill if both phases need coverage.
  • The state is in a ViewModel and the developer wants to test SavedStateHandle. Use the AndroidX ViewModel testing tools.
  • The class skeleton is wrong — fix ../structuring-a-compose-test/SKILL.md first.

Prerequisites

  • androidx.compose.ui:ui-test-junit4 on androidTestImplementation. StateRestorationTester is in package androidx.compose.ui.test.junit4.
  • A ComposeContentTestRule (i.e. one of createComposeRule() / createAndroidComposeRule<A>()). createEmptyComposeRule() is NOT compatible because it returns ComposeTestRule, which has no setContent.
  • The Composable under test stores its state with rememberSaveable { … } (or registers via SaveableStateRegistry). Plain remember does NOT survive the round-trip — the KDoc states it explicitly: "the state stored via regular state() or remember() will be lost." (cited at compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/StateRestorationTester.android.kt:67-68).

Workflow

  • 1. Construct the tester from the rule.
kotlin
import androidx.compose.ui.test.junit4.StateRestorationTester

@get:Rule val rule = createComposeRule(StandardTestDispatcher())
val restorationTester = StateRestorationTester(rule)

The constructor signature is class StateRestorationTester(private val composeTestRule: ComposeContentTestRule), file StateRestorationTester.android.kt:43.

  • 2. Use restorationTester.setContent { } instead of rule.setContent { }. This is non-negotiable: the tester replaces the LocalSaveableStateRegistry for the wrapped content. Calling rule.setContent directly bypasses the injection and emulateSavedInstanceStateRestore will fail with "setContent should be called first!" (cited at StateRestorationTester.android.kt:71).

  • 3. Hoist the state reference as a nullable var declared above setContent. This is the canonical shape — see compose/foundation/foundation/integration-tests/lazy-tests/src/androidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt:890-913:

kotlin
@Test
fun stateIsRestored() {
    val restorationTester = StateRestorationTester(rule)
    var state: LazyListState? = null

    restorationTester.setContent {
        state = rememberLazyListState()
        LazyColumn(Modifier.requiredSize(100.dp).testTag(LazyListTag), state = state!!) {
            items(20) { Spacer(Modifier.requiredSize(20.dp).testTag("$it")) }
        }
    }

    rule.onNodeWithTag(LazyListTag).performScrollToIndex(2)

    val (index, scrollOffset) = rule.runOnIdle {
        state!!.firstVisibleItemIndex to state!!.firstVisibleItemScrollOffset
    }

    state = null                                              // (*) clear the reference

    restorationTester.emulateSavedInstanceStateRestore()      // save → dispose → restore

    rule.runOnIdle {
        assertThat(state!!.firstVisibleItemIndex).isEqualTo(index)
        assertThat(state!!.firstVisibleItemScrollOffset).isEqualTo(scrollOffset)
    }
}
  • 4. Drive the state to a non-default value. A test that asserts a default cannot prove restoration occurred. Scroll the list, type into the TextField, toggle the switch.

  • 5. Capture the values to compare against. Read the state inside runOnIdle { } and store them in vals.

  • 6. Set state = null between the capture and emulateSavedInstanceStateRestore(). This is the load-bearing trick. The first composition assigned a value to state; nulling it forces the second state!! access to read whatever the second composition assigns — proving the second composition really happened. Without nulling, the test asserts on the original instance and would pass even if the round-trip silently restored nothing.

  • 7. Call emulateSavedInstanceStateRestore(). The internal flow (cited at StateRestorationTester.android.kt:70-77) is three runOnIdle blocks: saveStateAndDisposeChildren, emitChildrenWithRestoredState, then a no-op block to wait for emission.

  • 8. Re-read the state inside runOnIdle and assert equality with the captured values.

Show full SKILL.md (320 more words)Show less

Patterns

Pattern: remember vs rememberSaveable
kotlin
// WRONG
@Test
fun counterIsRestored() {
    val tester = StateRestorationTester(rule)
    var counter: MutableState<Int>? = null
    tester.setContent {
        counter = remember { mutableStateOf(0) }              // <-- not saveable
        Text("${counter!!.value}")
    }
    rule.runOnIdle { counter!!.value = 7 }
    counter = null
    tester.emulateSavedInstanceStateRestore()
    rule.runOnIdle { assertThat(counter!!.value).isEqualTo(7) }   // FAILS: 0
}
// WRONG because: plain remember is dropped on dispose. The KDoc states "state stored via
// regular state() or remember() will be lost" (StateRestorationTester.android.kt:67-68).
kotlin
// RIGHT
@Test
fun counterIsRestored() {
    val tester = StateRestorationTester(rule)
    var counter: MutableState<Int>? = null
    tester.setContent {
        counter = rememberSaveable { mutableStateOf(0) }      // <-- saveable
        Text("${counter!!.value}")
    }
    rule.runOnIdle { counter!!.value = 7 }
    counter = null
    tester.emulateSavedInstanceStateRestore()
    rule.runOnIdle { assertThat(counter!!.value).isEqualTo(7) }
}
Pattern: rule.setContent vs restorationTester.setContent
kotlin
// WRONG
@Test
fun stateIsRestored() {
    val tester = StateRestorationTester(rule)
    rule.setContent { /* … */ }                               // <-- bypasses the tester
    tester.emulateSavedInstanceStateRestore()                 // throws
}
// WRONG because: emulateSavedInstanceStateRestore checks `registry != null` and otherwise
// throws IllegalStateException("setContent should be called first!")
// (StateRestorationTester.android.kt:71). The injection only happens via tester.setContent.
kotlin
// RIGHT
@Test
fun stateIsRestored() {
    val tester = StateRestorationTester(rule)
    tester.setContent { /* … */ }
    tester.emulateSavedInstanceStateRestore()
}
Pattern: re-reading the same instance vs nulling between phases
kotlin
// WRONG
@Test
fun listScrollIsRestored() {
    val tester = StateRestorationTester(rule)
    lateinit var state: LazyListState
    tester.setContent { state = rememberLazyListState(); /* list */ }
    rule.onNodeWithTag(LazyListTag).performScrollToIndex(5)
    val captured = rule.runOnIdle { state.firstVisibleItemIndex }
    tester.emulateSavedInstanceStateRestore()
    rule.runOnIdle { assertThat(state.firstVisibleItemIndex).isEqualTo(captured) }
}
// WRONG because: `state` still points at the FIRST composition's instance. The assertion
// passes even if the second composition silently created a fresh state and restored nothing.
// Use a nullable var and null it between phases to force the second access to read from the
// post-restoration composition.
kotlin
// RIGHT
@Test
fun listScrollIsRestored() {
    val tester = StateRestorationTester(rule)
    var state: LazyListState? = null
    tester.setContent { state = rememberLazyListState(); /* list */ }
    rule.onNodeWithTag(LazyListTag).performScrollToIndex(5)
    val captured = rule.runOnIdle { state!!.firstVisibleItemIndex }
    state = null                                              // <-- forces re-read
    tester.emulateSavedInstanceStateRestore()
    rule.runOnIdle { assertThat(state!!.firstVisibleItemIndex).isEqualTo(captured) }
}
Pattern: 1 MB Bundle cap
kotlin
// WRONG
@Test
fun megaListSurvives() {
    val tester = StateRestorationTester(rule)
    tester.setContent {
        rememberSaveable { ByteArray(2 * 1024 * 1024) }       // 2 MB
    }
    tester.emulateSavedInstanceStateRestore()                 // throws IllegalStateException
}
// WRONG because: platformEncodeDecode in StateRestorationTester.android.kt:163 enforces
// `check(bytes.size <= 1024 * 1024) { "Bundle exceeds maximum size (1 MB): ${bytes.size} bytes." }`
// The same cap applies on real devices via Binder transaction limits.
kotlin
// RIGHT — keep saved state small. Persist large data via Room/DataStore, save only an id.
@Test
fun megaListSurvives() {
    val tester = StateRestorationTester(rule)
    tester.setContent {
        rememberSaveable { largeRowsId }                       // a stable key, not the data
    }
    tester.emulateSavedInstanceStateRestore()
}

Mandatory rules

  • MUST call restorationTester.setContent { } (NOT rule.setContent { }) for the round-trip to work.
  • MUST declare the state reference as a nullable var ... = null and reassign to null between the capture and emulateSavedInstanceStateRestore(). The assignment forces the second !! access to read the post-restoration composition.
  • MUST use rememberSaveable { … } (or another SaveableStateRegistry integration) for any state expected to survive. Plain remember and mutableStateOf not behind rememberSaveable ARE LOST. Cited at StateRestorationTester.android.kt:67-68.
  • MUST keep the saved Bundle under 1 MB. The check is at StateRestorationTester.android.kt:163.
  • MUST NOT treat emulateSavedInstanceStateRestore() as a stand-in for Activity recreation, configuration change, or process death. The KDoc explicitly says "It is not testing the integration with any other life cycles or Activity callbacks." (StateRestorationTester.android.kt:40-41).
  • MUST NOT combine this skill with createEmptyComposeRule() — that rule is ComposeTestRule, not ComposeContentTestRule, so the constructor will not compile.
  • PREFERRED: drive the state to a non-default value (scroll, type, toggle) before capturing — a test that asserts on the default value cannot prove restoration occurred.
  • PREFERRED: read the captured values via rule.runOnIdle { … } and assert equality, not identity.

Verification

  • The test constructs StateRestorationTester(rule) once and calls only restorationTester.setContent { … }.
  • The hoisted state is var state: T? = null, NOT lateinit var or non-null var state: T.
  • The test drives the state to a non-default value before capturing.
  • Capture happens inside rule.runOnIdle { … } and the result is stored in a val.
  • state = null appears between the capture and restorationTester.emulateSavedInstanceStateRestore().
  • All persisted state uses rememberSaveable { … }. No plain remember is expected to survive.
  • The total saved size is comfortably under 1 MB. Large blobs are excluded; only ids/keys are saved.
  • The test does NOT also assume Activity recreation behaviors (callbacks, ViewModel rebind, etc.).

References

© 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

Files

Just SKILL.md in compose/patterns/testing-state-restoration of skydoves/android-testing-skills.

Open the folder on GitHubat commit 8665ed5

Compare with similar skills

Testing State Restoration 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.

Testing State Restoration compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Testing State Restoration this skillskydoves/android-testing-skills333—~3.5kAutomated safety check: PassApache-2.0
React Native Best Practicesvercel-labs/openreview1.7k17 repos~1.1kAutomated safety check: PassMIT
Swiftui Protwostraws/SwiftUI-Agent-Skill5.2k2 repos~1.5kAutomated safety check: PassMIT
Kortix Brandkortix-ai/suna20k—~4kAutomated safety check: PassCustom licence
Ip As LogoKartikLabhshetwar/better-shot2.4k1 repos~4.3kAutomated safety check: PassMIT
Compose Multiplatform Patternsmonta-app/ocpp-emulator1805 repos~2kAutomated safety check: PassApache-2.0

Similar skills

  • React Native Best Practices

    vercel-labs/openreview

    Official

    A prioritized rule set for React Native and Expo apps covering list performance, animation, navigation, UI patterns, state, rendering, monorepos and configuration.

    1.7k GitHub starsUsed in 17 repos~1.1k tokens
    MobileAuto-check passed
  • Swiftui Pro

    twostraws/SwiftUI-Agent-Skill

    Comprehensively reviews SwiftUI code for best practices on modern APIs, maintainability, and performance.

    5.2k GitHub starsUsed in 2 repos~1.5k tokens
    MobileAuto-check passed
  • Kortix Brand

    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.

    20k GitHub stars~4k tokensUpdated today
    MobileAuto-check passed
  • Ip As Logo

    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.

    2.4k GitHub starsUsed in 1 repo~4.3k tokens
    MobileAuto-check passed
  • 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.

    180 GitHub starsUsed in 5 repos~2k tokens
    MobileAuto-check passed
  • Aso Appstore Screenshots

    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.

    1.8k GitHub starsUsed in 1 repo~9.6k tokens
    MobileAuto-check passed

More from skydoves/android-testing-skills

All 50 skills in this repo
  • Asserting Bounds And Dimensions

    skydoves/android-testing-skills

    A skill your agent uses to verify Compose layout measurements from a UI test using assertWidthIsEqualTo, assertHeightIsEqualTo, assertWidthIsAtLeast, assertHeightIsAtLeast…

    333 GitHub stars~3.3k tokensUpdated 4 mo ago
    Auto-check passed
  • Asserting Node State And Text

    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…

    333 GitHub stars~3.6k tokensUpdated 4 mo ago
    Auto-check passed
  • Capturing Preview Screenshots In CI

    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.

    333 GitHub stars~4.5k tokensUpdated 4 mo ago
    Auto-check: notes
  • Capturing Screenshots And Screenrecord

    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.

    333 GitHub stars~3.7k tokensUpdated 4 mo ago
    Auto-check passed
  • Choosing Test Rule Vs Runtest

    skydoves/android-testing-skills

    A skill your agent uses to pick the correct Compose UI test entry point.

    333 GitHub stars~4.5k tokensUpdated 4 mo ago
    Auto-check passed
  • Choosing What To Test

    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…

    333 GitHub stars~4.6k tokensUpdated 4 mo ago
    Auto-check passed

Categories

Questions about Testing State Restoration

What does Testing State Restoration do?

A skill your agent uses to test rememberSaveable round-trips with StateRestorationTester, the only supported tool for proving Compose state survives process death and configuration change. Testing State Restoration is an agent skill from skydoves/android-testing-skills. Use this skill to test rememberSaveable round-trips with StateRestorationTester, the only supported tool for proving Compose state survives process death and configuration change.

When should I use Testing State Restoration?

Testing State Restoration fits situations like: test rememberSaveable round-trips with StateRestorationTester; the only supported tool for proving Compose state survives process death and configuration change; the developer asks how do I test rememberSaveable; test state survives rotation.

How do I install Testing State Restoration in Claude Code?

Run `npx skills add skydoves/android-testing-skills --skill testing-state-restoration -a claude-code`. Or copy the skill folder (compose/patterns/testing-state-restoration in skydoves/android-testing-skills) into .claude/skills/testing-state-restoration in your project. Claude Code loads it when a task matches its description.

How do I install Testing State Restoration in Codex?

Run `npx skills add skydoves/android-testing-skills --skill testing-state-restoration -a codex`. Or copy the skill folder (compose/patterns/testing-state-restoration in skydoves/android-testing-skills) into .agents/skills/testing-state-restoration in your project. Codex loads it when a task matches its description.

Can I use Testing State Restoration in Cursor, Gemini CLI or GitHub Copilot?

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 testing-state-restoration -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/testing-state-restoration, .gemini/skills/testing-state-restoration, .github/skills/testing-state-restoration and .opencode/skills/testing-state-restoration in your project.

What does Testing State Restoration need to run?

SKILL.md names no scripts, command-line tools or credentials: Testing State Restoration is instructions for the agent only.

Does Testing State Restoration access the network?

SKILL.md names 1 domain. As links in the text: developer.android.com. This is read from the text; nothing was executed.

Is Testing State Restoration safe to install?

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.

What licence does Testing State Restoration use?

Testing State Restoration 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.

How many tokens does Testing State Restoration use?

About 3.5k 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.

What are the alternatives to Testing State Restoration?

Skills that share tags, products or a category with Testing State Restoration: 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.

Who maintains Testing State Restoration?

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.