# Menus Menus are declared in the manifest and implemented by registering command handlers during activation. ```json { "contributes": { "menus": [ { "id": "hello-plugin.menu", "label": "Hello Plugin", "topLevel": true, "order": 100 } ], "menuItems": [ { "id": "hello-plugin.open.item", "targetMenuId": "hello-plugin.menu", "label": "Open Dashboard", "command": "hello-plugin.open", "order": 10, "when": "projectOpen" } ] } } ``` Then register the command id: ```ts export function activate(ctx: ActivateContext): void { const disposable = ctx.commands?.registerCommand("hello-plugin.open", async () => { const win = await ctx.services?.windows.open({ layoutType: "hello-plugin.dashboard" }); return win ? { status: "opened", alreadyOpen: win.alreadyOpen } : { status: "skipped", reason: "ui-service-unavailable", message: "UI service unavailable." }; }); if (disposable) ctx.subscriptions.push(disposable); } ``` ## Rules - There is no separate `contributes.commands` collection. A command can only be registered if at least one manifest `menuItems[].command` or `slashCommands[].command` entry declares that exact id. - A missing command handler is surfaced by the host as a retryable reload error; menu clicks must never fail silently. - A registered handler's rejected promise is not swallowed: the host logs the plugin id, command id, status, reason and message, then presents a generic retryable error without raw payloads. In particular, return/await `services.windows.open(...)` so native-window failures follow this path. - An open/focus handler returns `status: "opened"` whether `alreadyOpen` is `false` (new window) or `true` (existing window focused). Neither success produces an alert. - Keep diagnostic views reachable when optional executables such as Git, ADB or Gradle are missing. Let the view explain that degraded state instead of skipping the menu action before opening it. - A handler owns precondition checks and feedback. See [Commands And Feedback](commands-and-feedback.md). - Menu item `when` expressions are evaluated by the host; unsupported or false conditions hide/disable the item according to host policy. ## Targets `targetMenuId` can refer to a plugin top-level menu id or a host menu id exposed by IdeA. Prefer a plugin top-level menu for plugin-specific workflows and host menus only when the action naturally belongs beside native actions.