Skip to content

Bare %N pane ID targets resolve to wrong panes (cyclic offset) #332

@qi-o

Description

@qi-o

Summary

When targeting panes by bare %N ID (e.g. -t %2) from within a psmux session, the target resolves to the wrong pane — there's a cyclic offset in the mapping. Session-scoped targets (session:window.index) work correctly, but bare %N does not. This breaks all tools that use tmux pane IDs for stable pane tracking, including oh-my-claudecode (OMC) team mode and likely tmuxp/libtmux (#318).

Environment

Item Value
OS Windows 11 Home China 10.0.26100
Shell PowerShell 7.6.2 (native, not MSYS2)
psmux version 3.3.5 (scoop)
Terminal Windows Terminal

Steps to Reproduce

1. Create a session with 3 panes

tmux new-session -d -s test -x 120 -y 40
tmux split-window -h -t test:0 -d
tmux split-window -v -t test:0 -d

2. Verify actual pane layout

tmux list-panes -t test:0 -F '#{pane_id} index=#{pane_index}'

Output (example):

%1 index=0
%3 index=1
%2 index=2

3. Test bare %N targeting from inside the session

Send these commands to the first pane and capture each pane:

# From inside pane %1, target each pane:
tmux display-message -p -t %1 '#{pane_id}'   # Expected: %1
tmux display-message -p -t %2 '#{pane_id}'   # Expected: %2
tmux display-message -p -t %3 '#{pane_id}'   # Expected: %3

4. Test send-keys targeting from inside the session

# From pane %1:
tmux send-keys -t %1 -l "THIS_IS_PANE_1"
tmux send-keys -t %2 -l "THIS_IS_PANE_2"
tmux send-keys -t %3 -l "THIS_IS_PANE_3"

Actual Behavior

display-message test

All three queries return %1:

PANE1=%1
PANE2=%1    ← should be %2 or %3
PANE3=%1    ← should be %2 or %3

send-keys test

Text arrives at wrong panes in a cyclic shift pattern:

-t %1 → text lands in pane %2  (wrong)
-t %2 → text lands in pane %3  (wrong)
-t %3 → text lands in pane %1  (wrong)

Additionally: running tmux commands from OUTSIDE any session

All bare %N targets collapse to %1:

# From a non-tmux terminal:
tmux display-message -p -t %1 '#{pane_id}'  # → %1 (correct)
tmux display-message -p -t %2 '#{pane_id}'  # → %1 (wrong!)
tmux display-message -p -t %3 '#{pane_id}'  # → %1 (wrong!)
tmux display-message -p -t %999 '#{pane_id}'  # → %1 (should error!)

Expected Behavior

As in standard tmux: bare %N pane IDs should resolve to the pane with that ID within the current session context, regardless of whether the command is issued from inside or outside the session (provided TMUX env var is set).

Secondary Issues Found

1. Non-existent pane targets don't error

tmux display-message -p -t %999 '#{pane_dead}'
# Returns: 0  (should exit non-zero with "can't find pane")

This causes getWorkerLiveness() checks to incorrectly report dead panes as alive.

2. Non-existent session-scoped pane index returns pseudo %0

tmux display-message -p -t test:0.999 '#{pane_id} #{pane_dead}'
# Returns: %0 0  (should exit non-zero)

The %0 pseudo-ID could cause downstream tools to behave unpredictably.

3. kill-session on non-existent session exits 0 silently

tmux kill-session -t no-such-session; echo $?
# Returns: 0  (should return 1 with error message)

Impact on OMC (oh-my-claudecode) Team Mode

OMC's tmux-session.ts relies on bare %N pane IDs throughout its worker lifecycle: | Operation | tmux Command | Broken? |
|-----------|-------------|---------|
| Worker liveness check | display-message -t <paneId> '#{pane_dead}' | Yes |
| Worker spawn | send-keys -t <paneId> -l <startCmd> | Yes |
| Worker output capture | capture-pane -t <paneId> -p -S -80 | Yes |
| Worker kill | kill-pane -t <paneId> | Yes |
| Pane key injection | send-keys -t <paneId> <key> | Yes |

All worker operations target wrong panes, making team mode non-functional under psmux.

Related Issues

Hypothesis

Given the similarity to the already-fixed $N session ID resolution bug (#323), this may have the same root cause: pane IDs (%N) may not be resolved correctly in psmux's target parser. The cyclic offset pattern suggests an off-by-one or index-vs-ID confusion in the pane lookup logic.

Note

I'm filing this because I'd really like psmux to reach a level where OMC team mode works reliably on native Windows. Happy to help test fixes or provide more detail.

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