Dictation: deliver dictated text as keyboard input, not as a paste #13796
What do you want to change?macOS dictation should reach terminal apps through the same channel as keyboard input. Today the live transcript is rendered as a preedit overlay, and on commit the entire transcript is delivered to the app as a single raw blob (or as bracketed paste, for clipboard-based dictation tools). I'd like Ghostty to stream the dictation's marked-text updates to the app — via the kitty keyboard protocol's preedit events (10 = preedit start, 11 = preedit end, 12 = preedit commit, 13 = preedit update), or by relaying incremental text — so TUI apps receive dictated text through their normal input path: word by word, revisable, exactly like typing. Why do you want to make this change?I work on opencode, a TUI coding agent, and I've been chasing this from the app side. My conviction: voice input is an extension of the keyboard — dictated text and typed text should be indistinguishable to the app. The problem has two parts, and fixing the first one doesn't help:
So multi-line preedit is not the fix. Even perfectly wrapped, the TUI still receives one big block on commit and still treats it as a paste. The only change that makes dictation actually behave like typing is to deliver it like typing: stream the marked text so it arrives through the input path, renders inline in the app's own text component, and revisions replace the marked range like any IME. The kitty preedit events are the standard mechanism for exactly this — and they benefit all IME users, not just dictation. Why this matters now: coding agents are a big reason terminal emulators are heating up again, and voice input (built-in dictation, Wispr, SuperWhisper, Typeless…) is a primary input method for a growing share of those users, for accessibility reasons and otherwise. Downstream apps keep getting more input-sensitive, and the paste/typed distinction keeps leaking into experiences where it shouldn't exist. Related
I'm happy to do the app-side work (opencode/opentui consuming the preedit events), test end-to-end, and iterate. |
Replies: 1 comment 1 reply
|
!vouch |
!vouch