7.0 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.skills declares read-only agent skills shipped inside the IdeA
plugin package. These skills are IdeA-native: IdeA can expose them in project
plugin settings, assign them to agents, inject them into the agent skill
catalogue, and serve their Markdown body through idea_skill_read for every
supported harness that receives IdeA capabilities, including Claude Code,
Codex, OpenCode local and OpenCode cloud.
{
"contributes": {
"skills": [
{
"id": "unity.build-debug",
"name": "unity-build-debug",
"description": "Diagnose Unity build failures.",
"kind": "workflow",
"path": "skills/unity-build-debug/SKILL.md"
}
]
}
}
Skill contribution rules:
idis stable within the plugin and is used by project/agent assignments.nameis the agent-facing name shown in the injected skill catalogue and accepted byidea_skill_read.descriptionis the short affordance shown before the agent loads the skill.kinddefaults to"workflow";"reference"is also supported.pathmust be a package-relative Markdown file path ending in.md.- Installing a plugin globally is not enough: a project must enable the plugin, then assign the skill to the target agent.
See Project Plugin Assignments for the
.ideai/project-plugins.json schema, validation rules, assignment order, and
agent relaunch requirements.
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.
MCP Server Paths
contributes.mcpServers entries are resolved by the host before starting a
declared MCP server. In command, args, env and cwd, the host expands:
${pluginRoot}to the installed plugin package root.${appDataDir}to the host-owned application data directory.
This substitution is limited to manifest-declared MCP server startup. It is not
available from activate(ctx), ctx.services.workspace or
ctx.services.tasks.runCommand().
Validation
Use the SDK validator in tests or build tooling:
import { assertPluginManifest } from "@idea/plugin-sdk";
assertPluginManifest(JSON.parse(manifestText));