Skip to content
Documentation ▾

Plugins

Manifest & API reference

Every field in atomcut.plugin.json, every method on window.atomcut, and the capability each one requires.

atomcut.plugin.json

The manifest is validated on install; an invalid or missing field is rejected with a readable error rather than installed half-broken. Every optional field defaults, so a minimal manifest is valid.

FieldTypeRequiredDefaultNotes
manifestVersion1Yes—Literal — must equal 1, the current schema version.
idstringYes—Reverse-DNS style, e.g. com.acme.confetti — alphanumeric segments joined by ., _ or -. The uniqueness key: installing a bundle whose id matches an installed plugin replaces it.
namestring (1–60 chars)Yes—Display name.
versionstring (semver)Yes—e.g. 1.0.0 — how the host tells an update from a fresh install.
descriptionstring (≤280 chars)No""Shown under the name in the manager.
author{ name, email?, url? }Yes—name is required (min 1 char); email and url are validated if present.
apiintegerYes—The plugin protocol major you target. A manifest whose api is newer than the host's protocol version is refused at install.
mainstringNo"ui.html"The entry HTML file inside the bundle — loaded into the sandbox iframe.
iconstring | nullNonullPath to a png/svg/webp/etc. inside the bundle. null falls back to a generated initials avatar.
capabilitiesCapability[]No[]The permissions this plugin asks for — see the capability table below. Declare only what you call.
categoriesstring[]No[]Free-form tags shown in the manager.
windowobjectNosee belowThe plugin's initial floating window.
publisherIdstring | nullNonullReserved for signed-publisher identity (marketplace, verified authors). Parsed and stored today; not yet enforced.
engines.atomcutstringNounsetA semver range the host's app version must satisfy, e.g. ">=1.4.0" — reserved for host-compatibility gating.

window

The plugin's initial floating window. All fields are optional.

FieldTypeRequiredDefaultNotes
widthinteger, 1–2400No360Initial width, px.
heightinteger, 1–2400No560Initial height, px.
minWidthinteger > 0NounsetMinimum resize width.
minHeightinteger > 0NounsetMinimum resize height.
resizablebooleanNotrueWhether the window can be resized.

window.atomcut

The only surface a sandboxed plugin can touch. Every method is async — a postMessage round trip to the host — except getContext(), which resolves from static boot data with no round trip. Calling a method whose capability wasn't granted rejects with an error naming the missing capability; calling an unknown method rejects too — the bridge fails closed.

MethodSignatureCapabilityNotes
getContext()(): Promise<HostContext>noneThe editor's app version and protocol version, this plugin's identity, and the capabilities actually granted (⊆ what you declared). No round trip.
document.getInfo()(): Promise<DocInfo>document:readThe open document's id, name, fps, durationMs and frameCount.
document.insertText(params)(params: InsertTextParams): Promise<InsertTextResult>document:writeInserts a text layer into the active frame at the playhead. text is required; x/y offset from the frame centre in px, fontSize and color (any CSS color) are optional. Returns the new layer's clipId.
selection.get()(): Promise<SelectionInfo>selection:readThe current activeFrameId, frameIds and clipIds.
ui.notify(message, level?)(message: string, level?: NotifyLevel): Promise<void>ui:notifyToasts a message in the editor. level is one of info | success | warning | error (default info).
ui.resize(size)(size: { width: number; height: number }): Promise<void>noneResizes this plugin's own window (clamped to 120–2400px per dimension).
ui.close()(): Promise<void>noneCloses this plugin's window.
on("selectionchange", handler)(event, handler: (info: SelectionInfo) => void): () => voidselection:readSubscribes to selection changes; call the returned function to unsubscribe. See below.

Capabilities

The whole trust model in one table: a plugin declares the capabilities it needs in capabilities, and every bridge call is checked against what was granted. Nothing here grants raw access to app state — each capability unlocks exactly the methods listed above.

CapabilityGrants
document:readRead the document — its frames, layers and properties.
document:writeCreate, edit and remove layers in the document.
selection:readSee and react to what the user has selected.
ui:notifyShow toast messages in the editor.

The selectionchange event

Subscribe with atomcut.on("selectionchange", handler); it returns an unsubscribe function. The host pushes this event whenever the active frame or the selected frames/clips change — only to plugins granted selection:read. The handler receives a SelectionInfo:

interface SelectionInfo {
  activeFrameId: string | null; // the comp the editor is focused on
  frameIds: string[];           // selected frames
  clipIds: string[];            // selected clips/layers
}

Call selection.get() once on load to read the current state, then rely on the event for changes — the same shape is returned by both.

New to plugins? Start at Plugins, or see Build a plugin for a working example.