From 496eacca674e91225b269559731bdbc023a47ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Av=C3=A9?= Date: Mon, 20 Jul 2026 15:47:16 +0200 Subject: [PATCH] Feat: improve run_waypipe handling, without needing temporary files --- home/zsh/files/waypipe.zsh | 43 +++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/home/zsh/files/waypipe.zsh b/home/zsh/files/waypipe.zsh index bc4a342..5fb4b12 100644 --- a/home/zsh/files/waypipe.zsh +++ b/home/zsh/files/waypipe.zsh @@ -1,4 +1,15 @@ -if [ "$PREVIOUS_SESSION_ID" != "" ]; then +if [ -n "$REMOTE_PATH" ]; then + # Fresh `s ` connection: the initial working directory is handed over in + # REMOTE_PATH (an env var is the only channel that survives waypipe's command + # transport intact — shell grouping like `cd …; exec …` does not). cd into it, + # then unset so it does NOT leak to child shells: a lingering exported + # REMOTE_PATH is what made every new zellij pane jump back to this same path + # instead of inheriting the pane's own cwd. + [ -d "$REMOTE_PATH" ] && cd "$REMOTE_PATH" + unset REMOTE_PATH +fi + +if [ -n "$PREVIOUS_SESSION_ID" ]; then # Spawned as a new window/terminal for an existing remote session (by the # niri/hyprland keybind). Inherit that session's working directory: find a # live shell whose SSH_SESSION_ID (carried in its environment) matches and @@ -12,7 +23,16 @@ if [ "$PREVIOUS_SESSION_ID" != "" ]; then # fail quietly into the pipe instead of raising a shell error. if cat "$_environ" 2>/dev/null | tr '\0' '\n' | grep -Fxq "SSH_SESSION_ID=$PREVIOUS_SESSION_ID"; then [ "$(cat /proc/$_pid/comm 2>/dev/null)" = zsh ] || continue + # SSH_SESSION_ID is exported, so transient `zsh -c …` subshells (prompt + # hooks, zellij helpers) inherit it too — but they aren't real session + # panes and often sit at /. Skip anything invoked in command mode; only + # interactive login/pane shells should count. + cat /proc/$_pid/cmdline 2>/dev/null | tr '\0' '\n' | grep -Fxq -- -c && continue _c=$(readlink -e /proc/$_pid/cwd 2>/dev/null) || continue + # A login shell still sitting at / is a helper forked during startup + # (e.g. p10k) that never ran the REMOTE_PATH cd, not a shell the user + # works in. Real panes have always cd'd somewhere; skip root. + [ "$_c" = / ] && continue if [ -n "$_c" ] && [ "$_pid" -gt "$_best_pid" ]; then _best_pid=$_pid _prev_cwd=$_c @@ -30,18 +50,25 @@ function run_waypipe() { fi local SSH_SESSION_ID=$RANDOM REMOTE_PATH # Map the current path relative to $HOME so it resolves to the remote user's - # home even when the username differs (the remote shell expands $HOME). + # home even when the username differs (the remote shell expands $HOME while + # parsing the command below). if [[ "$PWD" == "$HOME" || "$PWD" == "$HOME"/* ]]; then REMOTE_PATH="\$HOME${PWD#$HOME}" else REMOTE_PATH="$PWD" fi - # cd into the mirrored path before the interactive shell starts, so the cwd - # is never carried in an inherited env var (which would leak to every child - # shell and override the cwd of new zellij panes). SSH_SESSION_ID stays in - # the environment on purpose: it is the token the WM keybind above uses to - # locate this session's shells later. - waypipe -n ssh -t "$1" "cd \"$REMOTE_PATH\" 2>/dev/null; exec env SSH_SESSION_ID=$SSH_SESSION_ID zsh --login" + # Hand off the initial cwd and session token as a plain `env VAR=val … zsh` + # argv. This must stay free of shell grouping/metacharacters: waypipe rejoins + # and re-splits the command on whitespace and runs the leading word as a + # program, so `env` (a real binary) works but `cd …; exec …` would not. + # + # SSH_SESSION_ID is placed in TWO environments on purpose: + # - the leading prefix exports it into the LOCAL waypipe/ssh process, where + # the niri/hyprland "duplicate window" keybind reads it out of + # /proc//environ to learn which session to clone; + # - the `env SSH_SESSION_ID=…` sets it on the REMOTE zsh, where the scan + # block above locates this session's shells by matching it. + SSH_SESSION_ID=$SSH_SESSION_ID waypipe -n ssh -t "$1" env REMOTE_PATH=\"$REMOTE_PATH\" SSH_SESSION_ID=$SSH_SESSION_ID zsh --login } alias s='run_waypipe'