I am trying to figure out a way to detect whether the current terminal/connection (and under a tmux session as well) is through mosh or not.

From this thread, I found which pseudo-terminal session I am currently on:

$ tty

So, I need to some information of the process that spawned this pseudo-terminal, or owns this tty as a children. With the information, perhaps I might be able to determine whether it is from sshd or mosh. But how can I do that?

Another challenge: If the current shell is under tmux, the retrieved tty might not match the sshd/mosh-server information since tmux also allocates another pseudo-terminal. Regardless of how the tmux session was created, I'll need to distinguish my current connection is from SSH or mosh. How will it be possible?

Some trials:

(1) For SSH, it was possible to find the sshd process that matches the tty:

$ ps x | grep sshd | grep 'pts\/27'
 5270 ?        S      0:00 sshd: wookayin@pts/27

So I can know the current connection is through SSH. However, through mosh, I could not find any relevant information.

(2) Using environment variables like SSH_CLIENT or SSH_TTY might not work because both ssh/mosh set these variables, and it is even wrong inside a tmux session.

  • Using ps -p $PPID, I could detect the parent is mosh-server, tmux: server or sshd. However, tmux+mosh is still a complicated situation. – Jongwook Choi Oct 1 '17 at 23:26

I have come up with a decent solution to this, and wrapped it as a simple script: is_mosh:


has_ancestor_mosh() {
    pstree -ps $1 | grep mosh-server

is_mosh() {
    # argument handling
    for arg in "$@"; do
        case $arg in
          -v|--verbose) local VERBOSE=YES ;;
          *) ;;

    if [[ -n "$TMUX" ]]; then
        # current shell is under tmux
        local tmux_current_session=$(tmux display-message -p '#S')
        local tmux_client_id=$(tmux list-clients -t "${tmux_current_session}" -F '#{client_pid}')
        # echo $tmux_current_session $tmux_client_id
        local pid="$tmux_client_id"
        local pid="$$"

    local mosh_found=$(has_ancestor_mosh $pid)   # or empty if not found
    if [[ -z "$mosh_found" ]]; then
        return 1;    # exit code 1: not mosh

    test -n "$VERBOSE" && echo "mosh"
    return 0;        # exit code 0: is mosh

if [ -n "$ZSH_EVAL_CONTEXT" ]; then
  case $ZSH_EVAL_CONTEXT in *:file) sourced=1;; esac
elif [ -n "$BASH_VERSION" ]; then
  [ "$0" != "$BASH_SOURCE" ] && sourced=1
  case ${0##*/} in sh|dash) sourced=1;; esac
if [[ $sourced == 0 ]]; then
  is_mosh $@

The idea is quite simple: (i) to find the tmux client that is attached to the current tmux session, and then (ii) to search its ancestor processes to find if there is a mosh process.

It might not be complete, depending on environments, but I could successfully detect and apply 24-bit color feature only if it's not running under mosh (as mosh doesn't support 24-bit colors). Here is a solution (add these lines to your ~/.vimrc):

" 24-bit true color: neovim 0.1.5+ / vim 7.4.1799+
" enable ONLY if TERM is set valid and it is NOT under mosh
function! s:is_mosh()
  let output = system("is_mosh -v")
  if v:shell_error
    return 0
  return !empty(l:output)

function s:auto_termguicolors()
  if !(has("termguicolors"))

  if (&term == 'xterm-256color' || &term == 'nvim') && !s:is_mosh()
    set termguicolors
    set notermguicolors
call s:auto_termguicolors()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.