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.exe3.1 Required files
extension.json- one entry file referenced by
entry package.jsonwith abuildscript that ends by runningisa-ext package
3.2 Optional files
- native binaries under
native/ - packaged frontend assets under
app/or another folder referenced byentry - 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 themodpermission
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.
3.3 Recommended source layout
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.md3.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.xzThe package root must contain:
extension.json: the canonical extension manifest plus distribution metadata shown in dashboard administration screenspayload.tar.xz: an archive containing the installable extension assets, without anotherextension.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 identifiernameversionauthordescriptionentry: safe relative iframe entry pathpayloadSha256: SHA-256 hex digest ofpayload.tar.xz
The optional fields are:
minimumIsaWardenVersion: the lowest compatible ISA Warden host release as an exact semantic versionmodelRecommendations: validated model descriptors copied from the source manifest so an administrator can review them before installing the payloadicon: validated Lucide or packaged-asset metadatapermissions: the normalized permission listmodEntry: the safe relative host-module path whenpermissionscontainsmod
Future fields are accepted but not required:
changeloglicensescreenshotssignature
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-extThen package an extension with the installed command:
sh
isa-ext package chat-ui-3/extensions/hello-worldThe 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 scaffoldNon-interactive mode:
sh
isa-ext scaffold --name "Acme Hello" --author "Acme" --directory acme-helloThe scaffolded package.json uses isa-ext package . for its build script, so generated projects can be packaged with:
sh
npm run build