Skip to content

feat: cycle to the next agent pane needing attention - #37

Merged
corwinm merged 1 commit into
corwinm:mainfrom
mattaschmann:feat/pane-cycling-pr
Oct 4, 2026
Merged

corwinm merged 1 commit into
corwinm:mainfrom
mattaschmann:feat/pane-cycling-pr

Conversation

@mattaschmann

@mattaschmann mattaschmann commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

What

A cycle command on prefix + C-n that jumps to the agent pane that most
needs you. Press again to walk the rest.

Why

With several agents across panes, menu/popup make you open a list and
pick. Most of the time I just want "take me to whatever needs me next."

How

Each press jumps to the next pane in this order:

  1. waiting (question/permission prompt). Always first, even after you've
    looked at it, because only answering clears it.
  2. unseen idle → new → running → unknown
  3. seen idle → new → running → unknown

Within each group, the pane that's been in its state longest goes first, so a
long-waiting pane never gets starved by newer ones.

A pane is seen once it's been active since entering its current state
(normal tmux navigation counts), and goes back to unseen when its state
changes. Presses go through the waiting and unseen panes first, then continue
through the seen panes and wrap. It never dead-ends.

Unseen idle panes get a filled blue circle, so finished work you haven't
reviewed stands out. Once seen it drops to the normal hollow idle glyph.

Screenshot 2026-09-17 at 9 51 20 AM

Example of how new "unseen" shows up in the popup

Screenshot 2026-09-17 at 9 48 23 AM

Status line: waiting pane, unseen idle in blue, running.

Screenshot 2026-09-17 at 9 49 03 AM

After switching to the "unseen" pane

The seen/unseen state is a small reader-side ledger under
~/.local/state/coding-agents-tmux/cycle-state, derived from the displayed
status at read time. That means it works for every agent with no plugin/writer
changes and no state-file schema change.

Also: the status/menu/popup glyph now comes from one place
(getPaneStatusSymbol). list --compact emits the resolved glyph, so
tmux-menu-switch.sh drops its duplicate bash symbol table.

Config

  • @coding-agents-tmux-cycle-key (default C-n, off to disable)
  • @coding-agents-tmux-status-color-unseen (default colour39)

Notes for review

  • C-n is free on stock tmux, but it's a common rebind. Happy to change the
    default.
  • The ledger is per pane id. Stale entries from closed panes aren't pruned yet,
    and they're harmless. I can follow up if you want it tidier.

Testing

Ranking tiers, FIFO within a tier, unseen-before-seen, waiting-ahead-of-seen,
full rotation and wrap, current pane absent, ledger transitions, e2e cycle
against fake tmux, the compact glyph field, and snippet/bind-key assertions.
All checks pass. Two pre-existing tests (detectOpenCodeVersion, the Pi
refresh-failure test) flake under parallel node --test and pass in
isolation. Neither touches this code.

Live-verified on a clean checkout of main + this branch with an empty
ledger. Presses walk waiting → unseen idle → running, then continue through
seen panes.

Add a `cycle` command bound to `prefix + C-n` (configurable) that jumps to the
highest-priority agent pane needing attention and walks through the rest on
repeated presses.

Ranking, highest attention first: waiting-question/waiting-input > idle > new >
running > unknown. Within a tier, the pane in its state longest comes first
(FIFO), so a long-waiting pane is never starved by newer arrivals.

Seen/unseen: cycling tracks which panes you have already looked at. A pane is
seen once it has been active since entering its current state (ordinary tmux
navigation acknowledges panes too), and becomes unseen again when its state
changes. Unseen panes are offered before seen ones, so repeated presses sweep
everything new first, then continue through the rest and wrap; cycling never
dead-ends. Unseen idle panes get a distinct filled-circle glyph (blue where
colors are available) in the status line and choosers.

Implementation: a reader-side ledger under
~/.local/state/coding-agents-tmux/cycle-state derived from the displayed status
at read time, so it covers all agents with no writer/plugin changes and no
state-file schema change. Ranking is pure and unit-tested
(rankPanesForCycle / pickNextCyclePane). Status/menu/popup share one seen/unseen
source of truth via getPaneStatusSymbol; the CLI now emits the resolved glyph in
`list --compact`, letting the tmux menu script drop its duplicate bash symbol
table. A 5th tmux key binding is wired through the plugin entry,
buildTmuxSnippet, and tmux-config / install-tmux, with a matching
@coding-agents-tmux-status-color-unseen option.

@corwinm corwinm left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Looks very useful.

@corwinm
corwinm merged commit d4add90 into corwinm:main Oct 4, 2026
1 check passed
@mattaschmann
mattaschmann deleted the feat/pane-cycling-pr branch October 5, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants