Agent skill

Preserving State Across Reloads

by rosuH in rosuH/EasyWatermark

A skill your agent uses to keep Jetpack Compose state alive across HotSwan hot reloads by understanding the three escalating tiers Compose HotSwan uses (tier 1 targeted recomposition, tier 2…

Apache-2.0Auto-check passedMobile

Install Preserving State Across Reloads

skills CLI
$ npx skills add rosuH/EasyWatermark --skill preserving-state-across-reloads -a claude-code

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

GitHub CLI
$ gh skill install rosuH/EasyWatermark preserving-state-across-reloads --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/rosuH/EasyWatermark.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/preserving-state-across-reloads .claude/skills/preserving-state-across-reloads && 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
preserving-state-across-reloads
GitHub stars
1.9k
Used in
1 other repo
Token cost
~2.8k tokens
SKILL.md length
1,110 words
Files
1
Skills in repo
28
Repo updated
First seen
Licence
Apache-2.0

At a glance

A skill your agent uses to keep Jetpack Compose state alive across HotSwan hot reloads by understanding the three escalating tiers Compose HotSwan uses (tier 1 targeted recomposition, tier 2…

  • Works in 5 steps: Read the tier from the tool window after… → If state was lost on tier 2, audit the… → Hoist user-facing transient state into a… → …
  • Tier 2 composition reset
  • SKILL.md covers When to use this skill, When NOT to use this skill, Prerequisites and The three tiers, plus 5 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Preserving State Across Reloads is an agent skill from rosuH/EasyWatermark. Use this skill to keep Jetpack Compose state alive across HotSwan hot reloads by understanding the three escalating tiers Compose HotSwan uses (tier 1 targeted recomposition, tier 2 composition reset, tier 3 Activity.recreate) and choosing edits and state holders that stay inside tier 1 where scroll position, lazy items, dialog state, and per-composable remember values all survive. Explains which edits force escalation, which state holders survive each tier, and how to hoist transient UI state when the iteration…

Its SKILL.md is about 2.8k 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 and Refactoring. It works with Jetpack Compose. The repository describes itself as: 🔒 🖼 Securely, easily add a watermark to your sensitive photos. 安全、简单地为你的敏感照片添加水印,防止被人泄露、利用. The licence is Apache-2.0.

When your agent uses it

  • Tier 2 composition reset
  • Tier 3 Activity.recreate) and choosing edits and state holders that stay inside tier 1 where scroll position
  • Per-composable remember values all survive
  • The developer says scroll jumped to top after a hot reload

Example prompts

  • “scroll jumped to top after a hot reload”
  • “lost dialog state”
  • “lazy column re-fetched”
  • “/preserving-state-across-reloads”

Workflow steps

5 steps, taken from the step headings in SKILL.md.

  1. Read the tier from the tool window after every reload
  2. If state was lost on tier 2, audit the offended state holder
  3. Hoist user-facing transient state into a ViewModel for long iterations
  4. Avoid theme and root CompositionLocal mutations during a fast loop
  5. Avoid staticCompositionLocalOf for any value the developer is editing

What it can do on your machine

Read from SKILL.md and the folder at commit 61223db. 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
    • github.com
    • plugins.jetbrains.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

Preserving State Across Reloads loads about 2.8k tokens when it runs. Until then it costs about 221 tokens; SKILL.md has 1,110 words of instructions outside code blocks.

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

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 rosuH/EasyWatermark at commit 61223db, republished under its Apache-2.0 licence (© rosuH). 1,110 words, ~2,846 tokens.

Download SKILL.mdSave it as .claude/skills/preserving-state-across-reloads/SKILL.md (or your agent's skills folder).
name
preserving-state-across-reloads
description
Use this skill to keep Jetpack Compose state alive across HotSwan hot reloads by understanding the three escalating tiers Compose HotSwan uses (tier 1 targeted recomposition, tier 2 composition reset, tier 3 Activity.recreate) and choosing edits and state holders that stay inside tier 1 where scroll position, lazy items, dialog state, and per-composable remember values all survive. Explains which edits force escalation, which state holders survive each tier, and how to hoist transient UI state when the iteration loop must escalate. Use when the developer says "scroll jumped to top after a hot reload", "lost dialog state", "lazy column re-fetched", "tab selection reset", asks why HotSwan reload escalated to tier 2 or 3, plans a refactor and needs to know which scope it touches, or wants to know which state holders survive composition reset.
license
Apache-2.0. See LICENSE for complete terms.
metadata.author
Jaewoong Eum (skydoves)
metadata.keywords
jetpack-compose, performance, hot-reload, hotswan, state-preservation, remember-saveable, recomposition, composition-reset

Preserving State Across Reloads: keep edits inside HotSwan tier 1

Compose HotSwan applies every hot reload through three escalating tiers. Tier 1 (targeted recomposition) preserves the most: scroll position, navigation back stack, remember and rememberSaveable values, ViewModel state, lazy layout items, dialog and bottom sheet state. Tier 2 (composition reset) disposes and recreates compositions, dropping per-composable remember. Tier 3 (Activity.recreate()) restarts the Activity and only state held by ViewModel or SavedInstanceState survives.

The iteration loop is fastest and least surprising when every reload stays inside tier 1. This skill covers which edits trigger which tier, which state holders survive each tier, and how to hoist transient UI state when an edit must escalate.

When to use this skill

  • The developer reports "scroll jumped to top after a hot reload", "lost dialog state", "lazy column re-fetched", or "tab selection reset to zero".
  • The developer is about to refactor a composable and wants to know which recomposition scope the change touches.
  • The HotSwan tool window status shows a tier 2 or tier 3 reload and the developer wants to understand why it escalated.
  • The developer asks which state holders survive Activity.recreate() versus a composition reset.
  • The user mentions "tier 1", "tier 2", "tier 3", "composition reset", "HotSwan state preservation", or "rememberSaveable across reload".

When NOT to use this skill

  • The change was rejected as a schema violation entirely (added a parameter, changed a constructor, added a new resource ID) and HotSwan fell back to a full incremental build. See ../understanding-hot-reload-limits/SKILL.md.
  • HotSwan is not installed or the watcher is not running. See ../setting-up-compose-hotswan/SKILL.md.
  • The developer wants an AI agent to drive the loop autonomously. See ../iterating-with-ai-and-mcp/SKILL.md.
  • The recomposition itself is too wide independent of hot reload (a parent invalidating a whole subtree on every state tick). Diagnose with ../../recomposition/debugging-recompositions/SKILL.md first.

Prerequisites

  • Compose HotSwan installed and WATCHING against the running app. Setup lives in ../setting-up-compose-hotswan/SKILL.md.
  • Familiarity with Compose recomposition scopes; cross-link ../../recomposition/debugging-recompositions/SKILL.md for the underlying mechanics.
  • Familiarity with rememberSaveable for state that must survive process death and (in this context) composition reset.

The three tiers

TierMechanismPreservesLosesTriggered when
1. Targeted recompositionrecomposes only the affected scopes in placenavigation back stack, scroll position, remember, rememberSaveable, ViewModel, lazy layout items, dialog and bottom sheet statenothingsimple body change inside one composable scope
2. Composition resetdispose and recreate all compositions from scratchActivity, ViewModel, navigation (via NavController), rememberSaveable (depends on retention)per-composable remember values not retained by a Saveable, scroll position not held by a saveable state holdertier 1 unavailable (theme change, root-scope structural change)
3. Activity.recreate()recreate the entire ActivityViewModel, SavedInstanceStatescroll, transient dialog state, anything not savedcomposition fails or schema mismatch detected

The tier that ran is reported in the HotSwan tool window status after every reload. Read it after each edit to confirm the loop stayed where it was supposed to.

Workflow

1. Read the tier from the tool window after every reload

The HotSwan tool window prints the tier (1, 2, or 3) for each reload. If the developer expected tier 1 and the status reports tier 2 or 3, the edit touched a wider scope than intended. Read the tier before deciding whether the lost state is a configuration problem or expected behaviour.

2. If state was lost on tier 2, audit the offended state holder

Tier 2 disposes per-composable remember blocks. Walk the composable that lost state and convert its local remember to rememberSaveable for any value that the developer wants to keep across reloads that may escalate. This is the single highest-leverage change for a HotSwan-driven iteration loop.

3. Hoist user-facing transient state into a ViewModel for long iterations

When the developer is iterating on a screen for a long stretch and individual edits keep escalating to tier 2 or tier 3, hoist transient UI state (selected tab, expanded item, scroll position, dialog open) into a ViewModel. ViewModel survives all three tiers, so the iteration loop never loses the workbench state.

Show full SKILL.md (450 more words)Show less
4. Avoid theme and root CompositionLocal mutations during a fast loop

Editing a value used by MaterialTheme, or by any staticCompositionLocalOf, invalidates the root content lambda of the corresponding CompositionLocalProvider. HotSwan cannot scope that to a single recomposition target and escalates to tier 2. Move the colour, dimension, or typography under iteration into a local override on the composable being tuned, then move it back into the theme once the value is final.

5. Avoid staticCompositionLocalOf for any value the developer is editing

Even outside theme, any value provided through staticCompositionLocalOf invalidates the entire content of the provider on change. Use compositionLocalOf (which tracks reads) for values that may change during a hot-reload session.

Patterns

Pattern: local remember lost on tier 2
kotlin
// WRONG (for tier 2 reloads)
@Composable
fun TabScreen() {
    var selected by remember { mutableIntStateOf(0) }
    Tabs(selected = selected, onSelected = { selected = it })
}
// WRONG because: a tier 2 composition reset disposes remember; the selected tab snaps back to 0 after a reload that escalates.
kotlin
// RIGHT
@Composable
fun TabScreen() {
    var selected by rememberSaveable { mutableIntStateOf(0) }
    Tabs(selected = selected, onSelected = { selected = it })
}
Pattern: theme colour edit forces tier 2
kotlin
// WRONG (forces tier 2)
val LightColors = lightColorScheme(primary = Color(0xFFEE0044))
// WRONG because: editing a top-level colour used by MaterialTheme invalidates the root CompositionLocal; the reload escalates to tier 2 and disposes per-composable remember.
kotlin
// RIGHT (stays in tier 1)
@Composable
fun PrimaryButton(text: String) {
    Button(
        onClick = {},
        colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFEE0044)),
    ) { Text(text) }
}

