Skip to content

Instantly share code, notes, and snippets.

@golbin
Last active May 26, 2026 06:30
Show Gist options
  • Select an option

  • Save golbin/2842fab87515ce56b3bb1a216f8c433e to your computer and use it in GitHub Desktop.

Select an option

Save golbin/2842fab87515ce56b3bb1a216f8c433e to your computer and use it in GitHub Desktop.
SSH login tmux session picker
#!/bin/sh
set -eu
# Show this menu only for an SSH login with a terminal, and never inside tmux.
if [ -z "${SSH_TTY:-}" ] || [ -n "${TMUX:-}" ] || [ ! -t 0 ]; then
exit 0
fi
case "${LC_ALL:-${LC_CTYPE:-${LANG:-}}}" in
*UTF-8*|*utf8*|*utf-8*) ;;
*)
if locale -a 2>/dev/null | grep -qi '^ko_KR\\.UTF-8$'; then
export LANG=ko_KR.UTF-8 LC_CTYPE=ko_KR.UTF-8 LC_ALL=ko_KR.UTF-8
elif locale -a 2>/dev/null | grep -qi '^C\\.UTF-8$'; then
export LANG=C.UTF-8 LC_CTYPE=C.UTF-8 LC_ALL=C.UTF-8
elif locale -a 2>/dev/null | grep -qi '^en_US\\.UTF-8$'; then
export LANG=en_US.UTF-8 LC_CTYPE=en_US.UTF-8 LC_ALL=en_US.UTF-8
fi
;;
esac
if ! command -v tmux >/dev/null 2>&1; then
exit 0
fi
if ! command -v fzf >/dev/null 2>&1; then
tmux -u new-session -A -s main
exit 0
fi
case "${TERM:-}" in
""|dumb)
export TERM=xterm-256color
;;
*)
if command -v infocmp >/dev/null 2>&1 && ! infocmp "$TERM" >/dev/null 2>&1; then
export TERM=xterm-256color
fi
;;
esac
sessions="$(tmux -u list-sessions -F '#S' 2>/dev/null || true)"
choice="$(
{
printf '%s\n' "New shell"
printf '%s\n' "New tmux session"
if [ -n "$sessions" ]; then
printf '%s\n' "$sessions" | sed 's/^/Attach: /'
fi
} | fzf \
--reverse \
--no-unicode \
--prompt='SSH start> ' || true
)"
case "${choice:-}" in
"New shell"|"")
exit 0
;;
"New tmux session")
printf 'Session name [main]: '
read -r session_name
session_name="${session_name:-main}"
tmux -u new-session -A -s "$session_name"
exit 0
;;
Attach:\ *)
session_name="${choice#Attach: }"
tmux -u attach-session -t "$session_name"
exit 0
;;
esac
exit 0

SSH tmux session picker

Show an fzf menu on interactive SSH login, then start a normal shell, create a new tmux session, or attach to an existing tmux session.

This is useful for small remote machines where SSH should land directly in the right long-running workspace.

Requirements

  • tmux
  • fzf
  • A POSIX-compatible shell

The script is written for /bin/sh. The login hook examples below cover zsh and bash.

Install

mkdir -p ~/.local/bin
curl -fsSL https://gist.githubusercontent.com/golbin/2842fab87515ce56b3bb1a216f8c433e/raw/ssh-start-menu.sh -o ~/.local/bin/ssh-start-menu
chmod +x ~/.local/bin/ssh-start-menu

For zsh, add this to ~/.zprofile:

if [ -n "${SSH_TTY:-}" ] && [ -z "${TMUX:-}" ] && [ -x "$HOME/.local/bin/ssh-start-menu" ]; then
  "$HOME/.local/bin/ssh-start-menu"
fi

For bash, add this to ~/.bash_profile:

if [ -n "${SSH_TTY:-}" ] && [ -z "${TMUX:-}" ] && [ -x "$HOME/.local/bin/ssh-start-menu" ]; then
  "$HOME/.local/bin/ssh-start-menu"
fi

Recommended tmux Locale Settings

If Korean or other multibyte text works in a plain SSH shell but breaks inside tmux, make tmux start sessions with an explicit UTF-8 locale.

The script uses tmux -u for session listing, session creation, and attach. This forces tmux to treat the client terminal as UTF-8 capable.

Add this to ~/.tmux.conf:

set -g update-environment "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY"
set-environment -g LANG ko_KR.UTF-8
set-environment -g LC_CTYPE ko_KR.UTF-8
set-environment -g LC_ALL ko_KR.UTF-8
set -g default-terminal "tmux-256color"

Then restart existing tmux sessions, or reload the config and open a new pane:

tmux source-file ~/.tmux.conf

Existing tmux clients keep their old UTF-8 flag. Detach and attach again through this menu after changing the script or config.

You can check the current client flag with:

tmux list-clients -F '#{client_name} #{client_termname} #{client_utf8}'

The last value should be 1.

Behavior

The menu appears only for an interactive SSH login with a terminal attached.

It does not run:

  • outside SSH
  • inside an existing tmux session
  • for non-interactive commands such as ssh host command, scp, or rsync

Menu choices:

  • New shell: continue into the normal login shell
  • New tmux session: create or attach to a named session
  • Attach: <session>: attach to an existing session

If fzf is missing, the script falls back to:

tmux new-session -A -s main

Notes For Mobile Terminals

The script uses full-screen fzf mode and --no-unicode to avoid layout glitches in mobile SSH clients when the software keyboard changes the terminal height.

It also sets LANG and LC_CTYPE to an available UTF-8 locale when the SSH login environment is not already UTF-8. This keeps Korean and other multibyte text readable in fzf.

If the menu still renders incorrectly, check:

echo "$TERM"
echo "$LANG"
echo "$LC_ALL"
stty size
infocmp "$TERM" >/dev/null && echo ok || echo missing

License

MIT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment