Extension Manifest
Each installed extension must have a manifest.json in its directory under userData/extensions/<id>/.
json
{
"id": "acme.my-extension",
"name": "My Extension",
"version": "1.0.0",
"description": "Does something useful.",
"author": "Acme Corp",
"entryPoint": "/absolute/path/to/userData/extensions/acme.my-extension/dist/index.js"
}The extension's JS bundle then calls window.__openConduit.extensionRegistry.registerExtension() to declare its contributions at runtime:
ts
window.__openConduit.extensionRegistry.registerExtension(
{ id: 'acme.my-extension', name: 'My Extension', version: '1.0.0' },
{
activityBarItems: [ /* ... */ ],
}
);manifest.json Fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | ✅ | Unique extension identifier. Reverse-domain style recommended (acme.my-ext). |
name | string | ✅ | Display name |
version | string | ✅ | SemVer version |
entryPoint | string | ✅ | Absolute path to the JS bundle read by the preload bridge |
description | string | — | Short description |
author | string | — | Author name or org |
permissions | string[] | — | Permission strings required by write-access API methods. See Extension API → Permissions. |
activate | (api: ExtensionAPI) => void | Promise<void> | — | Lifecycle hook called once after all contributions are registered. Receives the Extension API. |
registerExtension — ExtensionManifest
The first argument to registerExtension mirrors the on-disk manifest (without entryPoint):
ts
interface ExtensionManifest {
id: string;
name: string;
version: string;
description?: string;
author?: string;
contributes?: {
activityBarItems?: ActivityBarContribution[];
commands?: CommandContribution[];
slashCommands?: SlashCommand[];
settingsTab?: SettingsContribution;
bottomPanelTabs?: BottomPanelTab[];
tools?: ToolContribution[];
mainViews?: MainViewContribution[];
splitPaneViews?: SplitPaneViewContribution[];
secondarySidebarPanels?: SecondarySidebarPanelContribution[];
statusBarItems?: StatusBarItemContribution[];
stores?: StoreSliceContribution[];
messageBadges?: MessageBadgeContribution[];
conversationModes?: ConversationModeContribution[];
};
permissions?: string[];
activate?: (api: ExtensionAPI) => void | Promise<void>;
}Contribution Points
| Key | Docs |
|---|---|
activityBarItems | Activity Bar Contributions |
commands | Command Contributions |
slashCommands | Slash Commands |
settingsTab | Settings Contributions |
bottomPanelTabs | Bottom Panel Contributions |
tools | Tool Contributions |
mainViews | View Contributions → Main Views |
splitPaneViews | View Contributions → Split Pane Views |
secondarySidebarPanels | View Contributions → Secondary Sidebar Panels |
statusBarItems | Status Bar Contributions |
stores | Store Slice Contributions |
messageBadges | Message Badge Contributions |
conversationModes | Conversation Mode Contributions |
hooks | Extension API |
activate(api)
The activate function is called once after all contributions are registered. Use it to interact with the host application via the ExtensionAPI.
ts
window.__openConduit.extensionRegistry.registerExtension(
{
id: 'acme.my-extension',
name: 'My Extension',
version: '1.0.0',
permissions: ['conversations.write'],
activate(api) {
api.ui.showNotification({ message: 'My Extension activated!' });
},
},
{ /* contributions */ },
);See Extension API for the full method reference.
