I regularly use term-mode then ssh into a remote machine to run bash commands. I want to display the remote machine's hostname in my modeline. I added the relevant code for the modeline but I'm having trouble getting the right values. user-login-name and system-name always give me my local machine's information, since that's where Emacs itself is running.

If it's relevant, I'm using doom-modeline.

1 Answer 1


You'll need some assistance from the remote server for that, but the key functionality already exists in the form of the directory-tracking support implemented in term.el, so you can leverage that.

The gist of it is that the process filter term-emulate-terminal has support for custom Emacs-specific \eAnSiT escape sequences (which it passes to term-handle-ansi-terminal-messages) which can be issued by the shell in order to set Emacs variables term-ansi-at-dir, term-ansi-at-host, and term-ansi-at-user. These are then used for setting default-directory (in particular), but obviously the term-ansi-at-host value also facilitates your requirement.

Refer to the commentary (M-x finder-commentary RET term RET), and isearch for directory tracking. You'll find some code to add to your ~/.bashrc files (not only on your local host, but also on each remote host you will ssh to).

You can then use something like this to include the reported hostname in the mode line:

(add-to-list 'mode-line-misc-info '(term-ansi-at-host (" @" term-ansi-at-host)))

The suggested bash config doesn't actually recover from exiting ssh (you'll be back on the original host, but it will be reporting the host you just exited from), so you'll probably want to enhance that. This is only lightly tested, but:

# Emacs term.el directory tracking support.
dirtrack () {
    printf '\033AnSiTc %s\n' "$PWD"
    printf '\033AnSiTh %s\n' "$HOSTNAME"
    printf '\033AnSiTu %s\n' "$USER"
: ${HOSTNAME=$(uname -n)}
case $TERM in
        cd()    { command cd    "$@" && printf '\033AnSiTc %s\n' "$PWD"; }
        pushd() { command pushd "$@" && printf '\033AnSiTc %s\n' "$PWD"; }
        popd()  { command popd  "$@" && printf '\033AnSiTc %s\n' "$PWD"; }
        ssh()   { command ssh   "$@" && dirtrack; }

Or if you only want the hostname info, and don't actually care about the directory-tracking support, then maybe just:

# Emacs term.el hostname tracking support.
: ${HOSTNAME=$(uname -n)}
case $TERM in
        printf '\033AnSiTh %s\n' "$HOSTNAME"
        ssh() { command ssh "$@" && printf '\033AnSiTh %s\n' "$HOSTNAME"; }

(I haven't tested that though, and it looks like term-handle-ansi-terminal-messages will still do some things with only the hostname being set, so it might be bad to not set everything.)

Or you might even consider making your shell prompts issue these escape sequences instead of using the above approaches. That would be redundant for most commands, but is potentially more robust (for handling arbitrary wrappers around ssh for instance). You'd have to experiment.

  • n.b. I know nothing about doom-modeline, so adapt the actual mode-line code as appropriate if it doesn't work as-is. Test from emacs -Q if necessary to verify whether it's working under default settings.
    – phils
    Sep 12, 2023 at 7:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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