OTA updates & versioning
A Kog device has two independently updatable layers, and the split is what makes updates fast and safe:
| Layer | Contains | Typical size | Updated by |
|---|---|---|---|
| App bundle | Your compiled app (bytecode + assets refs) | tens of KB | kog deploy, your own update flow |
| Runtime firmware | LVGL, JS engine, Kog host, drivers | a few MB | kog flash --runtime (rare) |
Day-to-day, you only ever ship app bundles.
App bundle updates
Bundles are written to a staging partition, verified (integrity hash + Ed25519 signature + ABI check), then atomically activated. On the next boot the runtime must reach a first successful frame within a few seconds or it rolls back automatically to the previous bundle — a bad deploy can't brick a device.
npx kog deploy --release # over USB or Wi-Fi, uses the OTA path
For fleet updates, the same verified-staged-swap mechanism is exposed so your app can fetch its own updates (useOTAStatus() reports progress/state to your UI).
The ABI contract
Your app bundle is compiled against a specific runtime ABI — the versioned vocabulary of widgets, properties, and host functions. The rule is simple: bundle ABI must exactly match device ABI.
You can't get this wrong accidentally:
kog dev/deployquery the device's ABI before pushing and explain any mismatch:- Device older → "Run
kog flash --runtimeto upgrade the board (app and settings preserved)." - Device newer → "Update your CLI:
npm i @kog/cli@latest."
- Device older → "Run
- The device independently re-verifies at install and at boot.
Runtime releases only bump the ABI on breaking protocol changes — many runtime versions share an ABI, so kog flash --runtime is an occasional event, not a routine one.
Signing
App bundles are Ed25519-signed. Devices provisioned with your public key refuse unsigned or foreign bundles; development mode uses a per-project dev key so the dev loop stays frictionless.