fish: add zmx wrappers

Amolith created

Change summary

dot_config/private_fish/functions/__zmx_choose_session.fish  |  49 +
dot_config/private_fish/functions/__zmx_format_sessions.fish |  16 
dot_config/private_fish/functions/zmx-remote-install.fish    | 159 ++++++
dot_config/private_fish/functions/zmx-select.fish            |  11 
dot_config/private_fish/functions/zssh-select.fish           |  41 +
dot_config/private_fish/functions/zssh.fish                  |  42 +
6 files changed, 318 insertions(+)

Detailed changes

dot_config/private_fish/functions/__zmx_choose_session.fish 🔗

@@ -0,0 +1,49 @@
+function __zmx_choose_session --description "Choose or create a zmx session name with fzf"
+    argparse 'p/preview=' -- $argv
+    or return 1
+
+    if not type -q fzf
+        echo "__zmx_choose_session: fzf is not installed or not on PATH" >&2
+        return 127
+    end
+
+    set -l preview_command 'zmx history {1}'
+    if set -q _flag_preview
+        set preview_command $_flag_preview
+    end
+
+    set -l display
+    read -lz display
+
+    set -l output_file (mktemp)
+    begin
+        if test -n "$display"
+            printf "%s" $display
+        end
+    end | fzf \
+        --print-query \
+        --expect=ctrl-n \
+        --height=80% \
+        --reverse \
+        --prompt="zmx> " \
+        --header="Enter: select | Ctrl-N: create new" \
+        --preview=$preview_command \
+        --preview-window=right:60%:follow \
+        >$output_file
+
+    set -l fzf_status $status
+    set -l query (sed -n '1p' $output_file)
+    set -l key (sed -n '2p' $output_file)
+    set -l selected (sed -n '3p' $output_file)
+    rm -f $output_file
+
+    if test "$key" = ctrl-n; and test -n "$query"
+        echo $query
+    else if test $fzf_status -eq 0; and test -n "$selected"
+        string split -f1 ' ' -- $selected
+    else if test -n "$query"
+        echo $query
+    else
+        return 130
+    end
+end

dot_config/private_fish/functions/__zmx_format_sessions.fish 🔗

@@ -0,0 +1,16 @@
+function __zmx_format_sessions --description "Format zmx list output for fzf"
+    while read -l line
+        set -l fields (string split \t -- $line)
+
+        if test (count $fields) -lt 5
+            continue
+        end
+
+        set -l name (string replace -r '^session_name=' '' -- $fields[1])
+        set -l pid (string replace -r '^pid=' '' -- $fields[2])
+        set -l clients (string replace -r '^clients=' '' -- $fields[3])
+        set -l dir (string replace -r '^started_in=' '' -- $fields[5])
+
+        printf "%-20s  pid:%-8s  clients:%-2s  %s\n" $name $pid $clients $dir
+    end
+end

dot_config/private_fish/functions/zmx-remote-install.fish 🔗

