Cursor blink is suppressed indefinitely by continuous child output — blink phase resets on all pty output, not just keyboard input #13286
Unanswered
sambatia
asked this question in
Issue Triage
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
Ghostty resets the cursor-blink phase on every burst of child pty output, throttled to once per 500 ms. Each reset pins the cursor to its visible phase and restarts the 600 ms blink timer. Any program that writes to the terminal more often than ~600 ms sustained — spinners, progress bars, agent CLIs (Claude Code etc.), terminal multiplexers rendering animated UI — therefore suppresses cursor blink entirely and indefinitely, even with
cursor-style-blink = trueset explicitly.The code comment says the intent is "Whenever a character is typed", but the reset lives in the pty read path (
processOutputLocked), so it fires for all child output, not typing.Reproduction
Ghostty 1.3.1 (stable, macOS), default config or
cursor-style-blink = true:The cursor stops blinking the moment the loop starts and stays solid for as long as it runs. Ctrl-C → blinking resumes within a second. Any output interval below ~0.6 s reproduces it; at 0.7 s+ the cursor blinks erratically (phase keeps restarting).
Mechanism (verified on main @ 53bd14f, present in v1.3.1)
src/termio/Termio.zig—processOutputLockedpushesreset_cursor_blinkfor any read data, throttled to once per 500 ms:ghostty/src/termio/Termio.zig
Lines 652 to 674 in 53bd14f
src/renderer/Thread.zig— the handler setscursor_blink_visible = trueand resets the timer toCURSOR_BLINK_INTERVAL(600 ms):ghostty/src/renderer/Thread.zig
Lines 448 to 461 in 53bd14f
ghostty/src/renderer/Thread.zig
Line 21 in 53bd14f
Reset throttle (500 ms) < blink interval (600 ms), so sustained output restarts the timer before the first off-phase can ever fire → cursor permanently solid.
Real-world impact
Found while debugging "cursor never blinks" inside the herdr terminal multiplexer: its client repaints animated UI (agent spinners) continuously, so the host cursor never blinks regardless of Ghostty configuration. The same applies to any long-running TUI with an animated element — while a Claude Code / codex spinner is animating, the input cursor goes solid.
cursor-style-blink = truesilently has no effect in these sessions, which reads as a config bug to users.Expected behavior
Blink-phase reset should track keyboard input (the stated intent of the comment) rather than child output, so that output cadence doesn't disable blinking. Resetting on typing is the common terminal behavior users expect (cursor solid while typing, blinking when idle); resetting on output makes blink dependent on whatever the foreground app happens to print.
Suggested direction
Move the
reset_cursor_blinkpush from the pty read path to the keyboard input path (or additionally gate it on recent keyboard activity). If output-based reset is intentional for some use case, a config option to scope it to input only would solve this.Related but distinct: #8003 (cursor blink timer causes full redraws — efficiency, not phase-reset semantics). Searched issues + discussions; found no existing report of this behavior.
Environment
main@ 53bd14fcursor-style = block,cursor-style-blink = true,shell-integration = detectAll reactions