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 (occasional)

Day-to-day, you only ever ship app bundles.

App bundle updates

npx kog deploy # over USB — builds, signs, and installs via the OTA path

kog deploy builds and signs your app, then stages it to the board over the USB dev-link. The bundle is written to a staging partition, verified (integrity hash + Ed25519 signature + ABI check), and armed. 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.

Because OTA install doesn't itself reboot, kog deploy resets the board for you after staging so the new app boots immediately. Pass --no-reset to leave the running app in place; it boots the new bundle on the next manual reset.

Deploy is USB-only — there is no Wi-Fi code-push path. (Wi-Fi on the device is for your app's own networking, not for pushing code.) 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).

Development vs. production posture

kog deploy puts the board in production posture: as it stages the bundle, the firmware writes dev_mode=0 to NVS, so the deployed app boots standalone with the hot-reload dev-link turned off (the full RAM goes to your app). This is the mirror of kog flash, which leaves the board in development posture so kog dev can hot-reload it. To go back to developing on a deployed board, run kog flash again.

Failed-trial recovery (known issue, fast-follow)

The deploy happy path — stage → trial-boot → confirm → promote — is validated on hardware. But if a deployed app fails its trial boot, the board self-heals to a safe state (production posture, hot-reload off), and the previous app may not be restored. Recover with kog flash, which restores development posture (and dev mode). A focused fix for the failed-trial recovery path is a fast-follow.

Stdlib fingerprint is cross-artifact consistent

As of the ship build, the device firmware and the in-browser/CLI bytecode producer log the same stdlib-fingerprint for a given generation (0x06089e4e for the current one). The fingerprint hashes only the pointer-free atom-string prefix (excluding the link-address table entries that used to make the xtensa and wasm32 builds differ), so device and producer agree. The fingerprint-based producer/CLI generation handshake (spec/16 §8.7.1) is now safe to wire; it's a fast-follow, not required for the current bytecode-version-based engine selection.

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 to upgrade the board's runtime (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 reflashing the runtime with kog flash is an occasional event, not a routine one.

Signing

App bundles can be Ed25519-signed. A development board is keyless — kog flash provisions no OTA public key, so per spec/05 §2 it accepts unsigned bundles and kog deploy pushes unsigned by default, keeping the dev loop frictionless. For production, provision the board with your OTA public key and configure the matching signing key (kog.config ota.signingKey, KOG_SIGNING_KEY, or --signing-key); kog deploy then Ed25519-signs the bundle and the board refuses unsigned or foreign bundles.