A command to connect to remote Emacs from the command line

Posted on April 9, 2026
Tags:

Table of Contents

  1. Features
  2. Script
  3. Behavior and notes

A small shell function to connect to a remote Emacs via SSH. It:

  1. reconnects repeatedly on failure
  2. allows normal exit
  3. uses exponential backoff when the network is poor (delay grows up to 30s)

Features

  1. Continuous reconnect loop.
  2. Clean exit on normal termination.
  3. Exponential backoff on errors, capped at 30s.
  4. Uses ssh with ServerAliveInterval and ServerAliveCountMax to improve connection stability.
  5. Calls emacsclient -t -a '' -s server on the remote host.

Script

  1. Place this function in your shell profile (for example, ~/.bashrc or ~/.zshrc).

  2. Call it as emacsclient-remote [user@host]. The default host is wd@nixos-nuc.

    function emacsclient-remote() {
      local host="${1:-wd@nixos-nuc}"
      local delay=2
    
      trap "echo '[INFO] stopped'; return" INT
    
      while true; do
        echo "[INFO] connecting to $host at $(date)"
    
        ssh \
          -o ServerAliveInterval=30 \
          -o ServerAliveCountMax=3 \
          -t "$host" \
          "emacsclient -t -a '' -s server"
    
        sleep $delay
    
        exit_code=$?
        if [[ $exit_code -eq 0 ]]; then
          echo "[INFO] normal exit, reset delay"
          delay=2
        else
          echo "[WARN] abnormal exit (code=$exit_code), retrying in ${delay}s..."
          # exponential backoff(最大 30s)
          (( delay < 30 )) && delay=$((delay * 2))
          (( delay > 30 )) && delay=30
        fi
      done
    }

Behavior and notes

  1. The function prints connection attempts with timestamps.
  2. A normal emacsclient exit (exit code 0) resets the backoff delay to 2s.
  3. Nonzero exit codes trigger a retry after delay seconds; delay doubles each failure until it reaches 30s.
  4. The trap on INT prints a stop message and returns to the shell.
  5. The ssh options used:
    1. =ServerAliveInterval=30: send keepalive every 30s.
    2. =ServerAliveCountMax=3: allow three missed responses before disconnect.