Deliver a JavaScript update
Use an over-the-air update for a TypeScript or CSS fix compatible with an installed release shell. Updates replace bytecode on the next launch. Native code, modules, permissions, assets, fonts and database migrations require a new native build.
Configure signing
Create an update key outside the app directory:
kuito update key ~/keys/myapp-updates.pemThe command writes a private key and prints its public key. Configure the host and public key before building the release shell:
import type { KuitoConfig } from 'kuito/config';
export default {
name: 'MyApp',
ios: { bundleIdentifier: 'com.example.myapp' },
android: { applicationId: 'com.example.myapp' },
updates: {
url: 'https://updates.example.com/myapp',
publicKey: 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE…',
},
} satisfies KuitoConfig;Replace the example public key with the full generated value. Keep the private key outside the repository and app; the CLI refuses a private-key path inside the app. Debug builds and release builds without this config do not download updates.
Build and upload
KUITO_UPDATE_KEY_PATH=~/keys/myapp-updates.pem kuito update build iosAlternatively, provide PEM contents through KUITO_UPDATE_KEY. --env chooses an environment and --out chooses the output directory. The default environment is production.
.kuito/updates/
ios/<fingerprint>/
update.json the signed manifest a shell fetches
<id>/*.hbc the kernels and the app
<id>/modules/ the app's chunksUpload these files to the configured HTTPS host without changing their relative paths. Upload bytecode under <id>/ first and publish update.json last. Retain .kuito/sourcemaps/<platform>/update-<id>/ with the release artifacts so errors can be symbolicated.
Understand compatibility and rollout
The shell requests the directory matching its native fingerprint. That fingerprint includes framework native code, Hermes, linked modules, permissions, assets, fonts and migrations. Name, version, build number, icon and launch screen do not determine compatibility. A single host can therefore serve distinct native builds.
After the first frame, the shell downloads the signed manifest, verifies it, then checks each script's size and SHA-256. The current session continues running its current code. A verified newer update becomes eligible on the next launch; older updates are refused.
Two consecutive launches that crash or fail to draw a frame roll back to the embedded bytecode. The failed update is then refused. A native crash after the first frame does not count toward that rollback. Failures and refusals appear in platform logs.
Current limits
There is no app API to check immediately, force a restart or inspect the active update. Rollback selects the embedded build, not the previous downloaded update. A shell trusts its original public key; key rotation requires a new shell.
See release builds for creating the compatible native app.