Move the literal back into the theme once the visual value is final. The escalation only matters during the fast iteration loop.

Pattern: lazy list scroll position survives tier 2 and tier 3
kotlin
// RIGHT
@Composable
fun Feed(items: List<Item>) {
    val state = rememberLazyListState()
    LazyColumn(state = state) {
        items(items, key = { it.id }) { Item(it) }
    }
}

rememberLazyListState is backed by a Saveable, so the scroll position survives composition reset and Activity recreation. Combined with stable keys, the visible items stay rendered after a reload that escalates.

Pattern: hoist iteration-critical state into a ViewModel
kotlin
// RIGHT
class FeedViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(FeedState())
    val uiState: StateFlow<FeedState> = _uiState.asStateFlow()
}

@Composable
fun FeedScreen(viewModel: FeedViewModel) {
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    Feed(state.items)
}

ViewModel outlives every tier of HotSwan reload (and configuration changes generally), so screen-level workbench state stays untouched even on tier 3.

Pattern: avoid staticCompositionLocalOf for values under iteration
kotlin
// WRONG (every edit forces tier 2)
val LocalAccent = staticCompositionLocalOf { Color.Red }
// WRONG because: changing the provided value invalidates the entire content of CompositionLocalProvider; HotSwan cannot scope that and escalates.
kotlin
// RIGHT
val LocalAccent = compositionLocalOf { Color.Red }

