The manifest
manifest.json is the only thing the app reads to build its menus and columns. The plugin itself starts later, at the first command or column call. A manifest the app cannot accept makes the plugin incompatible: it is listed in Settings ▸ Plugins with the reason and never loaded.
{
"id": "com.example.git-status",
"name": "Git Status",
"version": "1.1.0",
"runtime": "javascript",
"hostAPI": { "min": "1.7", "max": "1" },
"permissions": ["process.spawn:git"],
"commands": [
{ "id": "gitstatus.refresh", "title": "Refresh Git Status",
"placement": "pluginsMenu",
"availability": { "minSelection": 0, "schemes": ["file"] } }
],
"columns": [
{ "id": "gitstatus.state", "title": "Git", "width": 56, "badge": true,
"refreshWhenChanged": [".git/index"] }
],
"entry": "main.js"
}
Keys
id: letters, digits, ., _ and -, up to 128 characters, not starting with a dot. Reverse-DNS form keeps it unique. The app knows every command and column by its owner, as plugin:<id>/<command id>, so two plugins may use the same short command or column ids without one answering for the other.
name (up to 128 characters) and version (up to 64) are shown in Settings ▸ Plugins.
runtime: "javascript" or "process".
hostAPI: the range of host API versions the plugin works with, as semantic versions. The current version is 1.8. "max": "1" accepts every 1.x; a plugin outside the range is listed as incompatible, with the reason. Set min to the lowest version that has everything you use:
| Since | Feature |
|---|---|
| 1.1 | the tabMenu placement and surface in the command context |
| 1.2 | column type and defaultVisible |
| 1.3 | network.client for process plugins |
| 1.4 | app.open:<bundle id> and ocelot.openInApp; network.client for JavaScript plugins; truncated in spawn results |
| 1.6 | ocelot.storage, ocelot.invalidateColumn and the invalidateColumn notification |
| 1.7 | refreshWhenChanged on columns |
| 1.8 | the limits on this page; no side effects from a script's top level |
permissions: a list of the strings on the Permissions page. An unknown string makes the manifest incompatible. A change to the list disables the plugin until the user enables it again.
commands: up to 64 entries, each with
id: same grammar as the plugin id, unique within the plugin;title: up to 128 characters, shown in the menu as it is;placement:contextMenu(the Extensions section of the right-click menu on items and on the empty area),pluginsMenu(the Plugins menu in the menu bar) ortabMenu(the right-click menu of a tab; needs host API 1.1 andminSelection: 0, since a tab has no selection);availability: when the item is enabled. The app evaluates it; the plugin is never asked.minSelection(default 1) andmaxSelection: how many items must be selected. 0 lets the command run on the folder itself.schemes:["file"]for files on disk,["archive"]inside archives. Without it, any provider; but commands inside archives are disabled unless"archive"is listed, because the paths there are not files on disk.utTypes: at least one selected item conforms to one of these uniform type identifiers, for examplepublic.image.requiresWritableDirectory: the shown folder must be writable.- At most 32 schemes and 32 types, each up to 255 characters.
columns: up to 16 entries, each with id, title, width (20 to 1000, default 80), and optionally badge, type, defaultVisible and refreshWhenChanged, described on the Columns page.
entry: the file beside the manifest that is the plugin: main.js for a script (a regular file of at most 4 MB) or the name of an executable for a process plugin. A link is not accepted.
What makes a manifest incompatible
A key the app does not understand is ignored; a key it understands and cannot accept makes the plugin incompatible. The list, so the log line makes sense: an unknown permission; a hostAPI range the app is outside of; an id that breaks the grammar; a name or title over 128 characters or a version over 64; more than 64 commands or 16 columns; a command or column id declared twice; a column width outside 20 to 1000; an availability rule with more than 32 schemes or types; an unknown column type; an unknown placement other than menuBar, which is treated as pluginsMenu; an invalid refreshWhenChanged entry; an entry that is not a regular file.