(note: I wrote this question on stackoverflow, but got flagged as offtopic, so I'm re-writing it here)

Here's what I want:

Consistent behavior (as much as possible) between Vim, MacVim, zsh with vi-mode and tmux. In Vim and MacVim the insert-normal mode switch is working just fine, and in Vim case, works fine by running Vim both from zsh shell and within tmux. The Zsh shell also works well with the switch by doing this: https://raw.github.com/ramiroaraujo/dotfiles/master/zsh/vi-mode.zsh, which I don't seem to remember where I found it.

Now this doesn't work within tmux. The cursor stays the same in insert and normal mode, and it's really naggy. Suposly, the code avove should kinda work if a correct escape sequence is printed when in tmux, and I found this http://reza.jelveh.me/2011/09/18/zsh-tmux-vi-mode-cursor, but seems kind of old and looks like it's for bash, not zsh. Any help on any direction is very welcomed :)


2 Answers 2


After a few hours of diving into a wide variety of GitHub issues and man-pages I've found a setup that works for me, achieving what I believe you set out to achieve.

I am using rxvt-unicode v9.22, tmux 2.9a, neovim v0.4.2 and zsh 5.7.1 under Arch Linux. My setup is configured to use non-blinking beam cursor in insert mode, and non-blinking block cursor in normal mode.

For zsh, I use vi-mode with the following in my .zshrc:

bindkey -v

# Change cursor with support for inside/outside tmux
function _set_cursor() {
    if [[ $TMUX = '' ]]; then
      echo -ne $1
      echo -ne "\ePtmux;\e\e$1\e\\"

function _set_block_cursor() { _set_cursor '\e[2 q' }
function _set_beam_cursor() { _set_cursor '\e[6 q' }

function zle-keymap-select {
  if [[ ${KEYMAP} == vicmd ]] || [[ $1 = 'block' ]]; then
zle -N zle-keymap-select
# ensure beam cursor when starting new terminal
precmd_functions+=(_set_beam_cursor) #
# ensure insert mode and beam cursor when exiting vim
zle-line-init() { zle -K viins; _set_beam_cursor }

For my tmux configuration, the only important lines are:

set -g default-terminal "tmux-256color"
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q'

To make sure that neovim behaves correctly for urxvt, $TERM needs to be correct. I do this with .Xresources with the following line (don't forget to merge afterwards with xrdb -merge ~/.Xresources):

URxvt*termName: rxvt-256color

Now for neovim, no configuration should be necessary, other than making sure not to tamper with guicursor. Some GitHub issues mention setting set guicursor= in your init.vim, however my setup does not work if I add that.

Hope this setup is reproducible given what I've provided, otherwise my dotfiles are available on GitHub.

  • for me this is making an underline cursor when triggering vi mode in tmux. in the rest, it works.
    – alexzander
    Jul 9, 2021 at 17:32

try this command on your terminal (with enabling zsh-vi-mode/vi-mode plugin):

export VI_MODE_SET_CURSOR=true

if it works add it to /etc/zsh/zshrc or ~/.zshrc

  • Did not work for me.
    – Yar
    Dec 23, 2022 at 5:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .