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
spawn.sh --splitsplits 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:
The worker's window id is
$OTHER, not$CALLER. Nothing fails and nothing is logged.Cause
launch_in_tmuxcallssplit-windowwith 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
--windowbranch four lines above (L514) andlaunch_in_herdr(L631) both name their target explicitly.$TMUX_PANEis available here and is the tmux equivalent of the$HERDR_PANE_IDthat path uses:The same thing without agmsg in the way —
split-windowwith no-t, run from inside the caller's own pane, while the session's current window is elsewhere: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_PANEwhen it is there, and fall back to today's behaviour when it is not:Best-effort, not a guarantee: when
$TMUX_PANEis 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.--windowavoids the problem entirely and is a fine workaround.Happy to send this as a PR, with regression cases for
$TMUX_PANEset / unset / stale.Environment