Compose UI
Moustachauve/WLED-Android
Best practices for building UI with Jetpack Compose, focusing on state hoisting, detailed performance optimizations, and theming.
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…
$ npx skills add rosuH/EasyWatermark --skill preserving-state-across-reloads -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install rosuH/EasyWatermark preserving-state-across-reloads --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/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-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 "preserving-state-across-reloads" agent skill from https://github.com/rosuH/EasyWatermark/tree/master/.agents/skills/preserving-state-across-reloads into .claude/skills/preserving-state-across-reloads/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "preserving-state-across-reloads", 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/rosuH/EasyWatermark/tree/master/.agents/skills/preserving-state-across-reloadsType 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 rosuH/EasyWatermark --skill preserving-state-across-reloads -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install rosuH/EasyWatermark preserving-state-across-reloads --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rosuH/EasyWatermark.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/preserving-state-across-reloads .agents/skills/preserving-state-across-reloads && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "preserving-state-across-reloads" agent skill from https://github.com/rosuH/EasyWatermark/tree/master/.agents/skills/preserving-state-across-reloads into .agents/skills/preserving-state-across-reloads/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "preserving-state-across-reloads", 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 rosuH/EasyWatermark --skill preserving-state-across-reloads -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install rosuH/EasyWatermark preserving-state-across-reloads --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rosuH/EasyWatermark.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/preserving-state-across-reloads .cursor/skills/preserving-state-across-reloads && 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 "preserving-state-across-reloads" agent skill from https://github.com/rosuH/EasyWatermark/tree/master/.agents/skills/preserving-state-across-reloads into .cursor/skills/preserving-state-across-reloads/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "preserving-state-across-reloads", 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/rosuH/EasyWatermark.git --path .agents/skills/preserving-state-across-reloads--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 rosuH/EasyWatermark --skill preserving-state-across-reloads -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install rosuH/EasyWatermark preserving-state-across-reloads --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rosuH/EasyWatermark.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/preserving-state-across-reloads .gemini/skills/preserving-state-across-reloads && 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 "preserving-state-across-reloads" agent skill from https://github.com/rosuH/EasyWatermark/tree/master/.agents/skills/preserving-state-across-reloads into .gemini/skills/preserving-state-across-reloads/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "preserving-state-across-reloads", 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 rosuH/EasyWatermark preserving-state-across-reloadsInstalls 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 rosuH/EasyWatermark --skill preserving-state-across-reloads -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/rosuH/EasyWatermark.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/preserving-state-across-reloads .github/skills/preserving-state-across-reloads && 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 "preserving-state-across-reloads" agent skill from https://github.com/rosuH/EasyWatermark/tree/master/.agents/skills/preserving-state-across-reloads into .github/skills/preserving-state-across-reloads/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "preserving-state-across-reloads", 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 rosuH/EasyWatermark --skill preserving-state-across-reloads -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install rosuH/EasyWatermark preserving-state-across-reloads --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rosuH/EasyWatermark.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/preserving-state-across-reloads .opencode/skills/preserving-state-across-reloads && 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 "preserving-state-across-reloads" agent skill from https://github.com/rosuH/EasyWatermark/tree/master/.agents/skills/preserving-state-across-reloads into .opencode/skills/preserving-state-across-reloads/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "preserving-state-across-reloads", 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.
preserving-state-across-reloadsA 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. 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.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 61223db. 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.complugins.jetbrains.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.
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.
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 rosuH/EasyWatermark at commit 61223db, republished under its Apache-2.0 licence (© rosuH). 1,110 words, ~2,846 tokens.
.claude/skills/preserving-state-across-reloads/SKILL.md (or your agent's skills folder).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.
Activity.recreate() versus a composition reset.../understanding-hot-reload-limits/SKILL.md.../setting-up-compose-hotswan/SKILL.md.../iterating-with-ai-and-mcp/SKILL.md.../../recomposition/debugging-recompositions/SKILL.md first.WATCHING against the running app. Setup lives in ../setting-up-compose-hotswan/SKILL.md.../../recomposition/debugging-recompositions/SKILL.md for the underlying mechanics.rememberSaveable for state that must survive process death and (in this context) composition reset.| Tier | Mechanism | Preserves | Loses | Triggered when |
|---|---|---|---|---|
| 1. Targeted recomposition | recomposes only the affected scopes in place | navigation back stack, scroll position, remember, rememberSaveable, ViewModel, lazy layout items, dialog and bottom sheet state | nothing | simple body change inside one composable scope |
| 2. Composition reset | dispose and recreate all compositions from scratch | Activity, 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 holder | tier 1 unavailable (theme change, root-scope structural change) |
3. Activity.recreate() | recreate the entire Activity | ViewModel, SavedInstanceState | scroll, transient dialog state, anything not saved | composition 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.
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.
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.
ViewModel for long iterationsWhen 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.
CompositionLocal mutations during a fast loopEditing 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.
staticCompositionLocalOf for any value the developer is editingEven 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.
remember lost on tier 2// 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.// RIGHT
@Composable
fun TabScreen() {
var selected by rememberSaveable { mutableIntStateOf(0) }
Tabs(selected = selected, onSelected = { selected = it })
}// 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.// 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.
// 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.
ViewModel// 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.
staticCompositionLocalOf for values under iteration// 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.// RIGHT
val LocalAccent = compositionLocalOf { Color.Red }compositionLocalOf tracks reads and only invalidates the actual readers; HotSwan can keep the reload inside tier 1.
rememberSaveable over remember for any UI state the developer wants to keep across hot reloads that may escalate.CompositionLocal edits out of a fast iteration session; they force tier 2.staticCompositionLocalOf for values the developer is actively editing during a hot reload session.ViewModel when the iteration loop is long.rememberLazyListState (and the matching grid / pager state holders) for scroll and visible-item state because they are saveable by default.MaterialTheme colour escalates to tier 2 (status confirms the tier)rememberSaveable survives a tier 2 composition resetViewModel survives a tier 3 Activity.recreate()rememberLazyListState keeps scroll position after a tier 2 reload/docs/state-preservation)rememberSaveable: https://developer.android.com/develop/ui/compose/state-savingViewModel overview: https://developer.android.com/topic/libraries/architecture/viewmodelCompositionLocal: https://developer.android.com/develop/ui/compose/compositionlocal© 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
Just SKILL.md in .agents/skills/preserving-state-across-reloads of rosuH/EasyWatermark.
Open the folder on GitHubat commit 61223db
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.
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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Preserving State Across Reloads this skillrosuH/EasyWatermark | 1.9k | 1 repos | ~2.8k | Automated safety check: Pass | Apache-2.0 | |
| Compose UIMoustachauve/WLED-Android | 169 | 3 repos | ~676 | Automated safety check: Pass | Apache-2.0 | |
| Task Workflowikarenkov/Modo | 343 | — | ~2.4k | Automated safety check: Pass | None | |
| Compose Multiplatform Patternsmonta-app/ocpp-emulator | 180 | 5 repos | ~2k | Automated safety check: Pass | Apache-2.0 | |
| Android Developmentdpconde/claude-android-skill | 336 | — | ~1.7k | Automated safety check: Pass | MIT | |
| Benchmarkandroidx/androidx | 6.1k | — | ~1.1k | Automated safety check: Pass | Apache-2.0 |
Moustachauve/WLED-Android
Best practices for building UI with Jetpack Compose, focusing on state hoisting, detailed performance optimizations, and theming.
ikarenkov/Modo
Spec-driven workflow for non-trivial work. An agent skill from ikarenkov/Modo.
monta-app/ocpp-emulator
Compose Multiplatform and Jetpack Compose patterns for KMP projects — state management, navigation, theming, performance, and platform-specific UI.
dpconde/claude-android-skill
Create production-quality Android applications following Google's official architecture guidance and NowInAndroid best practices.
androidx/androidx
Benchmarking and improving the performance of Jetpack Compose.
openvetta/open-vetta
Master Material Design 3 and Jetpack Compose patterns for building native Android apps.
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…
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).
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.
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.
rosuH/EasyWatermark
A skill your agent uses to fix unstable Jetpack Compose types once a stability diagnosis has identified them.
rosuH/EasyWatermark
A skill your agent uses to explain why the Compose compiler classified a class or composable parameter as stable, runtime, unknown, or unstable.
Works with
Categories
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.
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.
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.
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.
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.
SKILL.md names no scripts, command-line tools or credentials: Preserving State Across Reloads is instructions for the agent only.
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.
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.
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.
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.
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.
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.