Releases take days.Ketoy takes seconds.

Ketoy helps Android teams ship Jetpack Compose, ViewModels and Kotlin logic to installed apps without a Play Store release. The Kotlin alternative to JSON server driven UI.

Skills
terminal

$ ketoy push ktx app_7f3a main.ktx --version 12

Signed with Ed25519

Version 12 is live on every device

Updated to version 12
Offers
Annual plans

Summer saleLast day of the sale

Save 25% when billed yearly.

AnnualBilled once a year
Save 25%
MonthlyCancel anytime
Claim offer
main.ktxversion 12 · signed

One annotation, everything over the air.

UI, state, logic and data. If it compiles to Kotlin, Ketoy delivers it, with no JSON schema to maintain and no second component model to learn.

Compose UIViewModel and stateNetworking and storageNavigation and flows
Compose UI

Real Compose, not a lookalike.

JSON driven UI hands you a subset of components drawn by a renderer. Ketoy compiles the Compose you already write, all 35 Material 3 components with every parameter. It renders natively on the device, so nothing is redrawn from a schema.

  • Scaffold
  • LazyColumn
  • TopAppBar
  • OutlinedTextField
  • AlertDialog
  • +30 more
Plans
Search plansAnnual
MonthlyAnnualFamily
Offline modeKeep screens on device
Release alertsWhen a bundle goes live
ContinueCompare
ViewModel and state

Your ViewModels, shipped with the screen.

Most over the air tools stop at layout, so logic still waits for a release. Ketoy ships the ViewModel too. It survives configuration changes, exposes StateFlow and works with Hilt, and coroutines and Flow operators come along with it.

  • viewModelScope
  • StateFlow
  • collectAsState
  • @HiltViewModel
  • SavedStateHandle
@HiltViewModelclass OffersViewModel @Inject constructor(    private val repo: OffersRepository) : ViewModel() {    val state = repo.offers()        .map { OffersUi(it) }        .stateIn(viewModelScope, Eagerly, OffersUi())     fun claim(id: String) = viewModelScope.launch {        repo.claim(id)    }}
Networking and storage

67 capabilities, one registry.

Dynamic code usually means either no platform access or far too much. Ketoy routes every bundle through registered capabilities, with HTTP, Room, DataStore and navigation built in. Register your own SDKs the same way and they go over the air as well.

  • HTTP
  • Room
  • DataStore
  • Hilt
  • Your SDKs
KBCbundle
HTTPRoomDataStoreNavigationHiltCoroutinesFlowLifecycleClipboardHapticsShareYour SDK
Navigation and flows

Whole flows, not just screens.

A new onboarding or checkout normally waits for the next release. Ketoy ships routes, back stacks and arguments together as one bundle. The flow goes live this afternoon and the APK stays untouched.

  • NavController
  • routes
  • arguments
  • deep links
NavGraphmain.ktx · v12

Merge to every phone, in four steps.

Annotate a screen, run one Gradle task, push. Fix a bug at 3:00 and every phone has it by 3:01. The app never reinstalls.

  1. 01

    Write

    Add @KetoyEntryPoint to a screen. Everything else is the Kotlin and Compose you already write, in the project you already have.

  2. 02

    Bundle

    One Gradle task compiles the screen to Ketoy Bytecode. Native code keeps compiling to DEX exactly as before.

  3. 03

    Push

    The CLI signs the bundle with your key and publishes a new version. Rolling back is one command, with no release in between.

  4. 04

    Verify and render

    Each device checks the signature, resolves capabilities and renders native Compose. First frame in under 100 ms.

Signed, sandboxed, then rendered.

Code that arrives over the air is a liability until it is checked. Ketoy treats every bundle as untrusted until three checks pass on the device, before the first frame.

  • 01

    Every bundle is signed

    Ketoy checks an Ed25519 signature before any code runs. Your private key stays on your server, so only you can ship a bundle.

  • 02

    The sandbox is a build error

    The compiler rejects file access, reflection and any unregistered API. Unsafe code never compiles, so it never ships and never needs catching at runtime.

  • 03

    Capabilities are the only door

    Bytecode reaches the platform through registered capabilities and nothing else. What is not registered is not callable, by design.

on devicemain.ktx · v12
  1. Bundle receivedmain.ktx, version 12
  2. Signature verifiedEd25519, against your public key
  3. Capabilities resolvedRegistered APIs only
  4. RenderedNative Jetpack Compose

Ketoy fails closed. A bundle that does not verify is ignored and the last good version keeps running.

Built for terminals, and the agents inside them.

The Ketoy CLI runs the whole workflow from your terminal or your CI. Ketoy Skills hand Claude Code, Cursor or any coding agent an accurate map of the framework before it writes a line.

ketoy

$ ketoy init

Compiler plugin added. App wired.

$ ./gradlew :app:ketoyBundle

main.ktx built

$ ketoy push ktx app_7f3a main.ktx --version 12

Live on every device

$ ketoy ktx rollback app_7f3a

Version 11 is live again

$

Ketoy CLI

Init, bundle, push, roll back.

One binary runs the whole workflow, so a release is a command and not a calendar event.

npm install -g ketoy-dev
CLI docs
Ketoy Skills

Your agent already knows Ketoy.

A skill pack that grounds coding agents in how Ketoy works, so they write a KetoyScreen correctly the first time.

  • Claude Code
  • Codex
  • Cursor
  • Windsurf
  • Gemini CLI
ketoy skills add

Questions, answered.

More in the docs
What is Ketoy?

Ketoy is a Kotlin over the air update framework for Android. You write real Jetpack Compose, ViewModels and business logic. Ketoy compiles it to a small signed .ktx bundle and delivers it to installed apps in seconds, with no Play Store release.

Is this allowed on the Play Store?

Yes. Ketoy generates code on device, the same way ART does with bytecode. Bundles run in a sandbox and render native Compose, which keeps updates inside Google Play policy.

What can Ketoy update over the air?

Jetpack Compose UI, ViewModels and state, navigation, coroutines and Flow, networking, Room and DataStore. Plain Kotlin works too, including data classes, objects and functions.

How is Ketoy different from JSON server driven UI?

There is no JSON schema and no parallel component model. Ketoy compiles ordinary Kotlin to Ketoy Bytecode (KBC). Bundles are about 20 times smaller than equivalent JSON SDUI and render as native Compose.

What happens if my server goes down?

The last signed bundle keeps running. Every KetoyScreen also takes a native fallback, so a missing bundle never breaks a screen.

Built by Android devs, for Android devs.

For us, over the air is not an add-on to a config service. It is the product. Install the CLI, annotate one screen and push. Your first update takes about ten minutes.

npm install -g ketoy-dev
Get startedGitHub