compositionLocalOf tracks reads and only invalidates the actual readers; HotSwan can keep the reload inside tier 1.

Mandatory rules

  • MUST prefer rememberSaveable over remember for any UI state the developer wants to keep across hot reloads that may escalate.
  • MUST keep theme and root CompositionLocal edits out of a fast iteration session; they force tier 2.
  • MUST NOT assume tier 1 always runs. Read the tier reported in the HotSwan tool window after every reload.
  • MUST NOT use staticCompositionLocalOf for values the developer is actively editing during a hot reload session.
  • PREFERRED: hoist transient UI state (selected tab, expanded item, dialog open, scroll position) into a ViewModel when the iteration loop is long.
  • PREFERRED: rely on rememberLazyListState (and the matching grid / pager state holders) for scroll and visible-item state because they are saveable by default.

Verification

  • Editing a composable body keeps scroll position and dialog state, and the tool window reports tier 1
  • Editing a MaterialTheme colour escalates to tier 2 (status confirms the tier)
  • State backed by rememberSaveable survives a tier 2 composition reset
  • State backed by a ViewModel survives a tier 3 Activity.recreate()
  • rememberLazyListState keeps scroll position after a tier 2 reload

References

© rosuH, 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 .agents/skills/preserving-state-across-reloads of rosuH/EasyWatermark.

