Summary
Plugins currently cannot generate custom UI or interactive surfaces. The universal manifest has no UI/component/preview/webview extension points, and ToolResult/HookResult only support text output. This issue tracks designing a minimal, progressive universal extension point for plugin-generated custom UI, including auto-generated web previews.
Motivation
Users want plugins to be able to:
- Render rich output (markdown, HTML, iframe) from tools/hooks without the user manually setting up a Python/Node/Vite HTTP server.
- Contribute panels, widgets, or preview surfaces to the agent UI.
- Generate web previews automatically from plugin code.
Current State
ToolResult in packages/core/src/types.ts is string | { title?, output: string, metadata? }.
HookResult only supports systemMessage, additionalContext, block, reason, suppressOutput.
- Only Pi Mono has an explicit runtime UI API (
ctx.ui.toast()); no other adapter exposes UI surfaces.
- Target harness survey:
- Claude Code: CSS themes only (
themes manifest field).
- Codex, Copilot CLI, Gemini, Kimi, OpenCode: no UI contribution surface.
- Pi Mono: rich runtime UI API, but only partially reflected in adapter codegen.
Proposed Direction
Design a minimal, opt-in universal UI extension point that degrades gracefully on platforms that do not support it.
Option A — Rich ToolResult / HookResult attachments (recommended first step)
export type UiRenderSpec =
| { type: 'markdown'; content: string }
| { type: 'html'; content: string; baseUrl?: string }
| { type: 'iframe'; url: string; title?: string }
| { type: 'panel'; title: string; content: string }
| { type: 'widget'; widgetType: string; props?: Record<string, unknown> };
export interface ToolResult {
title?: string;
output: string;
metadata?: Record<string, unknown>;
render?: UiRenderSpec | UiRenderSpec[];
}
export interface HookResult {
// ...existing fields
ui?: UiRenderSpec | UiRenderSpec[];
}
Option B — Top-level manifest ui section (future)
export interface PluginManifest {
// ...existing fields
ui?: {
pages?: UiPage[];
panels?: UiPanel[];
webPreviews?: WebPreview[];
components?: UiComponent[];
};
}
Acceptance Criteria
Classification
- Type: feature
- Effort: L
- Status: For Refinement
Related
- Research plan:
.agents/plans/2026-06-15-builtins-ui-research.md
Summary
Plugins currently cannot generate custom UI or interactive surfaces. The universal manifest has no UI/component/preview/webview extension points, and
ToolResult/HookResultonly support text output. This issue tracks designing a minimal, progressive universal extension point for plugin-generated custom UI, including auto-generated web previews.Motivation
Users want plugins to be able to:
Current State
ToolResultinpackages/core/src/types.tsisstring | { title?, output: string, metadata? }.HookResultonly supportssystemMessage,additionalContext,block,reason,suppressOutput.ctx.ui.toast()); no other adapter exposes UI surfaces.themesmanifest field).Proposed Direction
Design a minimal, opt-in universal UI extension point that degrades gracefully on platforms that do not support it.
Option A — Rich
ToolResult/HookResultattachments (recommended first step)Option B — Top-level manifest
uisection (future)Acceptance Criteria
UiRenderSpectype added topackages/core/src/types.ts.ToolResultandHookResultextended to support optionalrender/uifields.ctx.uito the universal shape where possible.Classification
Related
.agents/plans/2026-06-15-builtins-ui-research.md