Ksafe
ioannisa/KSafe
Required before any reply that touches KSafe (by ksafe(...), ksafe.get/put, :ksafe-compose, :ksafe-biometrics), even a 'can KSafe do X?' question or a one-line change that looks like plain Kotlin.
A skill your agent uses when building one shared Compose UI in Kotlin across Android, iOS, and desktop — commonMain @Composables, expect/actual, source-set placement, native interop, multiplatform…
$ npx skills add ericrisco/rsc-harness --skill compose-multiplatform -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install ericrisco/rsc-harness compose-multiplatform --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/ericrisco/rsc-harness.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/compose-multiplatform .claude/skills/compose-multiplatform && 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 "compose-multiplatform" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/compose-multiplatform into .claude/skills/compose-multiplatform/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "compose-multiplatform", 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/ericrisco/rsc-harness/tree/main/skills/compose-multiplatformType 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 ericrisco/rsc-harness --skill compose-multiplatform -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install ericrisco/rsc-harness compose-multiplatform --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/compose-multiplatform .agents/skills/compose-multiplatform && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "compose-multiplatform" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/compose-multiplatform into .agents/skills/compose-multiplatform/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "compose-multiplatform", 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 ericrisco/rsc-harness --skill compose-multiplatform -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install ericrisco/rsc-harness compose-multiplatform --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/compose-multiplatform .cursor/skills/compose-multiplatform && 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 "compose-multiplatform" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/compose-multiplatform into .cursor/skills/compose-multiplatform/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "compose-multiplatform", 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/ericrisco/rsc-harness.git --path skills/compose-multiplatform--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 ericrisco/rsc-harness --skill compose-multiplatform -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install ericrisco/rsc-harness compose-multiplatform --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/compose-multiplatform .gemini/skills/compose-multiplatform && 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 "compose-multiplatform" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/compose-multiplatform into .gemini/skills/compose-multiplatform/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "compose-multiplatform", 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 ericrisco/rsc-harness compose-multiplatformInstalls 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 ericrisco/rsc-harness --skill compose-multiplatform -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/compose-multiplatform .github/skills/compose-multiplatform && 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 "compose-multiplatform" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/compose-multiplatform into .github/skills/compose-multiplatform/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "compose-multiplatform", 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 ericrisco/rsc-harness --skill compose-multiplatform -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install ericrisco/rsc-harness compose-multiplatform --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/compose-multiplatform .opencode/skills/compose-multiplatform && 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 "compose-multiplatform" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/compose-multiplatform into .opencode/skills/compose-multiplatform/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "compose-multiplatform", 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.
compose-multiplatformA skill your agent uses when building one shared Compose UI in Kotlin across Android, iOS, and desktop — commonMain @Composables, expect/actual, source-set placement, native interop, multiplatform…
Compose Multiplatform is an agent skill from ericrisco/rsc-harness. Use when building one shared Compose UI in Kotlin across Android, iOS, and desktop — commonMain @Composables, expect/actual, source-set placement, native interop, multiplatform ViewModel/navigation/Koin. NOT a single-platform native build (that is kotlin-android / swift-ios), and NOT Dart/Flutter cross-platform UI (that is flutter).
Its SKILL.md is about 2.7k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files, including scripts and reference files (for example `evals/README.md`, `evals/cases.yaml` and `references/ios-interop.md`).
It sits in Mobile, covering Android development, Cross-platform mobile apps and iOS development. It works with Jetpack Compose, Android, iOS and Kotlin. The repository describes itself as: Your agent invents things because it has no memory, and can't touch your database because it has no arms. rsc is the meta-harness that gives it both, plus the trade to know the… The licence is MIT.
Read from SKILL.md and the folder at commit 92fde8f. 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.
Ships 1 file in scripts/ (Shell), which the agent can run.
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From 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.
Compose Multiplatform loads about 2.7k tokens when it runs, and up to ~4.5k if it reads all its reference files. Until then it costs about 89 tokens; SKILL.md has 1,008 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); the scripts in this folder are not scanned.
The full file from ericrisco/rsc-harness at commit 92fde8f, republished under its MIT licence (© ericrisco). 1,008 words, ~2,670 tokens.
.claude/skills/compose-multiplatform/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.You write one Compose UI tree in commonMain and let each platform be a thin host. The whole discipline is one sentence: common by default, platform by exception. Every line you put in commonMain ships to Android, iOS, and desktop unchanged; every line you put in a platform source set is a deliberate exception you should be able to justify.
Pin these or the K2 compiler bites you. Verify against current docs before locking a project — these are the floors, not opinions.
jpackage packaging).This is the question you answer dozens of times a day. Default to the leftmost column that compiles.
| Source set | Put here | Concrete example | Never here |
|---|---|---|---|
commonMain | Shared @Composables, ViewModels, business logic, common interfaces, expect declarations | @Composable fun GreetingScreen(), expect fun platformName(): String | android.*, platform.UIKit, java.awt, androidx.activity |
androidMain | Activity, actual using Android Context/Build | class MainActivity : ComponentActivity | iOS/desktop-only APIs |
iosMain | ComposeUIViewController factory, actual via cinterop/platform.* | fun MainViewController() = ComposeUIViewController { App() } | android.* |
desktopMain | application {} window, Swing interop | application { Window(::exitApplication) { App() } } | mobile-only APIs |
wasmJsMain (Beta) | Web entry point | ComposeViewport(document.body!!) { App() } | anything you can't ship as Beta |
Why this matters: a platform import in commonMain breaks the build for every other target, and the error surfaces in the iOS link step, far from the offending line. Keep commonMain import-clean.
The current default KMP layout (announced May 2026, aligned with AGP 9.0) is a dedicated shared KMP library module + per-platform app modules, not the old single composeApp:
my-app/
shared/ # KMP library: commonMain holds the Compose UI tree
src/
commonMain/ # @Composables, ViewModels, expect declarations, DI
androidMain/ # actual impls using android.*
iosMain/ # actual impls + ComposeUIViewController
desktopMain/ # actual impls + application {} window
wasmJsMain/ # web entry (Beta)
androidApp/ # thin Android host -> setContent { App() }
iosApp/ # Xcode project -> embeds the shared framework
desktopApp/ # ./gradlew :desktopApp:run
webApp/ # WasmGC entry (Beta)Split rule: if some screens are native and only some are shared Compose, split into sharedLogic (all platforms) + sharedUI (CMP platforms only). A server-inclusive project adds a root core module. Don't pre-split — start with one shared module and split when a platform genuinely needs native UI.
Source-set hierarchy — commonMain fans out, with intermediate sets where targets share code:
commonMain
├── androidMain
├── desktopMain (jvm)
├── wasmJsMain (Beta)
└── iosMain (intermediate)
├── iosArm64
└── iosSimulatorArm64Scaffold a new project with kmp.new or the Kotlin Multiplatform wizard (IntelliJ IDEA 2025.2.2+ / Android Studio Otter 2025.2.1+ with the KMP plugin). Add a shared module to an existing Android app via Android Studio's Shared Module Template.
Minimal version-catalog plugin wiring (full Gradle in references/project-setup.md):
// gradle/libs.versions.toml
[versions]
kotlin = "2.2.20"
compose = "1.11.0"
agp = "9.0.0"
[plugins]
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose" }expect/actual is how you reach a platform API while keeping the call site common. Declare expect in commonMain; provide an actual in every target you compile.
// commonMain
expect fun platformName(): String// androidMain
import android.os.Build
actual fun platformName(): String = "Android ${Build.VERSION.SDK_INT}"// iosMain
import platform.UIKit.UIDevice
actual fun platformName(): String =
UIDevice.currentDevice.systemName + " " + UIDevice.currentDevice.systemVersionRules, each with the reason it exists:
expect needs an actual in every compiled target. An orphan expect is not a warning — it is a hard build failure (often only surfacing on the iOS target), so add the actual per target or remove the target.expect symbol multiplies into N actuals you maintain; expose the smallest function, not a fat class.interface + DI over deep expect trees for anything you want to test or fake. expect class can't be mocked in common tests.// Bad: deep expect class — N actuals, untestable in commonTest
expect class Database {
fun query(sql: String): List<Row>
fun close()
}// Good: common interface, platform impls injected via Koin (fakeable in tests)
interface Database {
fun query(sql: String): List<Row>
fun close()
}
// androidMain/iosMain provide SqliteDatabase implementing Database, bound in a Koin module.You bridge in both directions. Shared Compose embeds native views; native hosts embed shared Compose.
UIKitView / UIKitViewController with a factory lambda.ComposeUIViewController in a UIViewControllerRepresentable.AndroidView for native views; host the tree via setContent { App() } in an Activity.application { Window { App() } }; Swing interop via SwingPanel.Embed a native view through an injected interface, not a raw expect — so the common screen stays platform-agnostic and testable:
// commonMain
interface MapFactory { /* returns a platform map handle */ }
@Composable
fun MapScreen(mapFactory: MapFactory = koinInject()) {
// iosMain provides the actual UIKitView wiring around mapFactory; see references/ios-interop.md
}Full bridge patterns (ComposeUIViewController SwiftUI wrapper, native-view-factory-via-Koin, MapKit/camera, ViewModel lifecycle) live in references/ios-interop.md — read it before writing iOS interop.
androidx.lifecycle.ViewModel works in commonMain. Obtain instances with koin-compose-viewmodel's koinViewModel { } so they survive recomposition. iOS has no built-in ViewModelStoreOwner — tie the VM lifecycle to SwiftUI manually (KMP-ObservableViewModel lets SwiftUI observe Kotlin VMs).initKoin() and call it from the Android Application and from iOS app init:// commonMain
fun initKoin(config: KoinAppDeclaration? = null) = startKoin {
config?.invoke(this)
modules(appModule, platformModule)
}androidx.navigation provides type-safe nav + deep links in commonMain.compose.components.resources generates Res accessors — Res.string.app_name, Res.drawable.logo, fonts — shared across all platforms.androidApp run config (hosts via setContent).iosApp in Xcode, or use the KMP iOS run config in the IDE../gradlew :desktopApp:run; package with ./gradlew :desktopApp:packageDistributionForCurrentOS (needs JDK 17+ for jpackage)../gradlew :webApp:wasmJsBrowserDevelopmentRun.| Anti-pattern | Why it bites | Do instead |
|---|---|---|
android.* / platform.UIKit / java.awt import in commonMain | Breaks the build for every other target, error surfaces far away | expect/actual or inject via a common interface |
expect with no actual for a target | Hard build failure on that target | Add an actual per compiled target or drop the target |
Recreating a ViewModel each recomposition (remember { VM() } wrong) | State loss on every recompose | koinViewModel { } / hoist state |
| Treating Compose Web as production | Web is Beta (1.9), not Stable | Ship Android/iOS/desktop; pilot Web only |
| Kotlin < 2.1.0 with CMP 1.8+ | K2 incompatibility — deps fail to link | Bump to Kotlin 2.2.x |
Deep expect class for testable logic | Can't fake in commonTest | Common interface + Koin-injected platform impl |
Pre-splitting into sharedLogic/sharedUI on day one | Premature complexity, extra Gradle wiring | Start with one shared module; split when a platform needs native UI |
After scaffolding or editing, run scripts/verify.sh <project-dir> (read-only, no Gradle/Xcode needed). It statically checks the structural invariants:
commonMain source set exists;expect in commonMain has a matching actual in some platform source set (catches orphans);org.jetbrains.compose) and a Kotlin version are present, and Kotlin is >= 2.1.0 (K2 floor);commonMain.It exits 0 on a clean or empty target and non-zero only on hard failures.
© ericrisco, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files (scripts, references) in skills/compose-multiplatform of ericrisco/rsc-harness.
Open the folder on GitHubat commit 92fde8f
Compose Multiplatform 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 |
|---|---|---|---|---|---|---|
| Compose Multiplatform this skillericrisco/rsc-harness | 156 | — | ~2.7k | Automated safety check: Pass | MIT | |
| Ksafeioannisa/KSafe | 332 | — | ~17k | Automated safety check: Pass | Apache-2.0 | |
| Developing Mobile Appstelagod/code-abyss | 244 | — | ~258 | Automated safety check: Pass | MIT | |
| Senior Mobileborghei/Claude-Skills | 874 | — | ~1.9k | Automated safety check: Pass | MIT | |
| Mobile Apps Createforcedotcom/sf-skills | 1.1k | — | ~1.4k | Automated safety check: Pass | Apache-2.0 | |
| Mobile App Developertheneoai/awesome-skills | 183 | — | ~2.1k | Automated safety check: Pass | MIT |
ioannisa/KSafe
Required before any reply that touches KSafe (by ksafe(...), ksafe.get/put, :ksafe-compose, :ksafe-biometrics), even a 'can KSafe do X?' question or a one-line change that looks like plain Kotlin.
telagod/code-abyss
Mobile development knowledge reference covering iOS (SwiftUI), Android (Jetpack Compose), React Native, and Flutter.
borghei/Claude-Skills
A skill your agent uses when the user asks to "build a mobile app", "scaffold React Native project", "create SwiftUI views", "set up Jetpack Compose", "optimize mobile performance", "configure Expo…
forcedotcom/sf-skills
The entry point for building any Salesforce native mobile app on iOS or Android.
theneoai/awesome-skills
Elite Mobile App Developer skill with expertise in native iOS (Swift), native Android (Kotlin), and cross-platform (React Native, Flutter).
Drjacky/claude-android-ninja
Build and migrate Android apps with Kotlin, Jetpack Compose, MVVM, Hilt, Room 3 (KSP, SQLiteDriver, Flow/suspend DAOs), Navigation3, and multi-module Gradle.
ericrisco/rsc-harness
A skill your agent uses when designing or analyzing a controlled experiment — falsifiable hypothesis, sample size from an MDE, reading significance/CI/power, CUPED, or rescuing tests that won't go…
ericrisco/rsc-harness
A skill your agent uses when making a web UI conform to WCAG 2.2 Level AA — axe-core or Lighthouse a11y violations, keyboard operability, focus management, ARIA roles/names/live regions, contrast…
ericrisco/rsc-harness
A skill your agent uses when running or fixing paid acquisition on Google or Meta — campaign structure (Performance Max, Demand Gen, Search, Advantage+), platform-fit creative, budget/scaling rules…
ericrisco/rsc-harness
A skill your agent uses when measuring whether an LLM or agent system actually got better and gating merges on it: golden sets, fixing an inflated LLM-as-judge, scoring RAG (faithfulness, contextual…
ericrisco/rsc-harness
A skill your agent uses when a creative goal must become a finished media file: pick and order generative-media models per modality — AI voiceover, image-to-video clips, score — then glue them with…
ericrisco/rsc-harness
A skill your agent uses when instrumenting product or web analytics — GA4/PostHog SDK wiring, event taxonomy, funnels, double-counted events, consent gating, PII scrubbing.
Categories
A skill your agent uses when building one shared Compose UI in Kotlin across Android, iOS, and desktop — commonMain @Composables, expect/actual, source-set placement, native interop, multiplatform…. Compose Multiplatform is an agent skill from ericrisco/rsc-harness. Use when building one shared Compose UI in Kotlin across Android, iOS, and desktop — commonMain @Composables, expect/actual, source-set placement, native interop, multiplatform ViewModel/navigation/Koin.
Compose Multiplatform fits situations like: building one shared Compose UI in Kotlin across Android; desktop — commonMain @Composables; source-set placement; multiplatform ViewModel/navigation/Koin.
Run `npx skills add ericrisco/rsc-harness --skill compose-multiplatform -a claude-code`. Or copy the skill folder (skills/compose-multiplatform in ericrisco/rsc-harness) into .claude/skills/compose-multiplatform in your project. Claude Code loads it when a task matches its description.
Run `npx skills add ericrisco/rsc-harness --skill compose-multiplatform -a codex`. Or copy the skill folder (skills/compose-multiplatform in ericrisco/rsc-harness) into .agents/skills/compose-multiplatform 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 ericrisco/rsc-harness --skill compose-multiplatform -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/compose-multiplatform, .gemini/skills/compose-multiplatform, .github/skills/compose-multiplatform and .opencode/skills/compose-multiplatform in your project.
Going by SKILL.md and its folder, Compose Multiplatform needs a shell for the scripts in its folder. Our summary lists: A Bash shell.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. 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. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Compose Multiplatform is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.7k 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. Its references folder adds about 1.8k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Compose Multiplatform: Ksafe (ioannisa/KSafe, 332 stars), Developing Mobile Apps (telagod/code-abyss, 244 stars), Senior Mobile (borghei/Claude-Skills, 874 stars) and Mobile Apps Create (forcedotcom/sf-skills, 1.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
ericrisco (a GitHub user) maintains it in ericrisco/rsc-harness, which has 156 GitHub stars. The repository holds 229 skills in this directory. The repository was last updated on October 6, 2026.
Source: ericrisco/rsc-harness on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.