Skip to content

feat: expose per-session window list in sidebar#23

Open
shunkakinoki wants to merge 4 commits intoAtaraxy-Labs:mainfrom
shunkakinoki:feat/window-list
Open

feat: expose per-session window list in sidebar#23
shunkakinoki wants to merge 4 commits intoAtaraxy-Labs:mainfrom
shunkakinoki:feat/window-list

Conversation

@shunkakinoki
Copy link
Copy Markdown

Summary

  • Adds per-session window/tab enumeration to the sidebar, so sessions with multiple tmux windows show each window as a clickable row
  • Introduces MuxWindowInfo type and optional windowList field on MuxSessionInfo
  • Adds switch-window client command to switch directly to a specific window within a session
  • Windows are only displayed when a session has more than one tab

Changes

Contract (packages/mux/contract):

  • New MuxWindowInfo interface (id, index, name, active, paneCount)
  • MuxSessionInfo.windowList optional field

TmuxProvider (packages/mux/providers/tmux):

  • Batch-fetches all windows via listWindows() and groups by session name
  • Populates windowList in listSessions()

Runtime (packages/runtime):

  • SessionData.windowList field piped through computeState()
  • switch-window command handler in the server

TUI (apps/tui):

  • SessionCard renders window rows (with active indicator) when windowList.length > 1
  • Clicking a window row sends switch-window command

Test plan

  • bun test - 349 tests pass
  • bun run build - builds successfully
  • Manual: open sidebar with multi-window session, verify windows shown
  • Manual: click a window row, verify it switches to that window

Add window/tab enumeration to the session data model so the sidebar
shows individual windows when a session has more than one tab.

Changes across all layers:
- Contract: add MuxWindowInfo type, optional windowList on MuxSessionInfo
- TmuxProvider: batch-fetch all windows and group by session
- Runtime: pipe windowList through SessionData and computeState
- Server: handle new switch-window client command
- TUI: render clickable window rows under sessions with multiple tabs
Copy link
Copy Markdown

@inspect-review inspect-review Bot left a comment

Choose a reason for hiding this comment

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

inspect review

Triage: 10 entities analyzed | 0 critical, 0 high, 9 medium, 1 low
Verdict: standard_review

Findings (2)

  1. [low] Server-side switch-window is hard-coded to tmux and ignores the resolved provider abstraction. In packages/runtime/src/server/index.ts the handler resolves const p = sessionProviders.get(cmd.sessionName) ?? mux; and calls p.switchSession(...), but then unconditionally runs Bun.spawnSync(["tmux", "select-window", "-t", ${cmd.sessionName}:${cmd.windowIndex}], ...). This will be incorrect/broken for non-tmux providers and breaks the provider-agnostic command semantics.
  2. [low] Server switch-window swallows/ignores failures but still updates and broadcasts focus/current session state as if the switch succeeded. The code wraps Bun.spawnSync(...) in try { ... } catch {} but spawnSync typically does not throw on non-zero exit; failures are ignored, yet focusedSession, cachedCurrentSession, and cachedCurrentSessionTs are updated and broadcastFocusOnly() is called. This can leave clients believing the window switched when it did not.

Reviewed by inspect | Entity-level triage found 0 high-risk changes

@Palanikannan1437
Copy link
Copy Markdown
Contributor

hey @shunkakinoki, would you mind sharing a screenshot of how this looks?

@shunkakinoki
Copy link
Copy Markdown
Author

shunkakinoki commented Apr 13, 2026

Hey @Palanikannan1437! Here's how the window list looks:

primary session (4 windows): 0:btop, 1:dotfiles, 2:dotfiles, 3:tui
work session (3 windows): 0:editor, 1:shell, 2:work

The active window has a indicator in green. Clicking a window row sends a switch-window command to jump directly to that tab.

Windows only appear when a session has >1 tab — single-window sessions are unchanged.

opensessions-window-list

