Skip to content

spawn --split targets the active tmux window instead of the caller's #990

Description

@g-taki

spawn.sh --split splits whatever window the attached tmux client has active, not the window of the caller. With more than one agent session in a tmux session, a worker can land in a different agent's window.

Reproduce

From a pane inside a tmux session, in a clone of this repo:

CALLER=$(tmux display-message -p -t "$TMUX_PANE" '#{window_id}')   # this pane's window
OTHER=$(tmux new-window -d -P -F '#{window_id}')                   # some other window

# give the switch a head start, so the result is deterministic
( sleep 1; bash scripts/spawn.sh claude-code demo-worker --split v ) &
tmux select-window -t "$OTHER"

# where did it go?
tmux list-panes -a -F '#{window_id} #{pane_title}' | grep demo-worker
echo "caller=$CALLER other=$OTHER"

The worker's window id is $OTHER, not $CALLER. Nothing fails and nothing is logged.

Cause

launch_in_tmux calls split-window with no -t, so tmux resolves the target from the attached client's current window:

https://github.com/fujibee/agmsg/blob/v1.2.3/scripts/spawn.sh#L518

target_id="$(tmux split-window "$dir" -P -F '#{pane_id}' -c "$PROJECT" "${tmux_boot[@]}")"

The --window branch four lines above (L514) and launch_in_herdr (L631) both name their target explicitly. $TMUX_PANE is available here and is the tmux equivalent of the $HERDR_PANE_ID that path uses:

The same thing without agmsg in the way — split-window with no -t, run from inside the caller's own pane, while the session's current window is elsewhere:

caller pane            %18
caller window          @12
other window           @13
$TMUX_PANE (in caller) %18
split landed in        @13     <- not the caller's window

The OS-terminal paths always open a new window, so this is the tmux split branch only.

Suggested fix

Resolve the caller's window from $TMUX_PANE when it is there, and fall back to today's behaviour when it is not:

   else
     local dir="-h"; [ "$SPLIT" = "v" ] && dir="-v"
-    target_id="$(tmux split-window "$dir" -P -F '#{pane_id}' -c "$PROJECT" "${tmux_boot[@]}")"
+    local target_window=""
+    if [ -n "${TMUX_PANE:-}" ]; then
+      target_window="$(tmux display-message -p -t "$TMUX_PANE" '#{window_id}' 2>/dev/null || true)"
+    fi
+    if [ -n "$target_window" ]; then
+      target_id="$(tmux split-window -t "$target_window" "$dir" -P -F '#{pane_id}' -c "$PROJECT" "${tmux_boot[@]}")"
+    else
+      target_id="$(tmux split-window "$dir" -P -F '#{pane_id}' -c "$PROJECT" "${tmux_boot[@]}")"
+    fi
     tmux select-pane -t "$target_id" -T "$NAME" 2>/dev/null || true
   fi

Best-effort, not a guarantee: when $TMUX_PANE is unset or stale it behaves exactly as today. Targeting the window rather than the caller's pane keeps today's active-pane behaviour, so existing chain-split layouts are unaffected.

--window avoids the problem entirely and is a fine workaround.

Happy to send this as a PR, with regression cases for $TMUX_PANE set / unset / stale.

Environment

agmsg  v1.2.3   tmux 3.7c   macOS 26   claude-code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions