Skip to content

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 ​

FieldTypeRequiredDescription
idstring✅Unique extension identifier. Reverse-domain style recommended (acme.my-ext).
namestring✅Display name
versionstring✅SemVer version
entryPointstring✅Absolute path to the JS bundle read by the preload bridge
descriptionstring—Short description
authorstring—Author name or org
permissionsstring[]—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 ​

KeyDocs
activityBarItemsActivity Bar Contributions
commandsCommand Contributions
slashCommandsSlash Commands
settingsTabSettings Contributions
bottomPanelTabsBottom Panel Contributions
toolsTool Contributions
mainViewsView Contributions → Main Views
splitPaneViewsView Contributions → Split Pane Views
secondarySidebarPanelsView Contributions → Secondary Sidebar Panels
statusBarItemsStatus Bar Contributions
storesStore Slice Contributions
messageBadgesMessage Badge Contributions
conversationModesConversation Mode Contributions
hooksExtension 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.

Released under the AGPLv3 License.