Map agent paneId to windowId so each window row displays the agent
status icon (spinner, checkmark, error, etc.) for agents running in
that specific window. Makes it easy to identify which tab has an
active agent at a glance.

- Build paneId->windowId map in computeState via tmux list-panes
- Enrich WindowData with agentStatus and agentName fields
- Render agent status icons on window rows in the TUI
Copy link
Copy Markdown

@inspect-review inspect-review Bot left a comment

Choose a reason for hiding this comment

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

inspect review

Triage: 24 entities analyzed | 0 critical, 0 high, 23 medium, 1 low
Verdict: standard_review

Findings (1)

  1. [low] Agent-to-window association is hard-coded to tmux for all sessions/providers: server/index.ts unconditionally builds paneToWindow via shell(["tmux","list-panes", ...]) and then uses it for every session when enriching windowList (paneToWindow.get(a.paneId) === w.id). For non-tmux providers (or environments without tmux), this mapping will be empty/wrong, so agentStatus/agentName on windows will be missing/incorrect.

Reviewed by inspect | Entity-level triage found 0 high-risk changes

Copy link
Copy Markdown

@inspect-review inspect-review Bot left a comment

Choose a reason for hiding this comment

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

inspect review

Triage: 24 entities analyzed | 0 critical, 0 high, 23 medium, 1 low
Verdict: standard_review

Findings (2)

  1. [low] Server-side switch-window is tmux-specific and ignores the resolved mux provider for window selection. In packages/runtime/src/server/index.ts, case "switch-window" calls const p = sessionProviders.get(cmd.sessionName) ?? mux; p.switchSession(cmd.sessionName, tty); but then always runs Bun.spawnSync(["tmux", "select-window", "-t", ${cmd.sessionName}:${cmd.windowIndex}]). This will fail/no-op or select the wrong window when the session provider is not tmux.
  2. [low] switch-window resolves a client tty but does not use it for the tmux select-window call, so with multiple tmux clients attached it may select the window in the wrong client. Evidence: const tty = ... is computed, passed to p.switchSession(...), but Bun.spawnSync(["tmux","select-window",...]) does not include any -c/client targeting using tty.

Reviewed by inspect | Entity-level triage found 0 high-risk changes

The tracker's applyPanePresence overwrites paneId when multiple panes
run the same agent, so only the last pane wins. Instead, build the
windowId-to-agent mapping directly in computeState by scanning the
process tree per-pane and grouping by window.
Copy link
Copy Markdown

@inspect-review inspect-review Bot left a comment

Choose a reason for hiding this comment

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

inspect review

Triage: 21 entities analyzed | 0 critical, 0 high, 20 medium, 1 low
Verdict: standard_review

Findings (1)

  1. [low] STATUS_PRIORITY is referenced before it is defined in packages/runtime/src/server/index.ts. The windowAgentMap builder uses STATUS_PRIORITY[status] inside the orderedMuxSessions.map(...) block added around line ~525, but const STATUS_PRIORITY: Record<string, number> = { ... } is declared later in the same function around line ~1055. Since const is not hoisted, this will throw a ReferenceError at runtime when that code path executes.
    Evidence:
  • Use: if (!existing || STATUS_PRIORITY[status] > STATUS_PRIORITY[existing.status]) { ... } inside the new windowAgentMap scan block.
  • Definition later: const STATUS_PRIORITY: Record<string, number> = { ... } added at ~1100.

Reviewed by inspect | Entity-level triage found 0 high-risk changes

@Palanikannan1437
Copy link
Copy Markdown
Contributor

Palanikannan1437 commented Apr 15, 2026

i'm not sure about this ui, seems up a bit too much for me, i think we could keep this toggleable via some shortcut, show windows, with the default as off...what do you think?

@Palanikannan1437
Copy link
Copy Markdown
Contributor

@eduwass is this something you wanted, I remember from one of the issues you opened a long time ago

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