Skip to content

Dictation mode does not show text in real-time in Ghostty [macOS] #2473

Description

@1dancook

Description

The dictation mode on macOS does work in Ghostty, however, the behavior in Ghostty is inconsistent with other applications. Normally, text is inserted into a document as you speak and is basically a real-time visual transcription. It also adapts and updates given further context. This real-time transcription doesn't happen in Ghostty.

Example

I've recorded an example of what this looks like. On the left is textedit.app and the normal way that dictation works on the system. On the right is (vanilla) vim running in Ghostty. Notice that the text only appears in Ghostty after dictation mode is stopped (I press the microphone button on my keyboard).

macos-dictation.mov

Version info

Ghostty: 1134a9c
MacOS: 15.0.1 (24A348)

Other comments

Dictation mode doesn't actually work at all in some other terminal emulators. The fact that it works in Ghostty is already superb! ❤️ There may be an accessibility related impact for this (which personally is not applicable). I wasn't able to find other issues or discussion related to dictation.

Activity

  1. mitchellh commented on Oct 22, 2024

    @mitchellh
    Contributor

    Thanks, I'm supportive of enabling this. It'll require some research.

  2. Jiehong commented on Jan 2, 2025

    @Jiehong

    This issue has a second impact: when starting dictation, the language selection icon is replaced by that up arrow:

    Image

    This means that users can't change the language of dictation at all.

    For me, in Europe, switching languages is a thing happening multiple times a day, and so this is an annoyance.

    Workaround: focus on a different app, switch dictation mode on and change the language. Cancel dictation, and go back to ghostty: the dictation language is the last one used.

  3. tadsn3w commented on Jan 31, 2025

    @tadsn3w

    I had a suggestion, but it was closed because it applies to this one. It’s quite different because on macOS, there are two different things: dictation and voice control. Dictation works as described here, while voice control doesn’t work at all. Voice control shows a red icon scratched out. I’m guessing the icon is the microphone, which isn’t available.

    The amusing aspect is that I require it to function effectively due to my hand pain. So, I had to download SuperWhisperer, another dictation tool, and it performs exceptionally well. The workflow differs from traditional dictation. You must enable SuperWhisperer, and it automatically copies and pastes into the application. Unlike voice typing to Ghost directly, you speak to SuperWhisperer, and at the end, it pastes the content into the application. It works flawlessly.

    What prevents the Mac tools from functioning as intended while allowing superwhisperer to perform its task effectively?

  4. dzonatan commented on Feb 7, 2025

    @dzonatan

    In the AI era, this feature is becoming more and more needed.

  5. injust commented on Feb 12, 2025

    @injust
    Contributor

    This issue has a second impact: when starting dictation, the language selection icon is replaced by that up arrow:

    Image This means that users can't change the language of dictation at all.

    For me, in Europe, switching languages is a thing happening multiple times a day, and so this is an annoyance.

    Workaround: focus on a different app, switch dictation mode on and change the language. Cancel dictation, and go back to ghostty: the dictation language is the last one used.

    Seems like Sublime Text is impacted by the same thing.

    https://forum.sublimetext.com/t/macos-dictation-formatting-commands-not-recognized/66915

  6. fbehrens commented on Jun 28, 2025

    @fbehrens

    This is how it does not work on most recent

    System Version: macOS 15.5 (24F74)
    

    with Voice Control enabled
    Image
    on plain Terminal, it works

  7. bendrucker commented on Jun 29, 2025

    @bendrucker

    This has changed in main compared to the current release. Text now appears in real time rather than buffering until the dictation session ends. But the control remains in the upper left rather than following the cursor input. And has the up arrow rather than a language switcher.

    ghostty.latest.mov

    I believe ded9be3 was the key change, namely this:

    // If we're not in a keyDown event, then we want to update our preedit
    // text immediately. This can happen due to external events, for example
    // changing keyboard layouts while composing: (1) set US intl (2) type '
    // to enter dead key state (3)
    if keyTextAccumulator == nil {
    syncPreedit()
    }

    Dictation does not generate keyDown events.

    I'm looking into what it would take to handle the cursor positioning and the language selection.

    Voice control is a separate feature and probably merits a separate issue once this one is fixed.

  8. bendrucker commented on Jun 29, 2025

    @bendrucker

    Some progress:

    ghostty.progres.mov

    It seems that the NSRect being zero sized prevented the dictation control from tracking the cursor. The control appears above the cursor instead of below and won't move until input flushes the pending text with the white background black text. Then the cursor advances along with the microphone.

    And I even get the language picker:

    ghostty.es.mov

    This is the only change:

    diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift
    index 0a2f2c84..5c6d549d 100644
    --- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift
    +++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift
    @@ -1669,7 +1669,7 @@ extension Ghostty.SurfaceView: NSTextInputClient {
     
             // Ghostty coordinates are in top-left (0, 0) so we have to convert to
             // bottom-left since that is what UIKit expects
    -        let viewRect = NSMakeRect(x, frame.size.height - y, 0, 0)
    +        let viewRect = NSMakeRect(x, frame.size.height - y, cellSize.width, cellSize.height)
     
             // Convert the point to the window coordinates
             let winRect = self.convert(viewRect, to: nil)

    I have to put this down for today but I'll keep exploring when I next have time. If anyone else wants to pick it up from here, feel free.

  9. mitchellh commented on Sep 2, 2025

    @mitchellh
    Contributor

    Thanks @bendrucker I pulled that into #8490. I think I see how to get the last remaining bit working too. I'm going to play with it.

  10. added a commit that references this issue on Sep 2, 2025
    ce94bb9
  11. added this to the 1.2.0 milestone on Sep 2, 2025
  12. mitchellh commented on Sep 2, 2025

    @mitchellh
    Contributor

    Note: opened followup #8493 to track more specific issues. We can continue to open others as we see fit, but the major point of this issue (text showing in real time) is resolved.

  13. yakppal commented on Sep 28, 2026

    @yakppal

    For anyone landing here because Voice Control (not Dictation) still shows a red crossed-out mic in Ghostty: I tracked down the cause.

    Voice Control only turns on its dictation grammar when the focused element's AXValue is settable. Ghostty's SurfaceView exposes a read-only AXValue, so Voice Control treats the terminal as read-only and drops free speech (Console shows EndPhrase did not match any grammars).

    Making AXValue settable is enough. Voice Control never actually writes it; the words still arrive through setMarkedText/insertText, which the surface already sends as typed input:

    extension Ghostty.SurfaceView {
        override func setAccessibilityValue(_ value: Any?) {}
    }

    I checked this by blocking each candidate accessibility attribute in turn. Only a settable AXValue matters.

    Disclosure: I found this while building Proxica, a macOS terminal built on Ghostty for AI coding CLIs (Claude Code, Codex, Gemini CLI, …). It ships with this fix, so Voice Control works there today. I'd be glad to see it land upstream too.

    Draft if you want no code (Proxica mention only):

    Voice Control (as opposed to Dictation) still fails in Ghostty because the terminal surface reports a read-only AXValue, so Voice Control drops free speech. Making AXValue settable fixes it.

    Disclosure: I build Proxica, a macOS terminal based on Ghostty for AI coding CLIs. It includes this fix, so Voice Control dictation works there if you need it now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions