Bug: Codex TUI overrides terminal cursor style in Neovim :terminal
What version of Codex CLI is running?
0.129.0
What subscription do you have?
pro
Which model were you using?
_No response_
What platform is your computer?
_No response_
What terminal emulator and version are you using (if applicable)?
ghostty+neovim 0.12
What issue are you seeing?
Codex emits ESC [ 0 q (DECSCUSR reset to default cursor shape) on every frame when not in Vim insert mode. In embedded terminal emulators like Neovim's built-in
:terminal, this actively overrides the host's configured cursor style (e.g. guicursor), forcing a blinking block cursor instead of the user's configured bar
cursor.
Environment
- Codex CLI: v0.129.0
- Neovim: 0.11+ (built-in terminal with "actual cursor" support)
- OS: macOS (Apple Silicon)
- Terminal: Neovim :terminal buffer
What steps can reproduce the bug?
Steps to Reproduce
- Configure Neovim with a bar cursor for terminal mode:
-- ~/.config/nvim/lua/init.lua
vim.o.guicursor = "n-sm-ve:block-Cursor,t-i-c-ci:ver16-Cursor,r-cr-v-o:hor7-Cursor"
- Open Neovim and enter a :terminal buffer.
- Confirm the cursor is a vertical bar (as configured by t:ver16-Cursor).
- Run codex inside the terminal buffer.
- Observe the cursor changes to a blinking block, ignoring the Neovim guicursor setting.
Minimal Reproduction (without Codex)
Inside a Neovim :terminal buffer, run:
printf '\033[0 q'
This sends the same escape sequence Codex emits, and the cursor changes from bar to blinking block — confirming the issue is the ESC [ 0 q escape.
Expected Behavior
When Codex has not intentionally changed the cursor style (i.e., not in Vim insert mode), it should not emit any cursor-shape escape sequence. The host
terminal's cursor configuration should be respected.
Actual Behavior
Codex emits SetCursorStyle::DefaultUserShape (ESC [ 0 q) on every render frame as the default cursor style. In embedded terminals, this is an active reset that
overrides the parent's cursor configuration, not a no-op.
Root Cause
The cursor_style() method in chat_composer.rs (line 4219) returns SetCursorStyle::DefaultUserShape for all non-Vim-insert states:
fn cursor_style(&self, _area: Rect) -> crossterm::cursor::SetCursorStyle {
if self.textarea.uses_vim_insert_cursor() {
crossterm::cursor::SetCursorStyle::SteadyBar
} else {
crossterm::cursor::SetCursorStyle::DefaultUserShape // ← the problem
}
}
This is also the default in renderable.rs (line 20-21) and used in custom_terminal.rs for initialization and reset.
DefaultUserShape is not "do nothing" — it actively sends ESC [ 0 q to the terminal. In standalone terminals this resolves to the user's configured default, but
in embedded terminals (Neovim, tmux with cursor passthrough disabled, etc.) it resolves to "blinking block" which may not match the host's configuration.
What is the expected behavior?
_No response_
Additional information
_No response_
3 Comments
As far as I understand, this was introduced in 0.129.0 and is not Neovim specific. Codex suddenly started overriding the cursor style instead of respecting the cursor shape configured by the shell/terminal. For example, even when my cursor is configured as a bar, opening Codex standalone shows a block cursor. This behavior did not exist before.
yes, starting codex in a regular xterm session will change the cursor type to a blinking block. Quitting codex leaves the cursor at this state w/o resetting original behavior.
I can confirm this issue also affects old Konsole versions.
In my case, Codex emits DECSCUSR cursor-style sequences like ESC [ 5 SPACE q. xterm handles them correctly, but Konsole 2.14.2 does not support them and renders the final "q" literally on screen.
Changing TERM or terminfo did not help, because the sequence appears to be emitted directly by Codex.
As a temporary workaround, I patched the musl binary by replacing DECSCUSR sequences with NUL bytes while preserving binary size/offsets:
https://gist.github.com/cycne/ce8754d8adf25494431239bf9e53385b
A proper fix would probably be a config option to disable cursor-style escape emission, or avoiding DECSCUSR unless the terminal is known to support it.