I am running Arch Linux locally. When I connect to my remote Debian 10 server via ssh, the cursor behaves in an awkward way:

As long as every command returns statuscode 0, everything is fine. When another code is returned, the cursor and the right prompt are shifted to the left by 2 characters, as shown below. The first prompt is normal, the second after pressing Ctrl+C:

~ »                    user@hostname
~ »            130 ↵ user@hostname

I have manually changed the line of dashes afterwards to show where the cursor is: below the |. I am in fact overriding the » when I start typing a command.

When I then try to use a command from history and change it, I change it at a different character than is shown on the screen, which is quite confusing and annoying.

After the next command that returned statuscode 0, the cursor is normal again.

This seems to be happening accross terminals (I tried in the console and using Alacritty and URXVT).

I am using the "af-magic" - theme. When I switch to another theme that does not show status codes, the problem disappears. It is the same though for other themes that do show the statuscode (e.g. "smt"). So something about the statuscode display seems to be causing the issue.

My .zshrc is the same both locally and remotely. Locally, I don't have that problem.


## oh my zsh
export ZSH="$HOME/.config/zsh/oh-my-zsh"


  git vi-mode zsh-autosuggestions history-substring-search

source $ZSH/oh-my-zsh.sh

## Load aliases
[ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc"

## vim mode config
# ---------------
bindkey -M vicmd 'k' history-substring-search-up
bindkey -M vicmd 'j' history-substring-search-down

# Activate vim mode.
bindkey -v

# autosuggest config
bindkey '^ ' autosuggest-accept

# Remove mode switching delay.

# Change cursor shape for different vi modes.
function zle-keymap-select {
  if [[ ${KEYMAP} == vicmd ]] ||
     [[ $1 = 'block' ]]; then
    echo -ne '\e[1 q'

  elif [[ ${KEYMAP} == main ]] ||
       [[ ${KEYMAP} == viins ]] ||
       [[ ${KEYMAP} = '' ]] ||
       [[ $1 = 'beam' ]]; then
    echo -ne '\e[5 q'
zle -N zle-keymap-select

_fix_cursor() {
   echo -ne '\e[5 q'

Any tips on how to solve this?

  • As it stands, I don't really understand your question. It's unclear what the first code block is meant to represent. If it's your prompt, it's unclear where you enter commands in there. We don't see the code that's meant to set your $PS1/$PROMPT. It's unclear what your _fix_cursor is meant to do or if it's meant to be part of the problem or an attempt to fix it. It would help if you removed the parts that are not relevant to your problem. Given your answer, it's likely it's only the value of $PS1 that is relevant (and/or the code that generates the prompt if it's dynamic). Commented Feb 13, 2021 at 11:35

1 Answer 1


My locale was not set. I set it now, and it works!

You must log in to answer this question.

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