RPC extension UI protocol
Extension UI Protocol
Extensions can request user interaction viactx.ui.select(), ctx.ui.confirm(), etc. In RPC mode, these are translated into a request/response sub-protocol on top of the base command/event flow.
There are two categories of extension UI methods:
- Dialog methods (
select,confirm,input,editor, andquestionnairefor a client that opted in): emit anextension_ui_requeston stdout and block until the client sends back anextension_ui_responseon stdin with the matchingid. - Fire-and-forget methods (
notify,setStatus,setWidget,setTitle,set_editor_text): emit anextension_ui_requeston stdout but do not expect a response. The client can display the information or ignore it.
timeout field, the agent-side will auto-resolve with a default value when the timeout expires. The client does not need to track timeouts.
Some ExtensionUIContext methods are not supported or degraded in RPC mode because they require direct TUI access:
custom()returnsundefinedsetWorkingMessage(),setWorkingIndicator(),setFooter(),setHeader(),setEditorComponent()are no-opsgetEditorText()returns""setToolsExpanded()andgetToolsExpanded()maintain context-local expansion state;getChatRenderSettings().toolOutputExpandedreports the same value. A same-valuesetToolsExpanded()call is a no-op and does not request a custom-UI render. This state is not sent through the client extension-UI protocol.pasteToEditor()delegates tosetEditorText()(no paste/collapse handling)getAllThemes()returns[]getTheme()returnsundefinedsetTheme()returns{ success: false, error: "..." }
ctx.mode is "rpc" and ctx.hasUI is true in RPC mode because the dialog and fire-and-forget methods are functional via the extension UI sub-protocol. Use ctx.mode === "tui" to guard TUI-specific features like custom() that require a real terminal.
Extension UI Requests (stdout)
All requests havetype: "extension_ui_request", a unique id, and a method field.
select
Prompt the user to choose from a list. Dialog methods with atimeout field include the timeout in milliseconds; the agent auto-resolves with undefined if the client doesn’t respond in time.
extension_ui_response with value (the selected option string) or cancelled: true.
confirm
Prompt the user for yes/no confirmation.extension_ui_response with confirmed: true/false or cancelled: true.
input
Prompt the user for free-form text.extension_ui_response with value (the entered text) or cancelled: true.
editor
Open a multi-line text editor with optional prefilled content.extension_ui_response with value (the edited text) or cancelled: true.
questionnaire
A wholeask_user_question call: one to four questions, each with a short header, its options (label, description, optional markdown preview) and multiSelect. Sent only to a client that turned the questionnaire capability on with set_extension_ui_capabilities; otherwise ask_user_question fails in RPC mode, because it needs a terminal.
extension_ui_response with answers, one per answered question, or cancelled: true. Each answer names its questionIndex and repeats its question, and its kind says what the user chose:
option: one of the question’s options;answeris its label.multi: for amultiSelectquestion;answerisnullandselectedlists the chosen labels.custom: free text typed instead of an option (single-select questions without previews);answeris the text.chat: the user wants to talk it over instead;answeris their text ornull.
notify
Display a notification. Fire-and-forget, no response expected.notifyType field is "info", "warning", or "error". Defaults to "info" if omitted.
setStatus
Set or clear a status entry in the footer/status bar. Fire-and-forget.statusText: undefined (or omit it) to clear the status entry for that key.
setWidget
Set or clear a widget (block of text lines) displayed above or below the editor. Fire-and-forget.widgetLines: undefined (or omit it) to clear the widget. The widgetPlacement field is "aboveEditor" (default) or "belowEditor". Only string arrays are supported in RPC mode; component factories are ignored.
setTitle
Set the terminal window/tab title. Fire-and-forget.set_editor_text
Set the text in the input editor. Fire-and-forget.Extension UI Responses (stdin)
Responses are sent for dialog methods only (select, confirm, input, editor, questionnaire). The id must match the request. A questionnaire is answered with answers (see questionnaire).
Value response (select, input, editor)
Confirmation response (confirm)
Cancellation response (any dialog)
Dismiss any dialog method. The extension receivesundefined (for select/input/editor) or false (for confirm).