Inter Plugin Communication
UXP allows communication between plugins installed within the same application
This feature is handy when you know another plugin already automates a specific task; in such cases, you can invoke it instead of duplicating the effort. To provide the best user experience, ensure your plugin clearly communicates such dependencies.
Overview
The Plugin Manager module provides the necessary APIs to establish the connection. Before diving into an example, make sure you're familiar with the following topics:
Additionally, you will need to have a basic understanding of the plugin you are going to communicate with, which includes:
- The plugin's
idandentrypoints - The structure of arguments to be passed, if applicable.
Implementation
We’ll refer to the two plugins as Requester and Responder.
Requester
This is the plugin that will initiate the communication with the Responder. It must have the enablePluginCommunication permission set to true in the manifest.json file.
Copied to your clipboard{// ..."requiredPermissions": {"ipc": { "enablePluginCommunication": true }}// ...}
Through the pluginManager module, the Requester plugin can get a list of all installed plugins in Premiere and find the Responder plugin by its id (which must be known in advance).
Copied to your clipboardconst { pluginManager } = require("uxp");const allPlugins = pluginManager.plugins;const responderPlugin = Array.from(allPlugins).find(plugin => plugin.id === "Test-responder"); // 👈 Responder id
When you've stored a reference to the Responder plugin, you can invoke its command entrypoints using the invokeCommand(), or request to show its panel using the showPanel() methods. Pass the id of the entrypoint you want to invoke or show.
Copied to your clipboardresponderPlugin.invokeCommand("simpleCommand");responderPlugin.showPanel("simplePanel");
Payloads
It is possible to pass data using the invokeCommand() method:
Copied to your clipboardconst payload = { message: "From Requester" };responderPlugin.invokeCommand("simpleCommand", payload);
Responder
This is the plugin that will receive the communication from the Requester plugin. It does not need additional manifest permissions, but the command entrypoints the Requester will invoke must be exposed in the manifest.json file.
Copied to your clipboard{// ..."entrypoints": [{"id": "simplePanel","type": "panel","label": { "default": "Main Panel" },// ...},{"id": "simpleCommand","type": "command","label": { "default": "Simple Command" }},{"id": "commandWithInput","type": "command","label": { "default": "Command With Input" }}],// ...}
The commands should also be implemented in the index.js file. For more information, please refer to the Add Commands tutorial.
Example
In this example, the Requester plugin implements a button that will initiate three requests to the Responder plugin:
- show the Responder's panel
- invoke the Responder's
simpleCommandentrypoint - invoke the Responder's
commandWithInputentrypoint, with an input payload
The Responder plugin will log the requests in the panel's body.
Requester code
Copied to your clipboard<!DOCTYPE html><html><head><script src="main.js"></script><link rel="stylesheet" href="style.css" /></head><body><sp-heading>Requester Plugin</sp-heading><sp-divider></sp-divider><div class="main-div"><sp-body id="plugin-body"><sp-button id="btnCommunicate">Communicate with Responder Plugin</sp-button></sp-body></div></body></html>
Copied to your clipboardbody { padding: 16px; color: white; }sp-divider { margin-bottom: 20px; }sp-heading { color: var(--uxp-host-text-color-secondary, white); }
Copied to your clipboard//global objects.const { pluginManager } = require("uxp");document.querySelector("#btnCommunicate").addEventListener("click", communicateWithAnotherPlugin);function communicateWithAnotherPlugin() {try {const allPlugins = pluginManager.plugins;const plugin = Array.from(allPlugins).find((plugin) => plugin.id === "Test-responder");if (plugin && plugin.enabled) {console.log("All commands:", plugin.manifest.commands);console.log("All panels:", plugin.manifest.panels);// Show the plugin panel// Note that panels can only be made visible// You can't ask to hide a panelplugin.showPanel("simplePanel");// Invoke the commandplugin.invokeCommand("simpleCommand");// Send an payload to the commandconst payload = { message: "Stay hydrated!" };// Invoke the command with the payloadplugin.invokeCommand("commandWithInput", payload.message);} else {// Prompt the user to install/enable the plugin before trying again}} catch (e) {console.error(e);}}
Copied to your clipboard{"id": "Test-requester","name": "Requester","shortname": "3pstarterplugin","version": "1.0.0","main": "index.html","host": { "app": "premierepro", "minVersion": "25.6.0" },"manifestVersion": 5,"requiredPermissions": {"localFileSystem": "request","clipboard": "readAndWrite","ipc": { "enablePluginCommunication": true }},"entrypoints": [{"id": "starterpanel","type": "panel","minimumSize": { "width": 430, "height": 500 },"maximumSize": { "width": 2000, "height": 2000 },"preferredDockedSize": { "width": 230, "height": 300 },"preferredFloatingSize": { "width": 400, "height": 300 },"label": { "default": "PremierePro IPC Panel" },"icons": [{"width": 23, "height": 23,"path": "icons/dark.png", "scale": [1,2],"theme": [ "darkest", "dark", "medium" ]},{"width": 23, "height": 23,"path": "icons/light.png", "scale": [1,2],"theme": [ "lightest", "light" ]}]}],"icons": [{"width": 48, "height": 48, "path": "icons/plugin-icon.png","scale": [1,2],"theme": [ "darkest", "dark", "medium", "lightest", "light", "all" ],"species": [ "pluginList" ]}]}
Responder code
Copied to your clipboard<!DOCTYPE html><html><head><script src="main.js"></script><link rel="stylesheet" href="style.css" /></head><body><sp-heading>Responder Plugin</sp-heading><sp-divider></sp-divider><div class="main-div"><sp-body id="plugin-body"> </sp-body></div><footer><sp-button id="clear-btn">Clear messages</sp-button></footer></body></html>
Copied to your clipboardbody { color: white; padding: 16px; }sp-divider { margin-bottom: 20px; }li:before { content: "• "; width: 3em; }#plugin-body {color: var(--uxp-host-text-color-secondary, white);height: 220px; margin-top: 5px; border: 1px solid #808080;border-radius: 4px; padding: 16px; overflow: scroll;}sp-heading { color: var(--uxp-host-text-color-secondary, white); }footer {display: flex; flex-wrap: wrap; justify-content: flex-end; }footer > * { margin: 5px; }footer div { margin-bottom: 1em; width: 100%; }.main-div { position: relative; }.clear-btn {display: none; position: absolute; top: 10px; right: 6px; cursor: pointer;}.main-div:hover .clear-btn { display: inline; }
Copied to your clipboard//global objects.const { entrypoints } = require("uxp");entrypoints.setup({commands: {simpleCommand: () => doThing(),commandWithInput: (args) => doThing(args),},panels: { simplePanel: { show(rootNode) {} },},});// Log messages to the panel's bodyfunction logToPanel(msg) {const bodyElement = document.getElementById("plugin-body");const message =msg === undefined? `Generic message from Requester Plugin <br />`: `<span>Custom message from Requester Plugin: ${msg}</span><br />`;bodyElement.innerHTML += message;}// Commands handlerfunction doThing(args) {console.log("payload", args);// Pass a payload (if any) to the panellogToPanel(args && args.data[0]);}// Clear the panel's bodydocument.getElementById("clear-btn").addEventListener("click", () => {const bodyElement = document.getElementById("plugin-body");if (bodyElement) {bodyElement.innerHTML = "";}});
Copied to your clipboard{"id": "Test-responder","name": "Responder","shortname": "3pstarterplugin","version": "1.0.0","main": "index.html","host": { "app": "premierepro", "minVersion": "25.6.0" },"manifestVersion": 5,"entrypoints": [{"id": "simplePanel","type": "panel","minimumSize": { "width": 430, "height": 500 },"maximumSize": { "width": 2000, "height": 2000 },"preferredDockedSize": { "width": 230, "height": 300 },"preferredFloatingSize": { "width": 400, "height": 300 },"label": { "default": "Main Panel" },"icons": [{"width": 23, "height": 23,"path": "icons/dark.png", "scale": [1,2],"theme": [ "darkest", "dark", "medium" ]},{"width": 23, "height": 23,"path": "icons/light.png", "scale": [1,2],"theme": [ "lightest", "light" ]}]},{"id": "simpleCommand","type": "command","label": {"default": "Simple Command"}},{"id": "commandWithInput","type": "command","label": {"default": "Command With Input"}}],"icons": [{"width": 48, "height": 48, "path": "icons/plugin-icon.png","scale": [1,2],"theme": [ "darkest", "dark", "medium", "lightest", "light", "all" ],"species": [ "pluginList" ]}]}
Additional notes
- You may not see any error if the entrypoint is not found. We recommend using
plugin.manifest.commandsandplugin.manifest.panelsto select from the actual list of entrypoints. Users may have turned off a particular plugin via the Adobe Creative Cloud Desktop App. Before invoking it, check the plugin's availability by usingplugin.enabled. - You cannot pass methods in the payload object.
- Cross-application communication is not supported (e.g., Premiere to Photoshop).
Summary
Inter-plugin communication enables UXP plugins to invoke commands and show panels from other installed plugins within Adobe Premiere.
Key Concepts:
- Requester plugin: This plugin initiates communication and requires the
enablePluginCommunication: truepermission inmanifest.json.- Plugin Manager: Use
pluginManager.pluginsto discover and reference other installed plugins by theirid. - Communication methods:
invokeCommand()to execute commands andshowPanel()to display panels from the target plugin.
- Plugin Manager: Use
- Responder plugin: This plugin receives communication requests, exposes entrypoints in its manifest (no special permissions are needed), and implements the entrypoints in its code.

