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_
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