Skip to main content

OTA updates & versioning

A Kog device has two independently updatable layers, and the split is what makes updates fast and safe:

LayerContainsTypical sizeUpdated by
App bundleYour compiled app (bytecode + assets refs)tens of KBkog deploy, your own update flow
Runtime firmwareLVGL, JS engine, Kog host, driversa few MBkog 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/deploy query the device's ABI before pushing and explain any mismatch:
    • Device older → "Run kog flash --runtime to upgrade the board (app and settings preserved)."
    • Device newer → "Update your CLI: npm i @kog/cli@latest."
  • 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.