Just tested a few Korean IME related discussion, can confirm that this is still happening on tip (c41c6b81a)
Discussed in https://github.com/ghostty-org/ghostty/discussions/9213
Originally posted by icedac October 15, 2025
https://github.com/user-attachments/assets/3cf03ca0-d6d4-4430-9a77-be2e4dd72d33
Title: [Bug] Korean IME: Initial syllable composition fails on first input
Description
When using the Korean IME in the Ghostty terminal on macOS, the initial consonant (Jamo) of the first typed syllable is immediately committed to the terminal instead of entering a pre-edit state. When the subsequent vowel is typed, the initial consonant disappears, and a new composition begins, resulting in the loss of the first consonant.
This issue only occurs on the very first attempt to type Korean on changing English to Korean. Subsequent attempts to types work correctly.
Environment
-
Ghostty Version: 1.2.2
-
Operating System: macOS
System Version: macOS 15.5 (24F74)
Kernel Version: Darwin 24.5.0
Secure Virtual Memory: Enabled
System Integrity Protection: Enabled
Time since boot: 29 days, 1 hour, 13 minutes
Model Name: MacBook Pro
Model Identifier: Mac15,8
Chip: Apple M3 Max
Total Number of Cores: 16 (12 performance and 4 efficiency)
Memory: 128 GB
System Firmware Version: 11881.121.1
OS Loader Version: 11881.121.1- Shell: zsh
- Input Method: Standard macOS Korean IME (2-Set Korean)
Steps to Reproduce
- Launch the Ghostty terminal.
- Switch the system input method to Korean.
- Attempt to type the word "한글" (Hangeul) by pressing the keys
g,k,sin sequence. - Problem: The moment you press
g(for the characterㅎ), it is rendered directly to the terminal instead of being held in a pre-edit buffer (which is typically indicated by an blinking cursor box or curosr underline). - When you then press
k(for the vowelㅏ), the previously committedㅎcharacter remain in the terminal, and only the input starts fresh fromㅏ. - The final result is incorrect, forming
ㅏㄴ(ks) after 'ㅎ' instead of the intended한(gks).
Expected Behavior
When the key for the initial consonant ㅎ is pressed, it should be held in the IME's pre-edit buffer, awaiting the next vowel for composition. It should not be committed to the terminal immediately. Typing the subsequent vowel ㅏ should correctly combine with the buffered ㅎ to form the syllable 하.
Actual Behavior
The initial consonant is prematurely committed to the terminal as a final character. When the next vowel is typed, this committed consonant is ignored, and a new composition process begins. This bug only affects the first attempt at Korean input on changing English to Korean; subsequent attempts works correctly, as demonstrated in the attached video.
Additional Context
This bug significantly impacts the user experience for those who type in Korean, causing constant interruptions and errors. A review of how the terminal handles IME composition for complex script languages seems necessary.
Activity
10Is this still happening on the latest tip version? I couldn't reproduce it, but my environment may differ from yours.
Is this still happening on the latest tip version? I couldn't reproduce it, but my environment may differ from yours.
Is this still happening on the latest tip version? I couldn't reproduce it, but my environment may differ from yours.
Yes I'm on macOS 27, it only happens when the first input after a surface is created, like creating a new tab, and type there.
Is this still happening on the latest tip version? I couldn't reproduce it, but my environment may differ from yours.
Yes I'm on macOS 27, it only happens when the first input after a surface is created, like creating a new tab, and type there.
Is this still happening on the latest tip version? I couldn't reproduce it, but my environment may differ from yours.
Yes I'm on macOS 27, it only happens when the first input after a surface is created, like creating a new tab, and type there.
This reproduced on my old M3 Max, and now I'm on an M5 Max where it still happens — so I haven't been able to use Ghostty.
However, I also picked up a Mac Studio with an M3 Ultra, and Korean renders correctly there. So the issue occurs on both of my MacBooks but not on the Mac Studio, which is odd. It's specific to Ghostty as well — Korean inputs fine in other terminals. (iterm2, wezTerm)
Also, when I originally hit this bug I tried to fix it myself — I rebuilt and iterated maybe a dozen times with Opus 4.1, but it wasn't up to the task and I never got to a working fix, so I never opened a PR. That said, I have a feeling I could crack it now with Fable and gpt-5.6-sol. I'll give it another shot when I have time.
This reproduced on my old M3 Max, and now I'm on an M5 Max where it still happens — so I haven't been able to use Ghostty.
However, I also picked up a Mac Studio with an M3 Ultra, and Korean renders correctly there. So the issue occurs on both of my MacBooks but not on the Mac Studio, which is odd. It's specific to Ghostty as well — Korean inputs fine in other terminals. (iterm2, wezTerm)
Also, when I originally hit this bug I tried to fix it myself — I rebuilt and iterated maybe a dozen times with Opus 4.1, but it wasn't up to the task and I never got to a working fix, so I never opened a PR. That said, I have a feeling I could crack it now with Fable and gpt-5.6-sol. I'll give it another shot when I have time.
Possibly related: I can consistently reproduce a first-input-context failure in Quick Terminal on macOS. This is not the normal tab/new-surface path reported here, but it appears to be the same class of IME initialization race.
Environment:
- Ghostty tip
600003455 - macOS 26.5
- Squirrel (Rime) Chinese input method
Reproduction:
- Focus another application and switch to Squirrel.
- Open Ghostty Quick Terminal with its global shortcut.
- Type
niimmediately.
Before the fix, the Quick Terminal panel became key but the IME context was inactive, so the expected preedit/candidate window did not appear. Squirrel's corresponding report/logs are in rime/squirrel#1162.
The relevant detail is that Quick Terminal uses an NSPanel with .nonactivatingPanel. In QuickTerminalController.makeWindowKey, window.isKeyWindow can become true while NSTextInputContext.current !== focusedSurface.inputContext. The current early return therefore treats an incomplete input-focus state as ready.
A local fix that works for me:
- call
makeFirstResponder(focusedSurface)as before; - activate
focusedSurface.inputContextwhen it is notNSTextInputContext.current; - invalidate the input context's character coordinates;
- stop retrying only when the window is key, the focused surface is first responder, and its input context is current;
- re-run
makeWindowKeyafterNSApp.activateeven if the panel already reports itself as key.
With that change, Squirrel preedit and the candidate window appear correctly when Quick Terminal is opened from a background application. Ghostty's full macOS test suite and a ReleaseLocal build also pass.
AI disclosure: I used OpenAI Codex to assist with diagnosis, implementation, and validation. I reviewed and understand the final change and the input-focus conditions described above.
That's strange. I haven't seen this before, though I am running into the backspace issue (ghostty-org/ghostty#14797). I'm on macOS 27.0.1, using a nightly build of Ghostty.
Is this still happening on the latest tip version? I couldn't reproduce it, but my environment may differ from yours.