Open the folder on GitHubat commit 61223db

Used in 1 other repository

We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in rosuH/EasyWatermark, which our catalogue first saw on October 7, 2026.

Compare with similar skills

Preserving State Across Reloads 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.

Preserving State Across Reloads compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Preserving State Across Reloads this skillrosuH/EasyWatermark1.9k1 repos~2.8kAutomated safety check: PassApache-2.0
Compose UIMoustachauve/WLED-Android1693 repos~676Automated safety check: PassApache-2.0
Task Workflowikarenkov/Modo343—~2.4kAutomated safety check: PassNone
Compose Multiplatform Patternsmonta-app/ocpp-emulator1805 repos~2kAutomated safety check: PassApache-2.0
Android Developmentdpconde/claude-android-skill336—~1.7kAutomated safety check: PassMIT
Benchmarkandroidx/androidx6.1k—~1.1kAutomated safety check: PassApache-2.0

Similar skills

  • Compose UI

    Moustachauve/WLED-Android

    Best practices for building UI with Jetpack Compose, focusing on state hoisting, detailed performance optimizations, and theming.

    169 GitHub starsUsed in 3 repos~676 tokens
    MobileAuto-check passed
  • Task Workflow

    ikarenkov/Modo

    Spec-driven workflow for non-trivial work. An agent skill from ikarenkov/Modo.

    343 GitHub stars~2.4k tokensUpdated 3 mo ago
    DevelopmentAuto-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
  • Android Development

    dpconde/claude-android-skill

    Create production-quality Android applications following Google's official architecture guidance and NowInAndroid best practices.

    336 GitHub stars~1.7k tokensUpdated 10 mo ago
    MobileAuto-check passed
  • Benchmark

    androidx/androidx

    Benchmarking and improving the performance of Jetpack Compose.

    6.1k GitHub stars~1.1k tokensUpdated yesterday
    MobileAuto-check passed
  • Mobile Android Design

    openvetta/open-vetta

    Master Material Design 3 and Jetpack Compose patterns for building native Android apps.

    290 GitHub starsUsed in 3 repos~950 tokens
    MobileAuto-check passed

More from rosuH/EasyWatermark

