Files
IdeaSDK/docs/manifest.md

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: currently 1.
  • 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 type values declared by contributes.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));