Thought
Making Mosh My Default Remote Terminal
A remote shell that stays connected, scrollable, and quiet.
I wanted to use mosh as my normal remote shell, but scrollback annoyed me.
When I am on a remote machine, I often need to scroll through logs, errors, or command output from a few minutes ago. With plain mosh, that did not work the way I wanted.
I could have gone back to SSH. That would have been the easy answer.
But I like mosh. It handles bad networks better, and it feels good for long remote sessions. I did not want to think, “Do I need SSH this time, or mosh?” every time I opened a terminal.
So I kept mosh and put tmux behind it.
mosh user@host -- tmux new -A -s main
mosh handles the connection. tmux handles the session and scrollback. Ghostty stays as my local terminal.
It is not the same as normal local terminal scrollback. The history lives inside tmux. For my use, that is fine.
A Small Helper
I did not want to type the full command every time, so I made a zsh function.
I keep the helper here: j1n-park/mosh-tmux.
mosh-tmux() {
local session="main"
if [ "$1" = "-s" ]; then
session="$2"
shift 2
fi
if [ -z "$1" ]; then
echo "usage: mosh-tmux [-s session] user@host [tmux args...]" >&2
return 2
fi
local target="$1"
shift
command mosh --no-init "$target" -- tmux new -A -s "$session" "$@"
}
The normal case is now:
mosh-tmux user@host
If I want another tmux session:
mosh-tmux -s work user@host
I also use --no-init. The main scrollback still comes from tmux, but this keeps mosh startup a little less surprising in my terminal.
Making tmux Quiet
I like what tmux does. I do not like how it looks by default.
The default status bar shows more than I need: hostname, time, session name, and other bits. I mostly want to know which window I am in.
I first tried turning the bar off:
set -g status off
That looked clean, but it was too clean. Once I had more than one window, I wanted a small hint.
So I kept the bar and removed almost everything from it.
set -g status-left ""
set -g status-right ""
set -g status-left-length 0
set -g status-right-length 0
set -g status-justify centre
One job: show the windows.
Matching Ghostty
I use Ghostty with Tokyo Night Night. The default tmux colors looked out of place, so I changed them.
set -g status-style "bg=#1a1b26,fg=#c0caf5"
setw -g window-status-format "#[fg=#292e42,bg=#1a1b26]#[fg=#c0caf5,bg=#292e42] #I · #{@last_command} #[fg=#292e42,bg=#1a1b26]"
setw -g window-status-current-format "#[fg=#bb9af7,bg=#1a1b26]#[fg=#1a1b26,bg=#bb9af7,bold] #I · #{@last_command} #[fg=#bb9af7,bg=#1a1b26]"
It ends up looking roughly like this:
0 · lazydocker 1 · htop 2 · nvim 3 · ls
Quiet enough.
Showing the Last Command
I turned off tmux automatic rename.
set -g automatic-rename off
set -g allow-rename off
Automatic rename works for long-running programs like nvim or htop, but not for quick commands like ls or git status.
I wanted each window to show the last command I ran. Just the command name, not the whole line.
So I used zsh’s preexec hook and saved the command in a tmux window option.
if [ -n "$TMUX" ]; then
tmux set-option -wq @last_command "shell"
preexec() {
local cmd="${1%% *}"
cmd="${cmd[1,24]}"
tmux set-option -wq @last_command "$cmd"
}
fi
Now the labels look like this:
0 · ls
1 · htop
2 · nvim
3 · git
That is enough context for me.
Keeping My Shell Config Separate
I also moved my own shell helpers into a separate file.
[ -f "$HOME/.my-config.zsh" ] && source "$HOME/.my-config.zsh"
I have lost .zshrc before. Rebuilding small helpers from memory is annoying. Keeping my own file separate makes it easier to back up and move around.
The Setup Now
What I use now:
- Ghostty as the local terminal
- mosh as the default remote connection
- tmux for sessions and scrollback
- zsh for small glue
- a quiet status bar with window index and last command
I also keep one manual toggle:
bind-key B set-option -g status
That is enough for now.