Every extension must include a manifest.json file in the repository root. The manifest is how Bulwark knows what the extension is, what capabilities it needs, and where its entry point lives.
{
"name": "my-extension",
"displayName": "My Extension",
"version": "1.0.0",
"type": "plugin",
"pluginType": "sidebar-app",
"description": "A short description.",
"author": "githubUsername",
"license": "MIT",
"permissions": ["email:read"],
"tags": ["productivity"],
"minAppVersion": "1.0.0",
"entryPoint": "index.js",
"icon": "icon.png"
}
| Field | Description |
|---|
name | Unique slug — lowercase, numbers, and dashes only. Used in URLs and install paths. |
displayName | Human-readable name shown in the directory and admin UI. |
version | Semantic version (for example 1.0.0). Must match a git tag in the source repo. |
type | Either plugin or theme. |
description | Short summary of what the extension does. Max 200 characters. |
license | SPDX identifier of an OSI-approved license (for example MIT, Apache-2.0, GPL-3.0-or-later). |
permissions | Array of permission strings the extension needs. Requesting more than necessary will be rejected. |
| Field | Description |
|---|
pluginType | One of hook, ui-extension, or sidebar-app. |
entryPoint | Relative path to the JavaScript entry module (for example index.js). |
minAppVersion | Minimum Bulwark version the plugin supports. Used for compatibility checks. |
| Field | Description |
|---|
entryPoint | Relative path to the theme stylesheet (typically theme.css). |
| Field | Description |
|---|
author | GitHub username of the author. Defaults to the submitter. |
tags | Array of category tags. Allowed: productivity, security, automation, appearance, integration, communication, developer-tools, accessibility. |
icon | Relative path to a square icon (128×128 PNG or SVG). |
screenshots | Array of relative paths to screenshot images. |
homepage | URL to the extension's website or documentation. |
Bulwark uses a declarative permission model. Each permission string takes the form resource:action. The directory shows these on the extension's listing so users can audit what an extension can do before installing.
| Category | Permissions |
|---|
| Email | email:read, email:write, email:send |
| Calendar | calendar:read, calendar:write |
| Contacts | contacts:read, contacts:write |
| Files | files:read, files:write |
| Identity | identity:read, identity:write |
| Filters | filters:read, filters:write |
| Tasks | tasks:read, tasks:write |
| Templates | templates:read, templates:write |
| S/MIME | smime:read |
| Vacation | vacation:read, vacation:write |
| Settings | settings:read |
| Security | security:read |
| UI | ui:toolbar, ui:email-banner, ui:email-footer, ui:composer-toolbar, ui:sidebar-widget, ui:settings-section, ui:context-menu, ui:navigation-rail, ui:keyboard |
| Auth | auth:observe |
When you submit, the directory checks that:
- The manifest is valid JSON with all required fields.
name is a valid slug and not already taken.
version matches an existing git tag on the referenced repository.
license is an OSI-approved SPDX identifier and a LICENSE file is present.
permissions contains only known permission strings.
If any of these fail, the submission is rejected with a machine-readable error.