5.2 KiB
Manifest
Every plugin package has an idea-plugin.json file at the archive root.
For development installs, the same file must exist at the root of the plugin
source directory selected in IdeA with Paramètres > Plugins > Installer depuis un dossier….
Minimal Plugin Directory
A plugin directory must contain the manifest at its root and a built ESM
entrypoint matching the manifest main field.
my-plugin/
├── idea-plugin.json
├── package.json
├── tsconfig.json
├── src/
│ └── index.ts
└── dist/
└── index.js
Create the directory:
mkdir -p my-plugin/src
cd my-plugin
npm init -y
npm install --save-dev typescript @idea/plugin-sdk
Use a package script that emits JavaScript into dist/:
{
"type": "module",
"scripts": {
"build": "tsc -p tsconfig.json"
},
"devDependencies": {
"@idea/plugin-sdk": "^0.3.0",
"typescript": "^5.0.0"
}
}
When developing against a local SDK checkout instead of a published package,
replace the SDK dependency with a file: reference, for example:
{
"devDependencies": {
"@idea/plugin-sdk": "file:../IdeaSDK",
"typescript": "^5.0.0"
}
}
Minimal tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"strict": true
},
"include": ["src"]
}
Minimal src/index.ts:
import type { IdeAPluginModule } from "@idea/plugin-sdk";
const plugin: IdeAPluginModule = {
activate(ctx) {
ctx.logger.info("plugin activated", { pluginId: ctx.pluginId });
}
};
export default plugin;
Build before installing or reloading:
npm run build
Then install the my-plugin/ directory in IdeA. For hot reload, keep installing
from the directory, rebuild after source changes, then run idea_plugin_reload
for the installed plugin id. Do not install from a ZIP archive for a hot-reload
development loop.
{
"ideaPluginManifestVersion": 1,
"id": "com.example.hello-plugin",
"displayName": "Hello Plugin",
"publisher": "Example",
"version": "0.1.0",
"description": "Example IdeA plugin.",
"main": "dist/index.js",
"engines": {
"idea": ">=0.1.0"
},
"trustLevel": "full",
"capabilities": ["ui", "tooling"],
"activationScope": "app",
"contributes": {
"menus": [],
"menuItems": [],
"layouts": [],
"mcpServers": []
}
}
Required Fields
ideaPluginManifestVersion: currently1.id: stable lowercase id using letters, digits, dots and dashes. It must start and end with an alphanumeric character.displayName: human-readable plugin name.version: semver version.main: package-relative ESM entrypoint loaded by IdeA.trustLevel: currently"full".
Optional Fields
description,publisher.engines.idea: host compatibility hint.activationScope:"app"by default, or"project"when activation needs a focused project immediately.capabilities:"ui","tooling"and/or"mcp".
Contributions
contributes.layouts is the only surface for plugin layouts. The same layout
contribution can be mounted inside an IdeA layout cell or opened in a detached OS
window. Do not add a separate manifest contribution type for windows.
For a command that opens a visible plugin window, declare both the menu command and the layout type:
{
"ideaPluginManifestVersion": 1,
"id": "com.example.unity-plugin",
"displayName": "Unity Developer Tools",
"publisher": "Example",
"version": "0.1.0",
"description": "Unity integration for IdeA.",
"main": "dist/index.js",
"engines": {
"idea": ">=0.1.0"
},
"trustLevel": "full",
"capabilities": ["ui", "tooling"],
"activationScope": "app",
"contributes": {
"menus": [
{
"id": "unity-plugin.menu",
"label": "Unity Developer Tools",
"topLevel": true,
"order": 100
}
],
"menuItems": [
{
"id": "unity-plugin.health.item",
"targetMenuId": "unity-plugin.menu",
"label": "Health",
"command": "unity-plugin.health",
"order": 10,
"when": "projectOpen"
}
],
"layouts": [
{
"type": "unity-plugin.health",
"label": "Unity Health",
"component": "UnityHealth",
"order": 10
}
]
}
}
capabilities: ["ui"] is required when a plugin relies on layouts or windows as
human-facing UI. Add "tooling" when the same plugin uses workspace, task,
tooling or terminal services. The contributes.layouts[].type value is the
public id used by both ctx.layouts.register({ type, component }) and
ctx.services.windows.open({ layoutType }).
Contribution ids are part of the runtime contract:
- commands can only register ids declared by
contributes.menuItems[*].command; - layouts can only register
typevalues declared bycontributes.layouts; services.windows.open({ layoutType })only accepts a layout type declared by the calling plugin.
Validation
Use the SDK validator in tests or build tooling:
import { assertPluginManifest } from "@idea/plugin-sdk";
assertPluginManifest(JSON.parse(manifestText));