All 23 skills in this repo
  • Deferring State Reads

    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…

    1.9k GitHub starsUsed in 1 repo~3.8k tokens
    Auto-check passed
  • Diagnosing Compose Stability

    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).

    1.9k GitHub starsUsed in 1 repo~3.3k tokens
    Auto-check passed
  • Generating Baseline Profiles

    rosuH/EasyWatermark

    A skill your agent uses to generate and measure Jetpack Compose Baseline Profiles end-to-end with the AGP 8.2+ Baseline Profile Generator module and the Macrobenchmark harness.

    1.9k GitHub starsUsed in 1 repo~5k tokens
    Auto-check passed
  • Migrating To Modifier Node

    rosuH/EasyWatermark

    A skill your agent uses to author new custom Jetpack Compose modifiers and migrate legacy ones from Modifier.composed { } to Modifier.Node + ModifierNodeElement<T.

    1.9k GitHub starsUsed in 1 repo~5k tokens
    Auto-check passed
  • Stabilizing Compose Types

    rosuH/EasyWatermark

    A skill your agent uses to fix unstable Jetpack Compose types once a stability diagnosis has identified them.

    1.9k GitHub starsUsed in 1 repo~4.4k tokens
    Auto-check passed
  • A skill your agent uses to explain why the Compose compiler classified a class or composable parameter as stable, runtime, unknown, or unstable.

    1.9k GitHub starsUsed in 1 repo~4.3k tokens
    Auto-check passed

Works with

Categories

Questions about Preserving State Across Reloads

What does Preserving State Across Reloads do?

A skill your agent uses to keep Jetpack Compose state alive across HotSwan hot reloads by understanding the three escalating tiers Compose HotSwan uses (tier 1 targeted recomposition, tier 2…. Preserving State Across Reloads is an agent skill from rosuH/EasyWatermark.recreate) and choosing edits and state holders that stay inside tier 1 where scroll position, lazy items, dialog state, and per-composable remember values all survive.

When should I use Preserving State Across Reloads?

Preserving State Across Reloads fits situations like: tier 2 composition reset; tier 3 Activity.recreate) and choosing edits and state holders that stay inside tier 1 where scroll position; per-composable remember values all survive; the developer says scroll jumped to top after a hot reload.

How do I install Preserving State Across Reloads in Claude Code?

Run `npx skills add rosuH/EasyWatermark --skill preserving-state-across-reloads -a claude-code`. Or copy the skill folder (.agents/skills/preserving-state-across-reloads in rosuH/EasyWatermark) into .claude/skills/preserving-state-across-reloads in your project. Claude Code loads it when a task matches its description.

How do I install Preserving State Across Reloads in Codex?

Run `npx skills add rosuH/EasyWatermark --skill preserving-state-across-reloads -a codex`. Or copy the skill folder (.agents/skills/preserving-state-across-reloads in rosuH/EasyWatermark) into .agents/skills/preserving-state-across-reloads in your project. Codex loads it when a task matches its description.

Can I use Preserving State Across Reloads 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 rosuH/EasyWatermark --skill preserving-state-across-reloads -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/preserving-state-across-reloads, .gemini/skills/preserving-state-across-reloads, .github/skills/preserving-state-across-reloads and .opencode/skills/preserving-state-across-reloads in your project.

What does Preserving State Across Reloads need to run?

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

Does Preserving State Across Reloads access the network?

SKILL.md names 3 domains. As links in the text: developer.android.com, github.com and plugins.jetbrains.com. This is read from the text; nothing was executed.

Is Preserving State Across Reloads 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 Preserving State Across Reloads use?

Preserving State Across Reloads 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 Preserving State Across Reloads use?

About 2.8k tokens (SKILL.md is roughly 11k 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 Preserving State Across Reloads?

Skills that share tags, products or a category with Preserving State Across Reloads: Compose UI (Moustachauve/WLED-Android, 169 stars), Task Workflow (ikarenkov/Modo, 343 stars), Compose Multiplatform Patterns (monta-app/ocpp-emulator, 180 stars) and Android Development (dpconde/claude-android-skill, 336 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Preserving State Across Reloads?

rosuH (a GitHub user) maintains it in rosuH/EasyWatermark, which has 1,895 GitHub stars. The repository holds 28 skills in this directory. The repository was last updated on October 10, 2026.

Source: rosuH/EasyWatermark on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.