@@ -0,0 +1,159 @@
+function zmx-remote-install --description "Install zmx on a remote host by streaming a locally downloaded release tarball"
+    argparse 'h/help' 'upgrade-only' 'v/version=' -- $argv
+    or return 1
+
+    if set -q _flag_help; or test (count $argv) -ne 1
+        echo "Usage: zmx-remote-install [--upgrade-only] [--version VERSION] [user@]host"
+        echo "Example: zmx-remote-install hel1"
+        echo "By default, installs the active local zmx version."
+        echo "With --upgrade-only, only upgrades an existing remote zmx that is older than local."
+        return 0
+    end
+
+    set -l destination $argv[1]
+    set -l desired_version
+
+    if set -q _flag_version
+        set desired_version $_flag_version
+    else if type -q zmx
+        set desired_version (zmx version | awk 'NR == 1 {print $2}')
+    else if type -q mise
+        set desired_version (mise exec -- zmx version | awk 'NR == 1 {print $2}')
+    end
+
+    if test -z "$desired_version"
+        echo "zmx-remote-install: could not determine local zmx version from zmx or mise" >&2
+        return 1
+    end
+
+    mkdir -p "$HOME/.ssh/controlmasters"
+
+    set -l remote_version (command ssh \
+        -o ControlMaster=auto \
+        -o ControlPersist=10m \
+        -o ControlPath="$HOME/.ssh/controlmasters/%C" \
+        $destination \
+        "sh -c 'PATH=\"\$HOME/.local/bin:\$PATH\"; if command -v zmx >/dev/null 2>&1; then zmx version | awk \"NR == 1 {print \\\$2}\"; fi'")
+    or return $status
+
+    if test -z "$remote_version"
+        if set -q _flag_upgrade_only
+            return 0
+        end
+
+        echo "Remote zmx is not installed; installing local zmx $desired_version..." >&2
+    else if test "$remote_version" = "$desired_version"
+        return 0
+    else
+        if not type -q semver
+            echo "zmx-remote-install: semver is required to compare local zmx $desired_version with remote zmx $remote_version" >&2
+            return 1
+        end
+
+        if not semver "$desired_version" >/dev/null 2>&1; or not semver "$remote_version" >/dev/null 2>&1
+            echo "zmx-remote-install: cannot compare local zmx $desired_version with remote zmx $remote_version; refusing to sidegrade" >&2
+            return 1
+        end
+
+        if not semver -r ">$remote_version" "$desired_version" >/dev/null 2>&1
+            return 0
+        end
+
+        echo "Remote zmx is $remote_version; upgrading to local zmx $desired_version..." >&2
+    end
+
+    set -l remote_platform (command ssh \
+        -o ControlMaster=auto \
+        -o ControlPersist=10m \
+        -o ControlPath="$HOME/.ssh/controlmasters/%C" \
+        $destination \
+        "sh -c 'printf \"%s %s\\n\" \"\$(uname -s)\" \"\$(uname -m)\"'")
+    or return $status
+
+    set -l remote_os (string split ' ' -- $remote_platform)[1]
+    set -l remote_arch (string split ' ' -- $remote_platform)[2]
+    set -l zmx_os
+    set -l zmx_arch
+
+    switch $remote_os
+        case Linux
+            set zmx_os linux
+        case Darwin
+            set zmx_os macos
+        case '*'
+            echo "zmx-remote-install: unsupported remote OS '$remote_os'" >&2
+            return 2
+    end
+
+    switch $remote_arch
+        case x86_64 amd64
+            set zmx_arch x86_64
+        case aarch64 arm64
+            set zmx_arch aarch64
+        case '*'
+            echo "zmx-remote-install: unsupported remote architecture '$remote_arch'" >&2
+            return 2
+    end
+
+    set -l archive "zmx-$desired_version-$zmx_os-$zmx_arch.tar.gz"
+    set -l base_url "https://zmx.sh/a"
+    set -l temp_dir (mktemp -d)
+    set -l archive_path "$temp_dir/$archive"
+    set -l checksum_path "$archive_path.sha256"
+
+    if test -z "$temp_dir"
+        echo "zmx-remote-install: failed to create a temporary directory" >&2
+        return 1
+    end
+
+    echo "Downloading $archive..." >&2
+    if not curl -fsSL "$base_url/$archive" -o "$archive_path"
+        rm -rf $temp_dir
+        return 1
+    end
+
+    if curl -fsSL "$base_url/$archive.sha256" -o "$checksum_path"
+        set -l expected (awk '{print $1}' "$checksum_path")
+        set -l actual
+
+        if type -q sha256sum
+            set actual (sha256sum "$archive_path" | awk '{print $1}')
+        else if type -q shasum
+            set actual (shasum -a 256 "$archive_path" | awk '{print $1}')
+        else
+            echo "zmx-remote-install: no local sha256sum or shasum found; refusing to install unverified archive" >&2
+            rm -rf $temp_dir
+            return 1
+        end
+
+        if test "$expected" != "$actual"
+            echo "zmx-remote-install: checksum verification failed for $archive" >&2
+            rm -rf $temp_dir
+            return 1
+        end
+    else
+        echo "zmx-remote-install: could not download checksum for $archive; refusing to install unverified archive" >&2
+        rm -rf $temp_dir
+        return 1
+    end
+
+    echo "Installing zmx $desired_version on $destination..." >&2
+    if not command ssh \
+            -o ControlMaster=auto \
+            -o ControlPersist=10m \
+            -o ControlPath="$HOME/.ssh/controlmasters/%C" \
+            $destination \
+            "sh -c 'mkdir -p \"\$HOME/.local/bin\" && tmp=\$(mktemp \"\$HOME/.local/bin/.zmx.XXXXXX\") && tar -xOzf - zmx > \"\$tmp\" && chmod 755 \"\$tmp\" && mv \"\$tmp\" \"\$HOME/.local/bin/zmx\"'" <"$archive_path"
+        rm -rf $temp_dir
+        return 1
+    end
+
+    rm -rf $temp_dir
+
+    command ssh \
+        -o ControlMaster=auto \
+        -o ControlPersist=10m \
+        -o ControlPath="$HOME/.ssh/controlmasters/%C" \
+        $destination \
+        "sh -c 'PATH=\"\$HOME/.local/bin:\$PATH\"; zmx version'"
+end

