# Windows Plugin windows are detached OS windows that host an existing `contributes.layouts` layout. There is no separate window contribution type. ```ts await ctx.services?.windows.open({ layoutType: "hello-plugin.dashboard", state: { openedFrom: "menu" } }); ``` `windows.open` is the public API for commands that need to make feedback visible to a human. A command handler may still return structured data, but menu clicks do not currently guarantee that return value is displayed. ## Contract - `layoutType` must match a layout type declared by the calling plugin. - The plugin must declare `capabilities: ["ui"]` when it relies on plugin layouts/windows as a human-facing surface. Add `"tooling"` only when the plugin also uses tooling/workspace/task services. - There is no `contributes.windows` manifest key. Windows always host an existing `contributes.layouts` layout. - The host validates the plugin is runtime-active and the layout exists before opening or focusing the window. - Reopening the same plugin/layout pair focuses the existing window. - `state` is JSON-serializable initial window state. The mounted component can later call `setState(next)` to update its local host state. - The window follows IdeA's focused project, matching detached native panel behavior. If no project is focused, the host shows a neutral shell until one is focused. ## Return Value ```ts const win = await ctx.services.windows.open({ layoutType: "hello-plugin.dashboard" }); win.label; win.alreadyOpen; win.surface.layoutType; ``` The returned `label` is a host-owned window identity. Treat it as opaque. ## Typical Menu Flow ```ts ctx.commands?.registerCommand("hello-plugin.open-dashboard", async () => { const win = await ctx.services?.windows.open({ layoutType: "hello-plugin.dashboard", state: { source: "menu" } }); return win ? { status: "opened", message: "Opened dashboard.", alreadyOpen: win.alreadyOpen } : { status: "skipped", reason: "ui-service-unavailable", message: "UI service unavailable." }; }); ```