Lifecycle

Startup sequence

  1. Main process starts the integrations worker (WorkerMain('integrations')) and waits for loadComplete.
  2. Main sends executeCode with { integration: { id, name, permissions, … }, codePath }.
  3. Worker builds GenerateContext(), then runs addon index.js inside vm.runInContext (initial execution timeout: 5 seconds).
  4. Addon code registers endpoints, config schema, and event handlers during this load phase.

Long-running work must continue after load using setTimeout, setInterval, sleep, or async handlers — not blocking synchronous code during the initial VM run.

When the worker restarts

The worker restarts when:

storage.Read() / storage.Write() persist across worker restarts within the same install. api.config params persist in app config.

Graceful stop — addon:prepare-stop

Before StreamKit+ kills the addon worker, the main process fires the built-in event addon:prepare-stop and waits for the handler to finish (with a short timeout, about 2.5 seconds). Use it to finish remote cleanup that must run while the OAuth token / network stack are still available.

When it fires

When it does not fire

Handler contract

events.On('addon:prepare-stop', async () => {
  // e.g. pause or disable remote resources (Twitch rewards, webhooks, …)
  await cleanupRemoteState();
  return { success: true };
});
Detail Value
Payload {} (empty object)
Permission None
Timeout ~2.5s — keep work short; unfinished work is abandoned and the worker is killed
Optional Omitting the handler is fine; other addons are unaffected

Do not rely on this event for data that must survive forever — persist important state with storage / api.config during normal operation. Prefer addon:prepare-stop for best-effort remote teardown (pause rewards, close sessions, revoke short-lived hooks).

See also events.

Crash loop protection

If the worker process crashes (uncaught exception, fatal error, abrupt exit), StreamKit+ restarts it automatically — similar to a normal restart.

To avoid an infinite restart loop, the app tracks consecutive crashes:

Rule Value
Max consecutive crashes 3
Stable run to reset the counter 30 seconds after loadComplete

What counts as a crash

What does not count

When the limit is reached

  1. Auto-restart stops; the addon worker is not started again.
  2. The user sees an error notification and an error status for the addon.
  3. In addon settings the addon stays enabled but shows a Stopped after errors badge (with a tooltip that a manual restart is required).
  4. After an app restart the crash-stop flag is cleared and the addon is started again automatically.

How to recover

During the same session the user must restart the addon manually from settings (↻ button) or disable and re-enable it. That clears the crash-stop flag and starts a fresh worker with a reset crash counter. Restarting the whole app also clears the flag and starts enabled addons again.

Implications for addon authors

Static web routes

When manifest.web is set and WEB_CONTENT (or ROOT) is granted, the main process registers static routes:

http://localhost:{WEB_SERVER_PORT}/addon_static/{id}/

The root serves the web file; paths in web_contents are served under the same prefix. Routes are removed on disable, restart, or uninstall.

Missing files

If manifest.json or index.js is missing at the recorded install path, the app treats the addon as broken: settings show an error banner, settings cannot be opened, and only uninstall is available. Overlay/timer triggers referencing that addon are cleaned up on startup.