dot_config/private_fish/functions/zmx-select.fish 🔗

@@ -0,0 +1,11 @@
+function zmx-select --description "Fuzzy-find or create a zmx session"
+    if not type -q zmx
+        echo "zmx-select: zmx is not installed or not on PATH" >&2
+        return 127
+    end
+
+    set -l session_name (zmx list 2>/dev/null | __zmx_format_sessions | __zmx_choose_session --preview 'zmx history {1}')
+    or return $status
+
+    zmx attach $session_name
+end

dot_config/private_fish/functions/zssh-select.fish 🔗

@@ -0,0 +1,41 @@
+function zssh-select --description "Fuzzy-find or create a zmx session on a remote host"
+    argparse 'h/help' 'install' -- $argv
+    or return 1
+
+    if set -q _flag_help; or test (count $argv) -ne 1
+        echo "Usage: zssh-select [--install] [user@]host"
+        echo "Example: zssh-select hel1"
+        return 0
+    end
+
+    set -l destination $argv[1]
+
+    if not string match -qr '^[A-Za-z0-9._@:%+-]+$' -- $destination
+        echo "zssh-select: destination contains characters that cannot be safely used in the preview command" >&2
+        return 2
+    end
+
+    mkdir -p "$HOME/.ssh/controlmasters"
+
+    if set -q _flag_install
+        zmx-remote-install $destination
+        or return $status
+    else
+        zmx-remote-install --upgrade-only $destination
+        or return $status
+    end
+
+    set -l remote_list (command ssh \
+        -o ControlMaster=auto \
+        -o ControlPersist=10m \
+        -o ControlPath="$HOME/.ssh/controlmasters/%C" \
+        $destination \
+        "sh -c 'PATH=\"\$HOME/.local/bin:\$PATH\"; command -v zmx >/dev/null 2>&1 || { echo \"zssh-select: zmx is not installed on the remote host or is not on PATH; retry with zssh-select --install\" >&2; exit 127; }; zmx list 2>/dev/null'")
+    or return $status
+
+    set -l preview_command "ssh -o ControlMaster=auto -o ControlPersist=10m -o ControlPath=$HOME/.ssh/controlmasters/%C $destination 'sh -c '\''PATH=\"\$HOME/.local/bin:\$PATH\"; zmx history {1}'\'' '"
+    set -l session_name (printf '%s\n' $remote_list | __zmx_format_sessions | __zmx_choose_session --preview $preview_command)
+    or return $status
+
+    zssh $destination $session_name
+end

dot_config/private_fish/functions/zssh.fish 🔗

@@ -0,0 +1,42 @@
+function zssh --description "SSH to a host and attach to a remote zmx session"
+    argparse 'h/help' 'install' -- $argv
+    or return 1
+
+    if set -q _flag_help; or test (count $argv) -lt 1
+        echo "Usage: zssh [--install] [user@]host [session]"
+        echo "Example: zssh devbox term"
+        return 0
+    end
+
+    set -l destination $argv[1]
+    set -l session main
+
+    if test (count $argv) -ge 2
+        set session $argv[2]
+    end
+
+    if not string match -qr '^[A-Za-z0-9._:-]+$' -- $session
+        echo "zssh: session names may only contain letters, numbers, dots, underscores, colons, and hyphens" >&2
+        return 2
+    end
+
+    mkdir -p "$HOME/.ssh/controlmasters"
+
+    if set -q _flag_install
+        zmx-remote-install $destination
+        or return $status
+    else
+        zmx-remote-install --upgrade-only $destination
+        or return $status
+    end
+
+    set -l remote_command "sh -c 'PATH=\"\$HOME/.local/bin:\$PATH\"; command -v zmx >/dev/null 2>&1 || { echo \"zssh: zmx is not installed on the remote host or is not on PATH; retry with zssh --install\" >&2; exit 127; }; exec zmx attach \"\$1\"' sh '$session'"
+
+    command ssh \
+        -o ControlMaster=auto \
+        -o ControlPersist=10m \
+        -o ControlPath="$HOME/.ssh/controlmasters/%C" \
+        -o RequestTTY=yes \
+        -o RemoteCommand="$remote_command" \
+        $destination
+end