Skip to content

Extension package layout ​

The current extension package shape is:

text
my-extension/
├── extension.json
├── package.json
├── index.html
├── mod.js                    # mod extensions only
└── native/
    ├── linux-x86_64/my-native-bin
    ├── linux-aarch64/my-native-bin
    ├── macos-aarch64/my-native-bin
    └── windows-x86_64/my-native-bin.exe

3.1 Required files ​

  • extension.json
  • one entry file referenced by entry
  • package.json with a build script that ends by running isa-ext package

3.2 Optional files ​

  • native binaries under native/
  • packaged frontend assets under app/ or another folder referenced by entry
  • assets needed by the extension UI
  • an optional extension icon asset referenced by icon.path
  • extension-local build scripts
  • extension-local README
  • one classic JavaScript host module referenced by modEntry, only when the manifest requests the mod permission

Model recommendations do not require a separate file. Their small portable descriptors live inline in the source extension.json. Follow the complete model-recommendation author workflow before publishing them.

For complex extensions, a source layout separate from packaged assets is recommended.

The pattern used by chat-ui-3/extensions/meeting-warden/README.md is a good reference:

text
my-extension/
├── extension.json
├── package.json
├── app/
├── native/
├── src/svelte-ui/
├── extension-native/
└── README.md

3.4 Dashboard distribution package ​

Dashboard-distributed extensions use a directory package with the suffix .isax. Clients do not read directory listings. Given a package root URL, clients derive exactly two child URLs:

text
<package-root-url>/extension.json
<package-root-url>/payload.tar.xz

The package root must contain:

  • extension.json: the canonical extension manifest plus distribution metadata shown in dashboard administration screens
  • payload.tar.xz: an archive containing the installable extension assets, without another extension.json

Dashboard administrators can also add this package from the desktop app with the Add Extension Browse action. The picker accepts the .isax directory itself (not a loose archive or JSON file), validates both files and the installable payload locally, then uploads payload.tar.xz as one extension artifact. The extension record stores the artifact ID; it never stores a short-lived signed download URL. URL-based packages continue to use the two HTTP child URLs above.

The distribution extension.json must include:

  • id: stable extension identifier
  • name
  • version
  • author
  • description
  • entry: safe relative iframe entry path
  • payloadSha256: SHA-256 hex digest of payload.tar.xz

The optional fields are:

  • minimumIsaWardenVersion: the lowest compatible ISA Warden host release as an exact semantic version
  • modelRecommendations: validated model descriptors copied from the source manifest so an administrator can review them before installing the payload
  • icon: validated Lucide or packaged-asset metadata
  • permissions: the normalized permission list
  • modEntry: the safe relative host-module path when permissions contains mod

Future fields are accepted but not required:

  • changelog
  • license
  • screenshots
  • signature

The archive payload must extract directly into one installable extension root. It contains entry assets and optional native/ assets, but not extension.json. During preview or installation, the host writes the package-root manifest into the extracted root and runs the same validator used by local installs in validate_extension().

The package-root manifest is the only manifest and is authoritative for preview, install, and update. The host rejects malformed minimum versions and packages whose minimum is newer than its own application version.

3.5 isa-ext build CLI ​

ISA Warden extensions are finalized with the Rust CLI at chat-ui-3/extensions/isa-ext. Each extension may use any local build system it needs, such as Vite, Parcel, Rust, or plain files, but the final dashboard bundle must be produced with isa-ext package.

Install the CLI from this repository:

sh
cargo install --path chat-ui-3/extensions/isa-ext

Then package an extension with the installed command:

sh
isa-ext package chat-ui-3/extensions/hello-world

The package command validates extension.json, verifies the manifest entry file, creates <id>.isax/payload.tar.xz without the source manifest, and writes the canonical package-root manifest with payloadSha256. When minimumIsaWardenVersion is present, isa-ext validates its semantic-version syntax and preserves it. When modelRecommendations is present, isa-ext also validates its versioned portable model contract and preserves it inline. The CLI validates icon, permissions, and modEntry; an unsafe or missing icon asset, a modEntry without mod, mod without modEntry, an unsafe path, or a missing module asset fails packaging. Inspecting this generated public block is a required step in the recommendation validation workflow.

Every repository extension root has a package.json with a common finalization step:

json
{
  "scripts": {
    "build": "npm run package",
    "package": "isa-ext package ."
  }
}

Complex extensions can add their own pre-package steps:

json
{
  "scripts": {
    "build": "npm run build:ui && npm run package",
    "build:ui": "npm --prefix src/svelte-ui run build",
    "package": "isa-ext package ."
  }
}

3.6 Scaffolding a minimal extension ​

isa-ext scaffold creates a small pale Hello World proof-of-concept extension with extension.json, index.html, app.js, styles.css, and package.json.

Interactive mode:

sh
isa-ext scaffold

Non-interactive mode:

sh
isa-ext scaffold --name "Acme Hello" --author "Acme" --directory acme-hello

The scaffolded package.json uses isa-ext package . for its build script, so generated projects can be packaged with:

sh
npm run build

ISA Warden extension specification