Host native widgets
Write this so someone with no background can follow.
Why this page exists
Host chrome negotiation settles one affordance: the Open Shell top context bar, inserted into parent terminal chrome (not hovered over the shell).
CLI apps still need a broader toolkit: color pickers, real GUI text editors, file upload with size validation, and similar interactions that benefit from host-owned GUI rather than stdout or a full TUI rewrite.
This page is that generalization — a structured host widget channel, not a pile of one-off dialogs.
Taxonomy
| Kind | Placement | Owner | Example |
|---|---|---|---|
Shell top bar |
Inserted into host chrome (preferred; never "hover the shell" for this job) |
Open Shell session |
Line mode, arrow/ |
App top bar |
Stacked under the shell top bar |
Active CLI / toolkit |
|
Hover widget |
Floats over terminal content (modal-ish overlay owned by the host, not stdout) |
Host, invoked by CLI (or shell on behalf of a tool) |
Color picker, in-place GUI text editor, file upload with |
|
Settled for shell top bar: prefer inserting a top bar into the parent terminal UI. Hovering a shell-owned bar over the terminal content for that use case is inferior. Keep that choice in host chrome negotiation; do not re-litigate it here. |
Hover widgets are a different kind: they intentionally float because the interaction is transient and modal-ish (pick a color, edit a blob, choose a file). They are not a substitute for inserted session chrome.
Relationship to terminal-gui-prompts
openshellorg/terminal-gui-prompts already promotes confirm and text prompts to native OS dialogs when a desktop is present, while still echoing the question to stdout for pipes/AI.
That library is the narrow precursor:
-
Today: fixed prompt kinds (confirm / text) → OS dialog or TTY fallback
-
Here: open-ended widget types on a host channel (picker, editor, upload, app chrome strip, …)
Treat terminal-gui-prompts as a compatible fallback and early adopter path for simple dialogs, not as the whole product.
When a capable Open Shell / openshellorg/terminal host is present, the same toolkit should prefer the host widget channel; otherwise fall back to terminal-gui-prompts, a TUI, or a classic terminal prompt.
Negotiation (capability probe)
Same shape as host chrome negotiation, widened to a capability catalog:
probe → identify host + desktop/GUI presence
offer → CLI/shell advertises WidgetRequest kinds + constraints
accept → host mounts widget (chrome insert, stacked bar, or float)
reject → fallback chain (see below)
| Step | Detail |
|---|---|
Probe |
Host identity (host chrome negotiation matrix) plus "can float overlays?" / "can stack app chrome?" / "can return binary blobs?" |
Offer |
Structured capability or per-request record (JSONL sketch below). Align with nu-emit / shell-context JSONL style where possible. |
Accept |
Host owns pixels and modal focus; CLI owns domain state and how the returned value is used. |
Reject / timeout / unsupported |
Fallback without retry spam. Optional re-probe on host attach. |
Fallback ladder (by kind)
| Kind | Typical fallbacks (first available) |
|---|---|
Shell top bar |
Display-overlay TUI bar inside Open Shell (never stdout) — see display layers |
App top bar |
In-process TUI strip on display-overlay; or omit chrome and use stdout banners only as last resort (discouraged) |
Hover widget |
terminal-gui-prompts / native OS dialog (confirm, text, file picker); else TUI overlay; else classic stdin prompt |
Protocol sketch (JSONL)
Illustrative only — wire format TBD. One request object per line on a control channel (not mixed into stdout data):
{
"v": 1,
"op": "widget.request",
"id": "req-9f3c",
"type": "file.upload",
"placement": "hover",
"constraints": {
"maxBytes": 10485760,
"accept": ["image/png", "image/jpeg", ".svg"]
},
"return": {
"channel": "blob",
"encoding": "handle"
}
}
| Field | Intent |
|---|---|
|
Widget kind: |
|
Hint: |
|
Type-specific limits — e.g. |
|
How the result comes back: |
|
Correlate request ↔ response; support cancel and timeout. |
Example types (v0 catalog)
type |
Default placement | Notes |
|---|---|---|
|
|
Owned by Open Shell; see host-chrome-negotiation — not a random CLI request |
|
|
Active CLI registers chrome while it owns the interaction |
|
|
Returns |
|
|
Real GUI editor; returns final text or cancel |
|
|
Host validates size/MIME; returns blob handle to the app |
|
|
Overlaps terminal-gui-prompts; prefer host channel when present |
Who owns what
| Concern | Owner | Notes |
|---|---|---|
Host protocol + pixel ownership |
Terminal application — first-class: |
Same integration surface as env-refresh and shell top bar |
Widget request API / toolkit bindings |
Language SDKs + optional promotion layer (evolve terminal-gui-prompts) |
CLIs should not each invent OSC spam |
Overlay / TUI fallback |
Open Shell runtime display-overlay (display layers) |
Never stdout for chrome or modal frames |
Domain result handling |
Calling CLI / shell feature |
Host returns value; app decides semantics |
Non-goals
-
Replacing every TUI — this channel is for interactions that benefit from real GUI
-
Polluting stdout/scrollback with widget frames or base64 blobs
-
Using hover overlays as the primary home for always-on session chrome (shell top bar stays inserted)
-
Requiring every terminal to implement the full catalog before shipping (fallbacks keep CLIs usable)
Open questions (protocol)
-
Transport: dedicated fd / Unix domain socket / named pipe vs multiplexed control plane next to shell-context JSONL?
-
Blob return: opaque host handle + streaming read vs temp file path vs base64 (discourage for large payloads)?
-
Focus / cancel: Esc and Ctrl+C ownership when a hover widget is open — host chrome vs control plane?
-
App top bar lifetime: auto-dismiss on prompt return vs explicit unregister; stacking multiple CLIs in a pipeline?
-
Security: which processes may request
file.upload/ editor; sandbox path allow-lists? -
Capability advertisement: probe once per session vs per widget type; versioning of the catalog?
-
SSH / remote: local host GUI for remote CLI (agent forwarding style) vs always TUI fallback?