Shell integration
Configure your shell prompt, environment tracking, completions, and session picker
shell prompt #
When you attach to a zmx session, we don't provide any indication that you are inside zmx. We do provide an environment variable ZMX_SESSION which contains the session name.
We recommend checking for that env var inside your prompt and displaying some indication there.
fish #
Place this file in ~/.config/fish/config.fish:
1functions -c fish_prompt _original_fish_prompt 2>/dev/null
2
3function fish_prompt --description 'Write out the prompt'
4 if set -q ZMX_SESSION
5 echo -n "[$ZMX_SESSION] "
6 end
7 _original_fish_prompt
8end
bash and zsh #
Depending on the shell, place this in either .bashrc or .zshrc:
1if [[ -n $ZMX_SESSION ]]; then
2 export PS1="[$ZMX_SESSION] ${PS1}"
3fi
powerlevel10k zsh theme #
powerlevel10k is a theme for zsh that overwrites the default prompt statusline.
Place this in .zshrc:
1function prompt_my_zmx_session() {
2 if [[ -n $ZMX_SESSION ]]; then
3 p10k segment -b '%k' -f '%f' -t "[$ZMX_SESSION]"
4 fi
5}
6POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS+=my_zmx_session
oh-my-posh #
oh-my-posh is a popular shell themeing and prompt engine. This code will display an icon and session name as part of the prompt if (and only if) you have zmx active:
1[[blocks.segments]]
2 template = '{{ if .Env.ZMX_SESSION }} {{ .Env.ZMX_SESSION }}{{ end }}'
3 foreground = 'p:orange'
4 background = 'p:black'
5 type = 'text'
6 style = 'plain'
Starship #
Starship is a popular shell themeing and prompt engine. This code will display an icon and session name as part of the prompt if (and only if) you have zmx active:
1format = """
2${env_var.ZMX_SESSION}\
3...
4"""
5
6[env_var.ZMX_SESSION]
7symbol = " "
8format = "[$symbol$env_value]($style) "
9description = "zmx session name"
10style = "bold magenta"
environment variables #
A session's environment is initialized when the session is created. When re-attaching from a new terminal or a different SSH connection, environment variables describing the client connection (such as SSH_AUTH_SOCK, DISPLAY, or terminal remote control variables like KITTY_LISTEN_ON, KITTY_PID, KITTY_WINDOW_ID) become outdated in the running shell.
zmx tracks these environment variables from attaching clients. You can inspect the current leader client's environment with zmx print-env:
1# Print all tracked environment variables (set variables as KEY=VALUE, unset as -KEY)
2zmx print-env .
3zmx print-env dev
4
5# Print POSIX shell commands (export ... / unset ...) suitable for eval
6zmx print-env -s .
7
8# Print a specific variable value
9zmx print-env . SSH_AUTH_SOCK
You can automatically update your shell environment before each prompt:
bash #
Add to ~/.bashrc:
1_zmx_env_hook() {
2 if [[ -n $ZMX_SESSION ]]; then
3 eval "$(zmx print-env -s .)"
4 fi
5}
6PROMPT_COMMAND="_zmx_env_hook${PROMPT_COMMAND:+; $PROMPT_COMMAND}"
zsh #
Add to ~/.zshrc:
1precmd() {
2 if [[ -n $ZMX_SESSION ]]; then
3 eval "$(zmx print-env -s .)"
4 fi
5}
fish #
Add to ~/.config/fish/config.fish:
1function _zmx_env_hook --on-event fish_prompt
2 if test -n "$ZMX_SESSION"
3 for line in (zmx print-env .)
4 if string match -q -- "-*" $line
5 set -e (string sub -s 2 $line)
6 else
7 set -gx (string split -m 1 "=" $line)
8 end
9 end
10 end
11end
configuring tracked variables #
By default, zmx tracks:
DISPLAYSSH_AUTH_SOCKSSH_AGENT_PIDSSH_CONNECTIONWINDOWIDXAUTHORITYKITTY_LISTEN_ONKITTY_PIDKITTY_WINDOW_ID
You can customize this list by setting ZMX_TRACK_ENV to a comma-separated list of variable names:
1export ZMX_TRACK_ENV="DISPLAY,SSH_AUTH_SOCK,GPG_AGENT_INFO"
shell completion #
Shell auto-completion for zmx commands and session names can be enabled using the completions subcommand. Once configured, you'll get auto-complete for both local zmx commands and sessions:
1ssh remote-server zmx attach session-na<TAB>
2# <- auto-complete suggestions appear here
NOTICE: when installing
zmxwithhomebrewcompletions are automatically installed.
bash #
Add this to your .bashrc file:
1if command -v zmx &> /dev/null; then
2 eval "$(zmx completions bash)"
3fi
zsh #
Add this to your .zshrc file:
1if command -v zmx &> /dev/null; then
2 eval "$(zmx completions zsh)"
3fi
fish #
Add this to ~/.config/fish/completions/zmx.fish:
1if type -q zmx
2 zmx completions fish | source
3end
yash #
Add this to your ~/.config/yash/rc:
1if command -v zmx > /dev/null 2>&1; then
2 eval "$(zmx completions yash)"
3fi
Or save as an autoloaded script in your completion directory:
1zmx completions yash > ~/.config/yash/completion/zmx
nu #
Add this to your Nushell config (config.nu):
use ("~/.cache/zmx/completions.nu" | path expand)
# Or generate dynamically:
zmx completions nu | save -f ~/.cache/zmx/completions.nu
session picker #
An interactive session picker using fzf to attach to existing sessions, preview scrollback, or create new sessions.
- Enter selects a matched session (or creates one if no sessions exist)
- Ctrl-N creates a new session using the typed query, even when a fuzzy match is highlighted
bash and zsh #
1zmx-select() {
2 local display
3 local prefix="${ZMX_SESSION_PREFIX:-}"
4 display=$(zmx list 2>/dev/null | while IFS=$'\t' read -r name pid clients created dir; do
5 name=${name#*name=}
6 pid=${pid#*pid=}
7 clients=${clients#*clients=}
8 dir=${dir#*start_dir=}
9 if [[ -n "$prefix" ]]; then
10 [[ "$name" == "$prefix"* ]] || continue
11 name=${name#"$prefix"}
12 fi
13 printf "%-20s pid:%-8s clients:%-2s %s\n" "$name" "$pid" "$clients" "$dir"
14 done)
15
16 local output query key selected session_name
17 output=$({ [[ -n "$display" ]] && echo "$display"; } | fzf \
18 --print-query \
19 --expect=ctrl-n \
20 --height=80% \
21 --reverse \
22 --prompt="zmx> " \
23 --header="Enter: select | Ctrl-N: create new" \
24 --preview='zmx history {1}' \
25 --preview-window=right:60%:follow \
26 )
27 local rc=$?
28
29 query=$(echo "$output" | sed -n '1p')
30 key=$(echo "$output" | sed -n '2p')
31 selected=$(echo "$output" | sed -n '3p')
32
33 if [[ "$key" == "ctrl-n" && -n "$query" ]]; then
34 session_name="$query"
35 elif [[ $rc -eq 0 && -n "$selected" ]]; then
36 session_name=$(echo "$selected" | awk '{print $1}')
37 elif [[ -n "$query" ]]; then
38 session_name="$query"
39 else
40 return 130
41 fi
42
43 zmx attach "$session_name"
44}
Run zmx-select directly or launch it from your shell rc file when outside a session. With && exit, detaching or exiting the session closes the SSH connection, while ctrl+c in the picker drops into a regular shell:
1if command -v zmx &> /dev/null && command -v fzf &> /dev/null && [[ -z "$ZMX_SESSION" ]]; then
2 zmx-select && exit
3fi
alternative: gentle hint (server use) #
On shared servers where you don't want fzf to launch on every login, print a reminder when active sessions exist:
1if command -v zmx &> /dev/null && [[ -z "$ZMX_SESSION" ]]; then
2 local count
3 count=$(zmx ls --short 2>/dev/null | wc -l)
4 if [[ "$count" -gt 0 ]]; then
5 echo "zmx: $count session(s) active (run zmx-select to attach)" >&2
6 fi
7fi