Chisle
The coding-agent plugin that bills 52% of a bare model across 20 live tasks. Terse persona + tool-output compressor + context diet.
Apache 2.0 Kotlin Multiplatform libraries from the Vocabloot app: BackupKit for backup into the user's own cloud, WidgetBridge for home-screen widgets.
Developer toolsKotlin · SwiftGitHub @vaazh-studiosOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Kotlin Multiplatform asset packs, downloaded on first use from the stores: Play Asset Delivery, Apple-hosted Background Assets (iOS 26+), On-Demand Resources (iOS 17 and 18). No server, no hosting bill.
Loading the full README.
Read the full README ↗Built for Vocabloot, the photo vocabulary app for iOS and Android. Part of the Vocabloot open-source libraries.
Kotlin Multiplatform asset packs, downloaded on first use from the app stores themselves: Google Play Asset Delivery on Android, Apple-hosted Background Assets on iOS 26 and later, On-Demand Resources on iOS 17 and 18. The stores host the bytes. No server, no hosting bill.
Games make an app big, and most players never open most of them. Shipping every game's art in the install costs downloads; hosting it yourself costs egress on every new device. Both stores already deliver extra content after install, for free, but each with its own API, states and packaging, and Apple has two systems depending on the iOS version. AssetDropKit gives Kotlin one API over all three, one pack layout, and one integrity check.
AssetPacks.fetch, state, readBytes, remove, with the same PackState names on every store.assetdropkit.json (SHA-256 per file) once per version; a mismatch is removed, fetched once more, then reported as Failed(Corrupt). state() says Ready only after the check.stallTimeoutMillis turns a download that stops moving into Failed(NoNetwork).// libs.versions.toml assetdropkit = { module = "com.vocabloot:assetdropkit", version = "0.1.3" }
// build.gradle.kts (shared) commonMain.dependencies { api(libs.assetdropkit) }
Package each pack once (packaging), then:
// Android (androidMain) // iOS (iosMain); store = the app's AssetDropAdapter
val source = PackSources.default(context, BuildConfig.DEBUG) val source = AppleStoreSource(store = store)
// common
val packs = AssetPacks(source = source, stallTimeoutMillis = 20_000)
when (val state = packs.fetch("postdelivery")) {
PackState.Ready -> {
val glb = packs.readBytes("postdelivery", "town/sedan.glb")
}
is PackState.Failed -> showFallback(state.reason) // NoNetwork, InsufficientStorage, Corrupt, ...
else -> askTheUser() // WaitingForWifi, NeedsPlayConfirmation (Android)
}
Show progress while the pack arrives, and switch to the downloaded art only once it is verified:
@Composable
fun GameIntro(packs: AssetPacks) {
val state by remember { packs.state("postdelivery") }.collectAsState(initial = null)
LaunchedEffect(Unit) { packs.fetch("postdelivery") }
when (val s = state) {
is PackState.Downloading -> ProgressLine(s.bytes, s.totalBytes)
PackState.Ready -> PlayWithPackArt() // Ready means checked against the manifest
is PackState.Failed -> PlayWithBuiltInArt() // and fetch again next time
else -> Unit
}
}
On Android, register Play's prompts in onCreate (packs.registerPlayPrompts(this)) and call show() on WaitingForWifi or NeedsPlayConfirmation. On iOS, copy templates/ios/AssetDropAdapter.swift into the app. More in recipes.
This is the beginning of the README. Read the rest at the original. Read the full README ↗