Skip to content

How to Develop App Extensions

App extensions are sandboxed web projects that open in desktop APP tabs. They are the right choice when you need to:

  • build custom UI inside Zelos
  • visualize or control extension-specific workflows
  • read typed bridge state such as theme and extension metadata

Create a project

zelos extensions create my-app-extension --type app

Optional metadata and template controls:

zelos extensions create my-app-extension --type app \
  --author "Jane Doe" \
  --description "Custom dashboard for device health" \
  --template react \
  --template-ref v1.0.0

The created project is based on:

Develop standalone

cd my-app-extension
npm install
npm run dev

Running the app in a normal browser tab uses the SDK MockBridge, so you can iterate without the desktop app.

Develop inside Zelos

npm run build
zelos extensions install-local .

For fast iteration:

npx vite build --watch

Then reload or reopen the APP tab in Zelos.

Lifecycle note

App extensions are not process-managed like agent extensions. The usual app workflow is:

  1. build the web assets
  2. zelos extensions install-local <path>
  3. reopen or reload the APP tab

Agent lifecycle commands such as zelos extensions start, stop, restart, and reinstall do not apply to app extensions.

Security note

Embedded app extensions run under a strict Content Security Policy:

  • No external network - fetch(), XMLHttpRequest, and form submissions to http:/https: URLs are blocked by CSP
  • Origin isolation - each extension runs under zelos-app://extensionId, isolated from the host and other extensions
  • Iframe sandbox - allow-scripts allow-same-origin only; no form submissions or popups

When developing standalone with MockBridge, standard browser CSP applies (typically unrestricted for localhost). External API access is only available in standalone mode.

Package and release

npm run package

That builds the app and delegates archive creation to:

zelos extensions package .

The generated extension.toml includes a [package] section that controls which files are included in the archive:

[package]
paths = ["dist"]

Use zelos extensions package --list . to preview the files before packaging.

Bridge and manifest essentials

A complete manifest for an app extension:

name = "My App Extension"
version = "0.1.0"
icon = "assets/icon.svg"
readme = "README.md"

[host]
type = "app"

[host.app]
kind = "web_app"
entry = "dist/index.html"

[package]
paths = ["dist"]
  • Vite should use base: "./" so assets resolve from zelos-app://...
  • the initial host state arrives in handshake-ack.snapshot as info, theme, and workspace
  • after connect, the host only pushes theme.changed and workspace.changed
  • v1 has no request/response or host-command bridge API
  • ZelosBridgeProvider applies Zelos light/dark theme classes and design tokens to the document automatically
  • optional host context is available through SDK hooks when your app needs it
  • keep extension-owned UI state inside the extension; APP tabs may be reloaded or remounted across the desktop app lifecycle

More detail